diff -u --recursive --new-file v2.4.4/linux/CREDITS linux/CREDITS
--- v2.4.4/linux/CREDITS	Fri Apr 20 16:23:12 2001
+++ linux/CREDITS	Tue May 22 19:54:04 2001
@@ -221,6 +221,14 @@
 S: 62-300 Wrzesnia
 S: Poland
 
+N: Fred Barnes
+E: frmb2@ukc.ac.uk
+D: Various parport/ppdev hacks and fixes
+S: Computing Lab, The University
+S: Canterbury, KENT
+S: CT2 7NF
+S: England
+
 N: Paul Barton-Davis
 E: pbd@op.net
 D: Driver for WaveFront soundcards (Turtle Beach Maui, Tropez, Tropez+)
@@ -1111,8 +1119,10 @@
 S: Germany
 
 N: Christoph Hellwig
-E: chhellwig@gmx.net
-D: Sound/OSS hacking
+E: hch@caldera.de
+E: hch@infradead.org
+D: misc driver & makefile hacking
+D: freevxfs driver
 S: Triftstraße 26
 S: 38644 Goslar
 S: Germany
@@ -1663,6 +1673,7 @@
 N: Jamie Lokier
 E: jamie@imbolc.ucc.ie
 D: Reboot-through-BIOS for broken 486 motherboards
+D: Some parport fixes
 S: 11 Goodson Walk
 S: Marston
 S: Oxford
@@ -1869,10 +1880,13 @@
 
 N: Arnaldo Carvalho de Melo
 E: acme@conectiva.com.br
-W: http://www.conectiva.com.br/~acme
+E: acme@gnu.org
+W: http://bazar.conectiva.com.br/~acme
+W: http://advogato.org/person/acme
+P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
 D: wanrouter hacking
-D: USB hacking
-D: miscellaneous Makefile & Config.in fixes
+D: misc Makefile, Config.in, drivers and network stacks fixes
+D: IPX Maintainer
 D: Cyclom 2X synchronous card driver
 D: i18n for minicom, net-tools, util-linux, fetchmail, etc
 S: Conectiva S.A.
@@ -2880,7 +2894,7 @@
 S: USA
 
 N: Tim Waugh
-E: tim@cyberelk.demon.co.uk
+E: tim@cyberelk.net
 D: Co-architect of the parallel-port sharing system
 S: 17 Curling Vale
 S: GUILDFORD
@@ -3011,8 +3025,8 @@
 E: jwoithe@physics.adelaide.edu.au
 W: http://www.physics.adelaide.edu.au/~jwoithe
 D: ALS-007 sound card extensions to Sound Blaster driver
-S: 4/36 Trevelyan St
-S: Wayville SA 5034
+S: 20 Jordan St
+S: Valley View, SA 5093
 S: Australia
 
 N: Clifford Wolf
diff -u --recursive --new-file v2.4.4/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.4/linux/Documentation/Changes	Wed Apr 11 19:02:27 2001
+++ linux/Documentation/Changes	Sat May 19 17:43:05 2001
@@ -31,7 +31,7 @@
 Eine deutsche Version dieser Datei finden Sie unter
 <http://www.stefan-winter.de/Changes-2.4.0.txt>.
 
-Last updated: April 6, 2001
+Last updated: May 9, 2001
 
 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
@@ -71,7 +71,7 @@
 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.2
+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
 almost certainly bugs (mainly, but not exclusively, in the kernel) that
@@ -83,9 +83,9 @@
 be compiled with it.
 
 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
+greater than -O2 may not be wise.  Similarly, if you choose to use gcc-2.95.x
 or derivatives, be sure not to use -fstrict-aliasing (which, depending on
-your version of gcc 2.95, may necessitate using -fno-strict-aliasing).
+your version of gcc 2.95.x, may necessitate using -fno-strict-aliasing).
 
 Make
 ----
@@ -268,15 +268,15 @@
 ------------------------
 o  <ftp://sourceware.cygnus.com/pub/gcc/releases/egcs-1.1.2/egcs-1.1.2.tar.bz2>
 
-gcc 2.95.2
+gcc 2.95.3
 ----------
-o  <ftp://ftp.gnu.org/pub/gnu/gcc/gcc-2.95.2.tar.gz>
+o  <ftp://ftp.gnu.org/pub/gnu/gcc/gcc-2.95.3.tar.gz>
 
 Gnu Make
 ********
 
 Make 3.77
---------
+---------
 o  <ftp://ftp.gnu.org/gnu/make/make-3.77.tar.gz>
 
 Binutils
diff -u --recursive --new-file v2.4.4/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.4/linux/Documentation/Configure.help	Fri Apr 20 16:23:12 2001
+++ linux/Documentation/Configure.help	Thu May 24 15:03:06 2001
@@ -4170,22 +4170,6 @@
 
   It is safe to say N here for now.
 
-IPv6: enable EUI-64 token format
-CONFIG_IPV6_EUI64
-  6bone, the network of computers using the IPv6 protocol, is moving
-  to a new aggregatable address format and a new link local address
-  assignment (EUI-64). Say Y if your site has upgraded already, or
-  has started to upgrade.
-
-IPv6: disable provider based addresses
-CONFIG_IPV6_NO_PB
-  Linux tries to operate correctly when your site has moved to EUI-64
-  only partially. Unfortunately, the two address formats (old:
-  "provider based" and new: "aggregatable") are incompatible. Say Y if
-  your site finished the upgrade to EUI-64, and/or you encountered
-  some problems caused by the presence of two link-local addresses on
-  an interface.
-
 IPv6: routing messages via old netlink
 CONFIG_IPV6_NETLINK
   You can say Y here to receive routing messages from the IPv6 code
@@ -5635,7 +5619,7 @@
   Default: 253
 
 Initial Bus Reset Settle Delay
-CONFIG_AIC7XXX_RESET_DELAY
+CONFIG_AIC7XXX_RESET_DELAY_MS
   The number of milliseconds to delay after an initial bus reset.
   The bus settle delay following all error recovery actions is
   dictated by the SCSI layer and is not affected by this value.
@@ -7188,7 +7172,7 @@
 
   This driver requires a specially patched pppd daemon.  The patch to
   pppd, along with binaries of a patched pppd package can be found at:
-  http://www.math.uwaterloo.ca/~mostrows
+  http://www.shoshin.uwaterloo.ca/~mostrows
  
 Wireless LAN (non-hamradio)
 CONFIG_NET_RADIO
@@ -10933,6 +10917,35 @@
   The module will be called ov511.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+Philips webcam support
+CONFIG_USB_PWC
+  Say Y or M here if you want to use one of these Philips USB webcams:
+  PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or 
+  the Askey VC010. The PCA635, PCVC665 and PCVC720 are not 
+  supported by this driver and never will be.
+
+  This driver has an optional plugin, which is distributed as a 
+  binary module only. It contains code that allow you to use 
+  higher resolutions and framerates but may not be distributed
+  as source. But even without this plugin you can these cams 
+  for most applications.
+
+  See Documentation/usb/philips.txt for more information and 
+  installation instructions.
+
+  The built-in microphone is enabled by selecting USB Audio support.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Character Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+
+  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 pwc.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+
 USB ADMtek Pegasus-based ethernet device support
 CONFIG_USB_PEGASUS
   Say Y if you want to use your USB ethernet device. Supported
@@ -11489,6 +11502,16 @@
   (the one containing the directory /) cannot be a module, so saying M
   could be dangerous. If unsure, say N.
 
+PReP residual data support
+CONFIG_PREP_RESIDUAL
+  Some PReP systems have residual data passed to the kernel by the
+  firmware.  This allows detection of memory size, devices present and
+  other useful pieces of information.  Sometimes this information is not
+  present or incorrect.
+
+  Unless you expect to boot on a PReP system, there is not need to select
+  yes.
+
 /proc file system support
 CONFIG_PROC_FS
   This is a virtual file system providing information about the status
@@ -11657,6 +11680,23 @@
   The module is called hpfs.o. If you want to compile it as a module,
   say M here and read Documentation/modules.txt. If unsure, say N.
 
+FreeVxFS file system support (VERITAS VxFS(TM) compatible)
+CONFIG_VXFS_FS
+  FreeVxFS is a filesystem driver that support the VERITAS VxFS(TM)
+  filesystem format.  VERITAS VxFS(TM) is the standard filesystem
+  of SCO UnixWare (and possibly others) and optionally available
+  for Sunsoft Solaris, HP-UX and many other operating systems.
+  Currently only readonly access is supported.
+
+  NOTE:	the filesystem type as used by mount(1), mount(2) and fstab(5)
+	is 'vxfs' as it describes the filesystem format, not the
+	actual driver.
+
+  This file system is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module is called freevxfs.o. If you want to compile it as a module,
+  say M here and read Documentation/modules.txt. If unsure, say N.
+
 NTFS support (read only)
 CONFIG_NTFS_FS
   NTFS is the file system of Microsoft Windows NT. Say Y if you want
@@ -12081,10 +12121,7 @@
   The nls settings can be changed at mount time, if your smbmount
   supports that, using the codepage and iocharset parameters.
 
-  Currently no smbmount distributed with samba supports this, it is
-  assumed future versions will. In the meantime you can get an
-  unofficial patch for samba 2.0.7 from:
-  http://www.hojdpunkten.ac.se/054/samba/index.html
+  smbmount from samba 2.2.0 or later supports this.
 
 nls support setting
 CONFIG_SMB_NLS_REMOTE
@@ -12096,10 +12133,7 @@
   The nls settings can be changed at mount time, if your smbmount
   supports that, using the codepage and iocharset parameters.
 
-  Currently no smbmount distributed with samba supports this, it is
-  assumed future versions will. In the meantime you can get an
-  unofficial patch for samba 2.0.7 from:
-  http://www.hojdpunkten.ac.se/054/samba/index.html
+  smbmount from samba 2.2.0 or later supports this.
 
 Coda file system support (advanced network fs)
 CONFIG_CODA_FS
@@ -13204,6 +13238,14 @@
   say M here and read Documentation/modules.txt. The module will be
   called msbusmouse.o. 
 
+Apple Desktop Bus support
+CONFIG_ADB
+  Apple Desktop Bus (ADB) support is for support of devices which
+  are connected to the to an ADB port.  ADB devices tend to have
+  4 pins.  If you have an Apple Macintosh prior to the iMac, or a
+  "Blue and White G3", you probably want to say Y here.  Otherwise
+  say N.
+
 Apple Desktop Bus mouse support
 CONFIG_ADBMOUSE
   Say Y here if you have this type of bus mouse (4 pin connector) as
@@ -16249,22 +16291,45 @@
 Processor Type
 CONFIG_6xx
   There are four types of PowerPC chips supported. The more common
-  types (601, 603, 604, 740, 750), the Motorola embedded versions
-  (821, 823, 850, 855, 860), the IBM embedded versions (403 and
+  types (601, 603, 604, 740, 750, 7400), the Motorola embedded versions
+  (821, 823, 850, 855, 860, 8260), the IBM embedded versions (403 and
   405) and the high end 64 bit Power processors (Power 3, Power 4).
-  Unless you are building a kernel for one of the embedded
-  processor systems, or a 64 bit IBM RS/6000, choose 6xx.  Note that
-  the kernel runs in 32-bit mode even on 64-bit chips.
+  Unless you are building a kernel for one of the embedded processor 
+  systems, or a 64 bit IBM RS/6000, choose 6xx.  Note that the kernel 
+  runs in 32-bit mode even on 64-bit chips.  Also note that because
+  the 82xx family has a 603e core, specific support for that chipset
+  is asked later on.
+
+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.
+
+   If in doubt, say N.
+
+Workarounds for PPC601 bugs
+CONFIG_PPC601_SYNC_FIX
+  Some versions of the PPC601 (the first PowerPC chip) have bugs which
+  mean that extra synchronization instructions are required near certain
+  instructions, typically those that make major changes to the CPU state.
+  These extra instructions reduce performance slightly.  If you say N
+  here, these extra instructions will not be included, resulting in a
+  kernel which will run faster but may not run at all on some systems
+  with the PPC601 chip.
+
+  If in doubt, say Y here.
 
 Machine Type
-CONFIG_PMAC
+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, Amiga Power-Up systems (APUS), CHRP and the
-  embedded MBX boards from Motorola. Currently, a single kernel binary
-  only supports one type or the other. However, there is very early
-  work on support for CHRP, PReP and PowerMac's from a single binary.
+  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.
 
 Power management support for PowerBooks
 CONFIG_PMAC_PBOOK
@@ -16324,6 +16389,37 @@
   an image of the device tree that the kernel copies from Open
   Firmware. If unsure, say Y here.
 
+RTAS proc interface
+CONFIG_PPC_RTAS
+  When you use this option, you will be able to use RTAS from
+  userspace. 
+  
+  RTAS stands for RunTime Abstraction Services and should
+  provide a portable way to access and set system information. This is
+  commonly used on RS/6000 (pSeries) computers. 
+  
+  You can access RTAS via the special proc filesystem entry rtas.
+  Don't confuse this rtas entry with the one in /proc/device-tree/rtas
+  which is readonly.
+  
+  If you don't know if you can use RTAS look into
+  /proc/device-tree/rtas. If there are some entries, it is very likely
+  that you will be able to use RTAS.
+
+  You can do cool things with rtas. To print out information about
+  various sensors in the system, just do a 
+
+    $ cat /proc/rtas/sensors 
+
+  or if you power off your machine at night but want it running when
+  you enter your office at 7:45 am, do a
+
+    # date -d 'tomorrow 7:30' +%s > /proc/rtas/poweron
+
+  and shutdown.
+
+  If unsure, say Y
+
 MESH (Power Mac internal SCSI) support
 CONFIG_SCSI_MESH
   Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
@@ -16367,6 +16463,16 @@
   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.
+
+Use AAUI port instead of TP by default
+CONFIG_MACE_AAUI_PORT
+  Some Apple machines (notably the Apple Network Server) which use the
+  MACE ethernet chip have an Apple AUI port (small 15-pin connector),
+  instead of an 8-pin RJ45 connector for twisted-pair ethernet.  Say
+  Y here if you have such a machine.  If unsure, say N.
+  The driver will default to AAUI on ANS anyway, and if you use it as
+  a module, you can provide the port_aaui=0|1 to force the driver
+  setting.
 
 BMAC (G3 ethernet) support
 CONFIG_BMAC
diff -u --recursive --new-file v2.4.4/linux/Documentation/DMA-mapping.txt linux/Documentation/DMA-mapping.txt
--- v2.4.4/linux/Documentation/DMA-mapping.txt	Thu Apr 19 08:38:48 2001
+++ linux/Documentation/DMA-mapping.txt	Sat May 19 17:43:05 2001
@@ -240,6 +240,7 @@
 
 where dev, size are the same as in the above call and cpu_addr and
 dma_handle are the values pci_alloc_consistent returned to you.
+This function may not be called in interrupt context.
 
 If your driver needs lots of smaller memory regions, you can write
 custom code to subdivide pages returned by pci_alloc_consistent,
@@ -262,7 +263,8 @@
 sleeping context (f.e. in_interrupt is true or while holding SMP
 locks), pass SLAB_ATOMIC.  If your device has no boundary crossing
 restrictions, pass 0 for alloc; passing 4096 says memory allocated
-from this pool must not cross 4KByte boundaries.
+from this pool must not cross 4KByte boundaries (but at that time it
+may be better to go for pci_alloc_consistent directly instead).
 
 Allocate memory from a pci pool like this:
 
@@ -270,21 +272,23 @@
 
 flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
 holding SMP locks), SLAB_ATOMIC otherwise.  Like pci_alloc_consistent,
-this returns two values, cpu_addr and dma_handle,
+this returns two values, cpu_addr and dma_handle.
 
 Free memory that was allocated from a pci_pool like this:
 
 	pci_pool_free(pool, cpu_addr, dma_handle);
 
 where pool is what you passed to pci_pool_alloc, and cpu_addr and
-dma_handle are the values pci_pool_alloc returned.
+dma_handle are the values pci_pool_alloc returned. This function
+may be called in interrupt context.
 
 Destroy a pci_pool by calling:
 
 	pci_pool_destroy(pool);
 
 Make sure you've called pci_pool_free for all memory allocated
-from a pool before you destroy the pool.
+from a pool before you destroy the pool. This function may not
+be called in interrupt context.
 
 			DMA Direction
 
diff -u --recursive --new-file v2.4.4/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.4.4/linux/Documentation/DocBook/Makefile	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/DocBook/Makefile	Mon May  7 12:14:56 2001
@@ -95,6 +95,7 @@
 		$(TOPDIR)/kernel/pm.c \
 		$(TOPDIR)/kernel/ksyms.c \
 		$(TOPDIR)/kernel/kmod.c \
+		$(TOPDIR)/kernel/module.c \
 		$(TOPDIR)/kernel/printk.c \
 		$(TOPDIR)/kernel/sched.c \
 		$(TOPDIR)/kernel/sysctl.c \
diff -u --recursive --new-file v2.4.4/linux/Documentation/DocBook/deviceiobook.tmpl linux/Documentation/DocBook/deviceiobook.tmpl
--- v2.4.4/linux/Documentation/DocBook/deviceiobook.tmpl	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/DocBook/deviceiobook.tmpl	Tue May  1 14:20:25 2001
@@ -171,7 +171,7 @@
 	with 'isa_' and are <function>isa_readb</function>,
 	<function>isa_writeb</function>, <function>isa_readw</function>, 
 	<function>isa_writew</function>, <function>isa_readl</function>,
-	<function>isa_writel</function), <function>isa_memcpy_fromio</function>
+	<function>isa_writel</function>, <function>isa_memcpy_fromio</function>
 	and <function>isa_memcpy_toio</function>
       </para>
       <para>
diff -u --recursive --new-file v2.4.4/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl
--- v2.4.4/linux/Documentation/DocBook/kernel-api.tmpl	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/DocBook/kernel-api.tmpl	Thu May 24 15:14:08 2001
@@ -41,8 +41,9 @@
 !Iinclude/linux/init.h
      </sect1>
 
-     <sect1><title>Atomics</title>
+     <sect1><title>Atomic and pointer manipulation</title>
 !Iinclude/asm-i386/atomic.h
+!Iinclude/asm-i386/unaligned.h
      </sect1>
 
      <sect1><title>Delaying, scheduling, and timer routines</title>
@@ -140,8 +141,13 @@
   </chapter>
 
   <chapter id="modload">
-     <title>Module Loading</title>
+     <title>Module Support</title>
+     <sect1><title>Module Loading</title>
 !Ekernel/kmod.c
+     </sect1>
+     <sect1><title>Inter Module support</title>
+!Ekernel/module.c
+     </sect1>
   </chapter>
 
   <chapter id="hardware">
diff -u --recursive --new-file v2.4.4/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl
--- v2.4.4/linux/Documentation/DocBook/kernel-hacking.tmpl	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/DocBook/kernel-hacking.tmpl	Sat May 19 17:43:05 2001
@@ -713,7 +713,8 @@
    </para>
    <para>
    Static data structures marked as <type>__initdata</type> must be initialised
-   (as opposed to ordinary static data which is zeroed BSS).
+   (as opposed to ordinary static data which is zeroed BSS) and cannot be 
+   <type>const</type>.
    </para> 
 
   </sect1>
diff -u --recursive --new-file v2.4.4/linux/Documentation/DocBook/kernel-locking.tmpl linux/Documentation/DocBook/kernel-locking.tmpl
--- v2.4.4/linux/Documentation/DocBook/kernel-locking.tmpl	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/DocBook/kernel-locking.tmpl	Sat May 19 17:43:05 2001
@@ -760,8 +760,11 @@
     </para>
 
     <para>
-      Any atomic operation is defined to act as a memory barrier
-      (ie. as per the <function>mb()</function> macro).  Also,
+      Some atomic operations are defined to act as a memory barrier
+      (ie. as per the <function>mb()</function> macro, but if in
+      doubt, be explicit.
+      <!-- Rusty Russell 2 May 2001, 2.4.4 -->
+      Also,
       spinlock operations act as partial barriers: operations after
       gaining a spinlock will never be moved to precede the
       <function>spin_lock()</function> call, and operations before
diff -u --recursive --new-file v2.4.4/linux/Documentation/cris/README linux/Documentation/cris/README
--- v2.4.4/linux/Documentation/cris/README	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/cris/README	Tue May  1 16:04:56 2001
@@ -1,13 +1,19 @@
 Linux 2.4 on the CRIS architecture
 ==================================
-$Id: README,v 1.6 2001/02/21 15:27:25 bjornw Exp $
+$Id: README,v 1.7 2001/04/19 12:38:32 bjornw Exp $
 
 This is a port of Linux 2.4 to Axis Communications ETRAX 100LX embedded 
 network CPU. For more information about CRIS and ETRAX please see further
 below.
 
-<to come: instructions on how to grab the right gcc, compiling and booting>
+In order to compile this you need a version of gcc with support for the
+ETRAX chip family. Please see this link for more information on how to 
+download the compiler and other tools useful when building and booting
+software for the ETRAX platform:
 
+http://developer.axis.com/doc/software/devboard_lx/install-howto.html
+
+<more specific information should come in this document later>
 
 What is CRIS ?
 --------------
@@ -97,7 +103,7 @@
 ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000 Axis Communications AB
 eth0 initialized
 eth0: changed MAC to 00:40:8C:CD:00:00
-ETRAX 100LX serial-driver $Revision: 1.6 $, (c) 2000 Axis Communications AB
+ETRAX 100LX serial-driver $Revision: 1.7 $, (c) 2000 Axis Communications AB
 ttyS0 at 0xb0000060 is a builtin UART with DMA
 ttyS1 at 0xb0000068 is a builtin UART with DMA
 ttyS2 at 0xb0000070 is a builtin UART with DMA
@@ -127,7 +133,7 @@
 Hostname is bbox1
 Telnetd starting, using port 23.
   using /bin/sash as shell.
-sftpd[15]: sftpd $Revision: 1.6 $ starting up
+sftpd[15]: sftpd $Revision: 1.7 $ starting up
 
 
 
diff -u --recursive --new-file v2.4.4/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.4.4/linux/Documentation/devices.txt	Sat Dec 30 11:26:10 2000
+++ linux/Documentation/devices.txt	Sat May 19 17:43:05 2001
@@ -660,6 +660,12 @@
 
  29 char	Universal frame buffer
 		  0 = /dev/fb0		First frame buffer
+		  1 = /dev/fb1		Second frame buffer
+		    ...
+		 31 = /dev/fb31		32nd frame buffer
+
+		Backward compatibility aliases {2.6}
+
 		 32 = /dev/fb1		Second frame buffer
 		    ...
 		224 = /dev/fb7		Eighth frame buffer
@@ -765,7 +771,7 @@
  36 char	Netlink support
 		  0 = /dev/route	Routing, device updates, kernel to user
 		  1 = /dev/skip		enSKIP security cache control
-		  3 = /dec/fwmonitor	Firewall packet copies
+		  3 = /dev/fwmonitor	Firewall packet copies
 		 16 = /dev/tap0		First Ethertap device
 		    ...
 		 31 = /dev/tap15	16th Ethertap device
@@ -2436,7 +2442,7 @@
 
 224 char	A2232 serial card
 		  0 = /dev/ttyY0		First A2232 port
-		  1 = /dev/cuy0			Second A2232 port
+		  1 = /dev/ttyY1		Second A2232 port
 		    ...
 
 225 char	A2232 serial card (alternate devices)
diff -u --recursive --new-file v2.4.4/linux/Documentation/fb/framebuffer.txt linux/Documentation/fb/framebuffer.txt
--- v2.4.4/linux/Documentation/fb/framebuffer.txt	Sat Jul  8 19:44:07 2000
+++ linux/Documentation/fb/framebuffer.txt	Thu May 24 15:14:08 2001
@@ -2,7 +2,7 @@
 			-----------------------
 
 Maintained by Geert Uytterhoeven <geert@linux-m68k.org>
-Last revised: January 2, 2000
+Last revised: May 10, 2001
 
 
 0. Introduction
@@ -296,7 +296,7 @@
 For more specific information about the frame buffer device and its
 applications, please refer to the Linux-fbdev website:
 
-    http://www.linux-fbdev.org/
+    http://linux-fbdev.sourceforge.net/
 
 and to the following documentation:
 
@@ -312,13 +312,13 @@
 8. Mailing list
 ---------------
 
-There's a _development_ mailing list at linux-fbdev@vuser.vu.union.edu,
-controlled by majordomo. Send an email with `help' in the message body to
-majordomo@vuser.vu.union.edu for subscription information.
+There are several frame buffer device related mailing lists at SourceForge:
+  - linux-fbdev-announce@lists.sourceforge.net, for announcements,
+  - linux-fbdev-user@lists.sourceforge.net, for generic user support,
+  - linux-fbdev-devel@lists.sourceforge.net, for project developers.
 
-The mailing list is archived at
-
-    http://www.mail-archive.com/linux-fbdev@vuser.vu.union.edu/
+Point your web browser to http://sourceforge.net/projects/linux-fbdev/ for
+subscription information and archive browsing.
 
 
 9. Downloading
diff -u --recursive --new-file v2.4.4/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- v2.4.4/linux/Documentation/ioctl-number.txt	Fri Mar  2 17:50:22 2001
+++ linux/Documentation/ioctl-number.txt	Sat May 19 17:54:14 2001
@@ -139,7 +139,7 @@
 'p'	00-3F	linux/mc146818rtc.h
 'p'	40-7F	linux/nvram.h
 'p'	80-9F				user-space parport
-					<mailto:tim@cyberelk.demon.co.uk>
+					<mailto:tim@cyberelk.net>
 'q'	00-1F	linux/videotext.h	conflict!
 'q'	80-FF				Internet PhoneJACK, Internet LineJACK
 					<http://www.quicknet.net>
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- v2.4.4/linux/Documentation/networking/8139too.txt	Thu Apr 19 09:32:48 2001
+++ linux/Documentation/networking/8139too.txt	Mon May  7 14:13:19 2001
@@ -185,6 +185,13 @@
 Change History
 --------------
 
+Version 0.9.17 - May 7, 2001
+
+* Fix chipset wakeup bug which prevent media connection for 8139B
+* Print out "media is unconnected..." instead of 
+  "partner ability 0000"
+
+
 Version 0.9.16 - April 14, 2001
 
 * Complete MMIO audit, disable read-after-every-write
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/cops.txt linux/Documentation/networking/cops.txt
--- v2.4.4/linux/Documentation/networking/cops.txt	Thu Jan  6 14:46:18 2000
+++ linux/Documentation/networking/cops.txt	Wed May 16 10:31:27 2001
@@ -1,5 +1,5 @@
 Text File for the COPS LocalTalk Linux driver (cops.c).
-	By Jay Schulist <jschlst@turbolinux.com>
+	By Jay Schulist <jschlst@samba.org>
 
 This driver has two modes and they are: Dayna mode and Tangent mode.
 Each mode corresponds with the type of card. It has been found
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/ethertap.txt linux/Documentation/networking/ethertap.txt
--- v2.4.4/linux/Documentation/networking/ethertap.txt	Wed Aug 23 09:30:13 2000
+++ linux/Documentation/networking/ethertap.txt	Wed May 16 10:31:27 2001
@@ -7,7 +7,7 @@
 Ethertap programming mini-HOWTO
 -------------------------------
 
-The ethertap driver was written by Jay Schulist <jschlst@turbolinux.com>,
+The ethertap driver was written by Jay Schulist <jschlst@samba.org>,
 you should contact him for further information. This document was written by
 bert hubert <bert.hubert@netherlabs.nl>. Updates are welcome.
 
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/filter.txt linux/Documentation/networking/filter.txt
--- v2.4.4/linux/Documentation/networking/filter.txt	Thu Jan  6 14:46:18 2000
+++ linux/Documentation/networking/filter.txt	Wed May 16 10:31:27 2001
@@ -1,5 +1,5 @@
 filter.txt: Linux Socket Filtering
-Written by: Jay Schulist <jschlst@turbolinux.com>
+Written by: Jay Schulist <jschlst@samba.org>
 
 Introduction
 ============
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.4.4/linux/Documentation/networking/ip-sysctl.txt	Sun Mar 25 18:14:21 2001
+++ linux/Documentation/networking/ip-sysctl.txt	Wed May 16 10:21:45 2001
@@ -398,4 +398,117 @@
 Updated by:
 Andi Kleen
 ak@muc.de
-$Id: ip-sysctl.txt,v 1.18 2001/03/16 06:49:20 davem Exp $
+
+
+
+
+
+
+/proc/sys/net/ipv6/* Variables:
+
+IPv6 has no global variables such as tcp_*.  tcp_* settings under ipv4/ also
+apply to IPv6 [XXX?].
+
+conf/default/*:
+	Change the interface-specific default settings.
+
+
+conf/all/*:
+	Change all the interface-specific settings.  
+
+	[XXX:  Other special features than forwarding?]
+
+conf/all/forwarding - BOOLEAN
+	Enable global IPv6 forwarding between all interfaces.  
+
+	IPv4 and IPv6 work differently here; e.g. netfilter must be used 
+	to control which interfaces may forward packets and which not.
+
+	This also sets all interfaces' Host/Router setting 
+	'forwarding' to the specified value.  See below for details.
+
+	This referred to as global forwarding.
+
+conf/interface/*:
+	Change special settings per interface.
+
+	The functional behaviour for certain settings is different 
+	depending on whether local forwarding is enabled or not.
+
+accept_ra - BOOLEAN
+	Accept Router Advertisements; autoconfigure using them.
+	
+	Functional default: enabled if local forwarding is disabled.
+			    disabled if local forwarding is enabled.
+
+accept_redirects - BOOLEAN
+	Accept Redirects.
+
+	Functional default: enabled if local forwarding is disabled.
+			    disabled if local forwarding is enabled.
+
+autoconf - BOOLEAN
+	Configure link-local addresses using L2 hardware addresses.
+
+	Default: TRUE
+
+dad_transmits - INTEGER
+	The amount of Duplicate Address Detection probes to send.
+	Default: 1
+	
+forwarding - BOOLEAN
+	Configure interface-specific Host/Router behaviour.  
+
+	Note: It is recommended to have the same setting on all 
+	interfaces; mixed router/host scenarios are rather uncommon.
+
+	FALSE:
+
+	By default, Host behaviour is assumed.  This means:
+
+	1. IsRouter flag is not set in Neighbour Advertisements.
+	2. Router Solicitations are being sent when necessary.
+	3. If accept_ra is TRUE (default), accept Router 
+	   Advertisements (and do autoconfiguration).
+	4. If accept_redirects is TRUE (default), accept Redirects.
+
+	TRUE:
+
+	If local forwarding is enabled, Router behaviour is assumed. 
+	This means exactly the reverse from the above:
+
+	1. IsRouter flag is set in Neighbour Advertisements.
+	2. Router Solicitations are not sent.
+	3. Router Advertisements are ignored.
+	4. Redirects are ignored.
+
+	Default: FALSE if global forwarding is disabled (default),
+		 otherwise TRUE.
+
+hop_limit - INTEGER
+	Default Hop Limit to set.
+	Default: 64
+
+mtu - INTEGER
+	Default Maximum Transfer Unit
+	Default: 1280 (IPv6 required minimum)
+
+router_solicitation_delay - INTEGER
+	Number of seconds to wait after interface is brought up
+	before sending Router Solicitations.
+	Default: 1
+
+router_solicitation_interval - INTEGER
+	Number of seconds to wait between Router Solicitations.
+	Default: 4
+
+router_solicitations - INTEGER
+	Number of Router Solicitations to send until assuming no 
+	routers are present.
+	Default: 3
+
+IPv6 Update by:
+Pekka Savola
+pekkas@netcore.fi
+
+$Id: ip-sysctl.txt,v 1.19 2001/05/16 17:11:04 davem Exp $
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/ipddp.txt linux/Documentation/networking/ipddp.txt
--- v2.4.4/linux/Documentation/networking/ipddp.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/networking/ipddp.txt	Wed May 16 10:31:27 2001
@@ -1,7 +1,7 @@
 Text file for ipddp.c:
 	AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
 
-This text file is written by Jay Schulist <jschlst@turbolinux.com>
+This text file is written by Jay Schulist <jschlst@samba.org>
 
 Introduction
 ------------
@@ -72,7 +72,7 @@
 
 Further Assistance
 -------------------
-You can contact me (Jay Schulist <jschlst@turbolinux.com>) with any
+You can contact me (Jay Schulist <jschlst@samba.org>) with any
 questions regarding decapsulation or encapsulation. Bradford W. Johnson
 <johns393@maroon.tc.umn.edu> originally wrote the ipddp.c driver for IP
 encapsulation in AppleTalk.
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/smctr.txt linux/Documentation/networking/smctr.txt
--- v2.4.4/linux/Documentation/networking/smctr.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/networking/smctr.txt	Wed May 16 10:31:27 2001
@@ -1,5 +1,5 @@
 Text File for the SMC TokenCard TokenRing Linux driver (smctr.c).
-        By Jay Schulist <jschlst@turbolinux.com>
+        By Jay Schulist <jschlst@samba.org>
 
 The Linux SMC Token Ring driver works with the SMC TokenCard Elite (8115T) 
 ISA and SMC TokenCard Elite/A (8115T/A) MCA adapters.
@@ -22,7 +22,7 @@
 following command will suffice for most:
 
 # modprobe smctr
-smctr.c: v1.00 12/6/99 by jschlst@turbolinux.com
+smctr.c: v1.00 12/6/99 by jschlst@samba.org
 tr0: SMC TokenCard 8115T at Io 0x300, Irq 10, Rom 0xd8000, Ram 0xcc000.
 
 Now just setup the device via ifconfig and set and routes you may have. After
diff -u --recursive --new-file v2.4.4/linux/Documentation/networking/tms380tr.txt linux/Documentation/networking/tms380tr.txt
--- v2.4.4/linux/Documentation/networking/tms380tr.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/networking/tms380tr.txt	Wed May 16 10:31:27 2001
@@ -1,5 +1,5 @@
 Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
-	Text file by: Jay Schulist <jschlst@turbolinux.com>
+	Text file by: Jay Schulist <jschlst@samba.org>
 
 The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
 SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
diff -u --recursive --new-file v2.4.4/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.4.4/linux/Documentation/parport.txt	Fri Apr  6 10:42:51 2001
+++ linux/Documentation/parport.txt	Sat May 19 17:54:14 2001
@@ -261,4 +261,4 @@
     io=0x378 irq=7 dma=3 (for DMA)
 --
 Philip.Blundell@pobox.com
-tim@cyberelk.demon.co.uk
+tim@cyberelk.net
diff -u --recursive --new-file v2.4.4/linux/Documentation/pci.txt linux/Documentation/pci.txt
--- v2.4.4/linux/Documentation/pci.txt	Sun Sep 17 09:45:06 2000
+++ linux/Documentation/pci.txt	Sat May 19 17:43:05 2001
@@ -60,8 +60,8 @@
 	remove		Pointer to a function which gets called whenever a device
 			being handled by this driver is removed (either during
 			deregistration of the driver or when it's manually pulled
-			out of a hot-pluggable slot). This function can be called
-			from interrupt context.
+			out of a hot-pluggable slot). This function always gets
+			called from process context, so it can sleep.
 	suspend,	Power management hooks -- called when the device goes to
 	resume		sleep or is resumed.
 
diff -u --recursive --new-file v2.4.4/linux/Documentation/rtc.txt linux/Documentation/rtc.txt
--- v2.4.4/linux/Documentation/rtc.txt	Thu Jan  4 12:50:17 2001
+++ linux/Documentation/rtc.txt	Sat May 19 17:43:05 2001
@@ -89,7 +89,7 @@
 #include <unistd.h>
 #include <errno.h>
 
-void main(void) {
+int main(void) {
 
 int i, fd, retval, irqcount = 0;
 unsigned long tmp, data;
@@ -277,5 +277,6 @@
 								 irqcount);
 
 close(fd);
+return 0;
 
 } /* end main */
diff -u --recursive --new-file v2.4.4/linux/Documentation/s390/3270.txt linux/Documentation/s390/3270.txt
--- v2.4.4/linux/Documentation/s390/3270.txt	Thu Apr 12 12:03:50 2001
+++ linux/Documentation/s390/3270.txt	Thu May 24 15:14:08 2001
@@ -100,9 +100,9 @@
 	you will see login prompts appear on your 3270s as soon as
 	boot is complete (or with emulated 3270s, as soon as you dial
 	into your vm guest using the command "DIAL <vmguestname>").
-	Since the line-mode major number is 212, the line to add to
+	Since the line-mode major number is 227, the line to add to
 	/etc/modules.conf should be:
-		alias char-major-212 tub3270
+		alias char-major-227 tub3270
 
 	3. Define graphic devices to your vm guest machine, if you
 	haven't already.  Define them before you reboot (reipl):
@@ -175,7 +175,7 @@
 	C. Are the device special files created, as in installation
 	step 2 above?  Use the ls -l command to find out; for instance,
 	issue "ls -l /dev/3270/tty620".  The output should start with the
-	letter "c" meaning character device and should contain "212, 1"
+	letter "c" meaning character device and should contain "227, 1"
 	just to the left of the device name.  No such file?  no "c"?
 	Wrong major number?  Wrong minor number?  There's your
 	problem!
diff -u --recursive --new-file v2.4.4/linux/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt
--- v2.4.4/linux/Documentation/scsi-generic.txt	Thu Apr 12 12:03:50 2001
+++ linux/Documentation/scsi-generic.txt	Tue May  1 16:04:56 2001
@@ -238,8 +238,8 @@
 open(const char * filename, int flags)
 --------------------------------------
 The filename should be an 'sg' device such as
-/dev/sg[a-z]
 /dev/sg[0,1,2,...]
+/dev/sg[a-z]             <<< now deprecated >>>
 or a symbolic link to one of these. [Devfs has its own sub-directory for
 sg devices with entries like: /dev/scsi/host1/bus2/target3/lun4/generic .]
 It seems as though SCSI devices are allocated to sg minor numbers in the
diff -u --recursive --new-file v2.4.4/linux/Documentation/sound/MAD16 linux/Documentation/sound/MAD16
--- v2.4.4/linux/Documentation/sound/MAD16	Mon Aug 23 10:23:23 1999
+++ linux/Documentation/sound/MAD16	Tue May  1 16:05:00 2001
@@ -1,3 +1,5 @@
+(This recipe has been edited to update the configuration symbols.)
+
 From: Shaw Carruthers <shaw@shawc.demon.co.uk>
 
 I have been using mad16 sound for some time now with no problems, current
@@ -14,9 +16,9 @@
 .config has:
 
 CONFIG_SOUND=m
-CONFIG_ADLIB=m
-CONFIG_MAD16=m
-CONFIG_YM3812=m
+CONFIG_SOUND_ADLIB=m
+CONFIG_SOUND_MAD16=m
+CONFIG_SOUND_YM3812=m
 
 modules.conf has:
 
diff -u --recursive --new-file v2.4.4/linux/Documentation/sound/Opti linux/Documentation/sound/Opti
--- v2.4.4/linux/Documentation/sound/Opti	Wed Mar  8 11:37:03 2000
+++ linux/Documentation/sound/Opti	Tue May  1 16:05:00 2001
@@ -29,21 +29,21 @@
 
 Sound card support should be enabled as a module (chose m).
 Answer 'm' for  these items:
-  Generic OPL2/OPL3 FM synthesizer support			(CONFIG_ADLIB)
-  Microsoft Sound System support				(CONFIG_MSS)
-  Support for OPTi MAD16 and/or Mozart based cards	 	(CONFIG_MAD16)
-  FM synthesizer (YM3812/OPL-3) support				(CONFIG_YM3812)
+  Generic OPL2/OPL3 FM synthesizer support		(CONFIG_SOUND_ADLIB)
+  Microsoft Sound System support			(CONFIG_SOUND_MSS)
+  Support for OPTi MAD16 and/or Mozart based cards	(CONFIG_SOUND_MAD16)
+  FM synthesizer (YM3812/OPL-3) support			(CONFIG_SOUND_YM3812)
 
 The configuration menu may ask for addresses, IRQ lines or DMA
 channels. If the card is used as a module the module loading
 options will override these values.
 
 For the OPTi 931 you can answer 'n' to:
-  Support MIDI in older MAD16 based cards (requires SB)		(CONFIG_MAD16_OLDCARD)
+  Support MIDI in older MAD16 based cards (requires SB)	(CONFIG_SOUND_MAD16_OLDCARD)
 If you do need MIDI support in a Mozart or C928 based card you
 need to answer 'm' to the above question. In that case you will
 also need to answer 'm' to:
-  '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' (CONFIG_SB)
+  '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' (CONFIG_SOUND_SB)
 
 Go on and compile your kernel and modules. Install the modules. Run depmod -a.
 
diff -u --recursive --new-file v2.4.4/linux/Documentation/sound/cs46xx linux/Documentation/sound/cs46xx
--- v2.4.4/linux/Documentation/sound/cs46xx	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/cs46xx	Sat May 19 17:43:05 2001
@@ -0,0 +1,138 @@
+
+Documentation for the Cirrus Logic/Crystal SoundFusion cs46xx/cs4280 audio 
+controller chips (2001/05/11)
+
+The cs46xx audio driver supports the DSP line of Cirrus controllers. 
+Specifically, the cs4610, cs4612, cs4614, cs4622, cs4624, cs4630 and the cs4280
+products.  This driver uses the generic ac97_codec driver for AC97 codec
+support.  
+
+
+Features:
+
+Full Duplex Playback/Capture supported from 8k-48k.
+16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported.
+
+APM/PM - 2.2.x PM is enabled and functional. APM can also
+be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
+definition.
+
+DMA playback buffer size is configurable from 16k (defaultorder=2) up to 2Meg 
+(defaultorder=11).  DMA capture buffer size is fixed at a single 4k page as
+two 2k fragments.
+
+MMAP seems to work well with QuakeIII, and test XMMS plugin.
+
+Myth2 works, but the polling logic is not fully correct, but is functional.
+
+The 2.4.4-ac6 gameport code in the cs461x joystick driver has been tested 
+with a Microsoft Sidewinder joystick (cs461x.o and sidewinder.o).  This 
+audio driver must be loaded prior to the joystick driver to enable the
+DSP task image supporting the joystick device.
+
+
+Limitations:
+
+SPDIF is currently not supported.
+
+Primary codec support only.  No secondary codec support is implemented.
+
+
+
+NOTES:
+
+Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
+and has been tested.
+Module parameter hercules_egpio_disable set to 1, will force a 0 to EGPIODR
+to disable the external amplifier.
+
+VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
+the external amplifier for the "back" speakers, since we do not
+support the secondary codec then this external amp is not
+turned on.  The primary codec external amplifier is supported but
+note that the AC97 EAPD bit is inverted logic (amp_voyetra()).
+
+DMA buffer size - there are issues with many of the Linux applications
+concerning the optimal buffer size.  Several applications request a 
+certain fragment size and number and then do not verify that the driver
+has the ability to support the requested configuration.  
+SNDCTL_DSP_SETFRAGMENT ioctl is used to request a fragment size and
+number of fragments.  Some applications exit if an error is returned
+on this particular ioctl. Therefore, in alignment with the other OSS audio 
+drivers, no error is returned when a SETFRAGs IOCTL is received, but the 
+values passed from the app are not used in any buffer calculation 
+(ossfragshift/ossmaxfrags are not used).
+Use the "defaultorder=N" module parameter to change the buffer size if
+you have an application that requires a specific number of fragments
+or a specific buffer size (see below).
+
+Debug Interface
+---------------
+There is an ioctl debug interface to allow runtime modification of the 
+debug print levels.  This debug interface code can be disabled from the 
+compilation process with commenting the following define:
+#define CSDEBUG_INTERFACE 1
+There is also a debug print methodolgy to select printf statements from
+different areas of the driver.  A debug print level is also used to allow
+additional printfs to be active.  Comment out the following line in the
+driver to disable compilation of the CS_DBGOUT print statements:
+#define CSDEBUG 1
+ 
+Please see the defintions for cs_debuglevel and cs_debugmask for additional
+information on the debug levels and sections.
+
+There is also a csdbg executable to allow runtime manipulation of these 
+parameters.  for a copy email: twoller@crystal.cirrus.com
+
+
+
+MODULE_PARMS definitions
+------------------------
+MODULE_PARM(defaultorder, "i");
+defaultorder=N
+where N is a value from 1 to 12
+The buffer order determines the size of the dma buffer for the driver.
+under Linux, a smaller buffer allows more responsiveness from many of the 
+applications (e.g. games).  A larger buffer allows some of the apps (esound) 
+to not underrun the dma buffer as easily.  As default, use 32k (order=3)
+rather than 64k as some of the games work more responsively.
+(2^N) * PAGE_SIZE = allocated buffer size
+
+MODULE_PARM(cs_debuglevel, "i");
+MODULE_PARM(cs_debugmask, "i");
+cs_debuglevel=N
+cs_debugmask=0xMMMMMMMM
+where N is a value from 0 (no debug printfs), to 9 (maximum)
+0xMMMMMMMM is a debug mask corresponding to the CS_xxx bits (see driver source).
+
+MODULE_PARM(hercules_egpio_disable, "i");
+hercules_egpio_disable=N
+where N is a 0 (enable egpio), or a 1 (disable egpio support)
+
+MODULE_PARM(initdelay, "i");
+initdelay=N
+This value is used to determine the millescond delay during the initialization
+code prior to powering up the PLL.  On laptops this value can be used to
+assist with errors on resume, mostly with IBM laptops.  Basically, if the 
+system is booted under battery power then the mdelay()/udelay() functions fail to 
+properly delay the required time.  Also, if the system is booted under AC power
+and then the power removed, the mdelay()/udelay() functions will not delay properly.
+ 
+MODULE_PARM(powerdown, "i");
+powerdown=N
+where N is 0 (disable any powerdown of the internal blocks) or 1 (enable powerdown)
+
+
+MODULE_PARM(external_amp, "i");
+external_amp=1
+if N is set to 1, then force enabling the EAPD support in the primary AC97 codec.
+override the detection logic and force the external amp bit in the AC97 0x26 register
+to be reset (0).  EAPD should be 0 for powerup, and 1 for powerdown.  The VTB Santa Cruz
+card has inverted logic, so there is a special function for these cards.
+
+MODULE_PARM(thinkpad, "i");
+thinkpad=1
+if N is set to 1, then force enabling the clkrun functionality.
+Currently, when the part is being used, then clkrun is disabled for the entire system,
+but re-enabled when the driver is released or there is no outstanding open count.
+
diff -u --recursive --new-file v2.4.4/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt
--- v2.4.4/linux/Documentation/sysrq.txt	Thu Mar 22 09:20:45 2001
+++ linux/Documentation/sysrq.txt	Thu May 24 15:03:06 2001
@@ -29,7 +29,8 @@
            You send a BREAK, then within 5 seconds a command key. Sending
            BREAK twice is interpreted as a normal BREAK.
 
-On Mac   - Press 'Keypad+-F13-<command key>'
+On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,  
+             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. 
diff -u --recursive --new-file v2.4.4/linux/Documentation/usb/hotplug.txt linux/Documentation/usb/hotplug.txt
--- v2.4.4/linux/Documentation/usb/hotplug.txt	Tue Jan 16 12:02:51 2001
+++ linux/Documentation/usb/hotplug.txt	Sat May 19 17:49:14 2001
@@ -69,7 +69,10 @@
 
 If "usbdevfs" is configured, DEVICE and DEVFS are also passed.  DEVICE is
 the pathname of the device, and is useful for devices with multiple and/or
-alternate interfaces that complicate driver selection.
+alternate interfaces that complicate driver selection.  By design, USB
+hotplugging is independent of "usbdevfs":  you can do most essential parts
+of USB device setup without using that filesystem, and without running a
+user mode daemon to detect changes in system configuration.
 
 Currently available policy agent implementations can load drivers for
 modules, and can invoke driver-specific setup scripts.  The newest ones
@@ -85,14 +88,26 @@
 
 See <linux/usb.h> for full information about such table entries; or look
 at existing drivers.  Each table entry describes one or more criteria to
-be used when matching a driver to a device or class of devices.
+be used when matching a driver to a device or class of devices.  The
+specific criteria are identified by bits set in "match_flags", paired
+with field values.  You can construct the criteria directly, or with
+macros such as these, and use driver_info to store more information.
+
+    USB_DEVICE (vendorId, productId)
+	... matching devices with specified vendor and product ids
+    USB_DEVICE_VER (vendorId, productId, lo, hi)
+	... like USB_DEVICE with lo <= productversion <= hi
+    USB_INTERFACE_INFO (class, subclass, protocol)
+	... matching specified interface class info
+    USB_DEVICE_INFO (class, subclass, protocol)
+	... matching specified device class info
 
 A short example, for a driver that supports several specific USB devices
 and their quirks, might have a MODULE_DEVICE_TABLE like this:
 
     static const struct usb_device_id mydriver_id_table = {
-	{ idVendor: 0x9999, idProduct 0xaaaa, driver_info: QUIRK_X },
-	{ idVendor: 0xbbbb, idProduct 0x8888, driver_info: QUIRK_Y|QUIRK_Z },
+	{ USB_DEVICE (0x9999, 0xaaaa), driver_info: QUIRK_X },
+	{ USB_DEVICE (0xbbbb, 0x8888), driver_info: QUIRK_Y|QUIRK_Z },
 	...
 	{ } /* end with an all-zeroes entry */
     }
diff -u --recursive --new-file v2.4.4/linux/Documentation/usb/philips.txt linux/Documentation/usb/philips.txt
--- v2.4.4/linux/Documentation/usb/philips.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/usb/philips.txt	Tue May 22 10:25:36 2001
@@ -0,0 +1,141 @@
+This file contains some additional information for the Philips webcams.
+E-mail: webcam@smcc.demon.nl                        Last updated: 2001-04-25
+
+The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
+It contains a lot of extra information, a FAQ, and the binary plugin
+'PWCX'. This plugin contains decompression routines that allow you to
+use higher image sizes and framerates; in addition the webcam uses less
+bandwidth on the USB bus (handy if you want to run more than 1 camera
+simultaneously). These routines fall under an NDA, and may therefor not be
+distributed as source; however, its use is completely optional.
+
+You can build this code either into your kernel, or as a module. I recommend
+the latter, since it makes troubleshooting a lot easier. The built-in
+microphone is supported through the USB Audio class.
+
+(Taken from install.html)
+
+When you load the module you can set some default settings for the
+camera; some programs depend on a particular image-size or -format. The
+options are:
+
+size
+   Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
+   'vga', for an image size of resp. 128x96, 160x120, 176x144,
+   320x240, 352x288 and 640x480 (of course, only for those cameras that support these resolutions).
+
+fps
+   Specifies the desired framerate. Is an integer in the range of 4-30.
+
+palette
+   Specifies the desired colour order that should be delivered by read() and
+   mmap(). The string can be one of bgr24, rgb24, rgb32, bgr32, yuyv,
+   yuv420, yuv420p. If the tool you use produces odd colours (more
+   specificly, red and blue are swapped), try palette=bgr24 or
+   palette=rgb24.
+
+fbufs
+   This paramter specifies the number of internal buffers to use for storing 
+   frames from the cam. This will help if the process that reads images from 
+   the cam is a bit slow or momentarely busy. However, on slow machines it 
+   only introduces lag, so choose carefully. The default is 3, which is 
+   reasonable. You can set it between 2 and 5.
+
+mbufs
+   This is an integer between 1 and 4. It will tell the module the number of
+   buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
+   The default is 2, which is adequate for most applications (double
+   buffering).
+      
+   Should you experience a lot of 'Dumping frame...' messages during
+   grabbing with a tool that uses mmap(), you might want to increase if. 
+   However, it doesn't really buffer images, it just gives you a bit more
+   slack when your program is behind. But you need a multi-threaded or
+   forked program to really take advantage of these buffers.
+
+   The absolute maximum is 4, but don't set it too high!  Every buffer takes
+   up 1.22 MB of RAM, so unless you have a lot of memory setting this to
+   something more than 2 is an absolute waste.  This memory is only
+   allocated during open(), so nothing is wasted when the camera is not in
+   use.
+
+power_save
+   When power_save is enabled (set to 1), the module will try to shut down
+   the cam on close() and re-activate on open(). This will save power and
+   turn off the LED. Not all cameras support this though (the 645 and 646
+   don't have power saving at all), and some models don't work either (they
+   will shut down, but never wake up). Consider this experimental. By
+   default this option is disabled.
+
+compression (only useful with the plugin)
+   With this option you can control the compression factor that the camera
+   use to squeeze the image through the USB bus. You can set the 
+   parameter between 0 and 3:
+     0 = prefer uncompressed images; if the requested mode is not available
+         in an uncompressed format, the driver will silently switch to low
+         compression.
+     1 = low compression.
+     2 = medium compression.
+     3 = high compression.
+      
+   High compression takes less bandwidth of course, but it could also
+   introduce some unwanted artefacts. The default is 2, medium compression. 
+   See the FAQ on the website for an overview of which modes require
+   compression.
+      
+   The compression parameter only applies to the Vesta & ToUCam cameras.
+   The 645 and 646 have fixed compression parameters.      
+
+trace
+
+   In order to better detect problems, it is now possible to turn on a
+   'trace' of some of the calls the module makes; it logs all items in your
+   kernel log at debug level.
+
+   The trace variable is a bitmask; each bit represents a certain feature.
+   If you want to trace something, look up the bit value(s) in the table 
+   below, add the values together and supply that to the trace variable.
+
+   Value  Value   Description					   Default
+   (dec)  (hex)
+       1    0x1   Module initialization; this will log messages       On
+                  while loading and unloading the module
+
+       2    0x2   probe() and disconnect() traces                     On
+
+       4    0x4   Trace open() and close() calls                      Off
+
+       8    0x8   read(), mmap() and associated ioctl() calls         Off
+
+      16   0x10   Memory allocation of buffers, etc.                  Off
+
+      32   0x20   Showing underflow, overflow and Dumping frame       On
+                  messages
+
+      64   0x40   Show viewport and image sizes                       Off
+
+
+   For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
+   so you would supply trace=12 during insmod or modprobe. If
+   you want to turn the initialization and probing tracing off, set trace=0.
+   The default value for trace is 35 (0x23).
+
+   Example:
+     
+     # modprobe pwc size=cif fps=15 power_save=1
+
+The fbufs, mbufs and trace parameters are global and apply to all connected
+cameras. Each camera has its own set of buffers.
+
+size, fps, palette only specify defaults when you open() the device; this is
+to accommodate some tools that don't set the size or colour palette. You can
+change these settings after open() with the Video4Linux ioctl() calls. The
+default of defaults is QCIF size at 10 fps, BGR order.
+
+The compression parameter is semiglobal; it sets the initial compression
+preference for all camera's, but this parameter can be set per camera with
+the VIDIOCPWCSCQUAL ioctl() call.
+
+All parameters are optional.
+
+
diff -u --recursive --new-file v2.4.4/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.4/linux/MAINTAINERS	Wed Apr 25 14:35:25 2001
+++ linux/MAINTAINERS	Sun May 20 12:11:38 2001
@@ -160,8 +160,8 @@
 
 APPLETALK NETWORK LAYER
 P:	Jay Schulist
-M:	jschlst@turbolinux.com
-L:	linux-atalk@netspace.org
+M:	jschlst@samba.org
+L:	linux-atalk@lists.netspace.org
 S:	Maintained
 
 ARM MFM AND FLOPPY DRIVERS
@@ -280,13 +280,17 @@
 CONFIGURE, MENUCONFIG, XCONFIG
 P:	Michael Elizabeth Chastain
 M:	mec@shout.net
-L:	linux-kbuild@torque.net
-W:	http://www.kernel.org/pub/linux/kernel/projects/kbuild/
+L:	kbuild-devel@lists.sourceforge.net
+W:	http://kbuild.sourceforge.net
 S:	Maintained
 
 CONFIGURE.HELP
-P:	Axel Boldt
-M:	axel@uni-paderborn.de
+P:	Steven P. Cole
+M:	Steven P. Cole <elenstev@mesatop.com>
+P:	Eric S. Raymond
+M:	Eric S. Raymond <esr@thyrsus.com>
+L:	kbuild-devel@lists.sourceforge.net
+W:	http://kbuild.sourceforge.net
 S:	Maintained
 
 COSA/SRP SYNC SERIAL DRIVER
@@ -393,7 +397,7 @@
 
 DISK GEOMETRY AND PARTITION HANDLING
 P:     Andries Brouwer
-M:     aeb@veritas.com
+M:     aeb@cwi.nl
 W:     http://www.win.tue.nl/~aeb/linux/Large-Disk.html
 W:     http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
 W:     http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
@@ -405,6 +409,12 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
+P:	Tobias Ringstrom
+M:	tori@unhappy.mine.nu
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+
 DOUBLETALK DRIVER
 P:	James R. Van Zandt
 M:	jrv@vanzandt.mv.com
@@ -495,6 +505,12 @@
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
+FREEVXFS FILESYSTEM
+P:	Christoph Hellwig
+M:	hch@caldera.de
+W:	ftp://ftp.openlinux.org/pub/people/hch/vxfs
+S:	Maintained
+
 FTAPE/QIC-117
 P:	Claus-Justus Heine
 M:	claus@momo.math.rwth-aachen.de
@@ -548,22 +564,6 @@
 W:	http://www.nt.tuwien.ac.at/~kkudielk/Linux/
 S:	Maintained
 
-KERNEL BUILD (Makefile, Rules.make, scripts/*)
-P:	Keith Owens
-M:	kaos@ocs.com.au
-P:	Michael Elizabeth Chastain
-M:	mec@shout.net
-L:	linux-kbuild@torque.net
-W:	http://www.kernel.org/pub/linux/kernel/projects/kbuild/
-S:	Maintained 
-
-LOGICAL VOLUME MANAGER
-P:     Heinz Mauelshagen
-M:     linux-LVM@EZ-Darmstadt.Telekom.de
-L:     linux-LVM@msede.com
-W:     http://linux.msede.com/lvm
-S:     Maintained 
-
 HIPPI
 P:	Jes Sorensen
 M:	jes@linuxcare.com
@@ -694,9 +694,9 @@
 M:	jjciarla@raiz.uncu.edu.ar
 S:	Maintained
 
-IPX/SPX NETWORK LAYER
-P:	Jay Schulist
-M:	jschlst@turbolinux.com
+IPX NETWORK LAYER
+P:	Arnaldo Carvalho de Melo
+M:	acme@conectiva.com.br
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
@@ -759,6 +759,15 @@
 L:	autofs@linux.kernel.org
 S:	Maintained
 
+KERNEL BUILD (Makefile, Rules.make, scripts/*)
+P:	Keith Owens
+M:	kaos@ocs.com.au
+P:	Michael Elizabeth Chastain
+M:	mec@shout.net
+L:	linux-kbuild@torque.net
+W:	http://www.kernel.org/pub/linux/kernel/projects/kbuild/
+S:	Maintained 
+
 KERNEL NFSD
 P:	Neil Brown
 M:	neilb@cse.unsw.edu.au
@@ -793,6 +802,13 @@
 L:	linuxppc-dev@lists.linuxppc.org
 S:	Maintained
 
+LOGICAL VOLUME MANAGER
+P:     Heinz Mauelshagen
+M:     linux-LVM@EZ-Darmstadt.Telekom.de
+L:     linux-LVM@msede.com
+W:     http://linux.msede.com/lvm
+S:     Maintained 
+
 M68K
 P:	Jes Sorensen
 M:	jes@linuxcare.com
@@ -927,6 +943,8 @@
 M:	ak@muc.de
 P:	Alexey Kuznetsov
 M:	kuznet@ms2.inr.ac.ru
+P:	Pekka Savola (ipv6)
+M:	pekkas@netcore.fi
 L:	netdev@oss.sgi.com
 S:	Maintained
 
@@ -989,7 +1007,7 @@
 P:	Phil Blundell
 M:	Philip.Blundell@pobox.com
 P:	Tim Waugh
-M:	tim@cyberelk.demon.co.uk
+M:	tim@cyberelk.net
 P:	David Campbell
 M:	campbell@torque.net
 P:	Andrea Arcangeli
@@ -1000,7 +1018,7 @@
 
 PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
 P:	Tim Waugh
-M:	tim@cyberelk.demon.co.uk
+M:	tim@cyberelk.net
 L:	linux-parport@torque.net
 W:	http://www.torque.net/linux-pp.html
 S:	Maintained
@@ -1171,7 +1189,7 @@
 
 SMB FILESYSTEM
 P:	Urban Widmark
-M:	urban@svenskatest.se
+M:	urban@teststation.com
 W:	http://samba.org/
 L:	samba@samba.org
 S:	Maintained
@@ -1222,13 +1240,13 @@
 
 SPX NETWORK LAYER
 P:	Jay Schulist
-M:	jschlst@turbolinux.com
+M:	jschlst@samba.org
 L:	linux-net@vger.kernel.org
 S:	Supported
 
 SNA NETWORK LAYER
 P:	Jay Schulist
-M:	jschlst@turbolinux.com
+M:	jschlst@samba.org
 L:	linux-sna@turbolinux.com
 W:	http://www.linux-sna.org
 S:	Supported
diff -u --recursive --new-file v2.4.4/linux/Makefile linux/Makefile
--- v2.4.4/linux/Makefile	Fri Apr 27 18:17:19 2001
+++ linux/Makefile	Tue May 22 11:16:14 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 4
-EXTRAVERSION =
+SUBLEVEL = 5
+EXTRAVERSION =-pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -118,11 +118,7 @@
 
 CORE_FILES	=kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
 NETWORKS	=net/network.o
-DRIVERS		=drivers/block/block.o \
-		 drivers/char/char.o \
-		 drivers/misc/misc.o \
-		 drivers/net/net.o \
-		 drivers/media/media.o
+
 LIBS		=$(TOPDIR)/lib/lib.a
 SUBDIRS		=kernel drivers mm fs net ipc lib
 
@@ -132,6 +128,11 @@
 DRIVERS-  :=
 
 DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
+DRIVERS-y += drivers/char/char.o \
+	drivers/block/block.o \
+	drivers/misc/misc.o \
+	drivers/net/net.o \
+	drivers/media/media.o
 DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o
 DRIVERS-$(CONFIG_DRM) += drivers/char/drm/drm.o
 DRIVERS-$(CONFIG_NUBUS) += drivers/nubus/nubus.a
@@ -144,7 +145,6 @@
 DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o
 DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o
 DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o
-DRIVERS-$(CONFIG_SCSI_AIC7XXX) += drivers/scsi/aic7xxx/aic7xxx_drv.o
 DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o
 
 ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
@@ -178,7 +178,7 @@
 DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o
 DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
 
-DRIVERS += $(DRIVERS-y)
+DRIVERS := $(DRIVERS-y)
 
 
 # files removed with 'make clean'
@@ -416,7 +416,7 @@
 distclean: mrproper
 	rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
 		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-		-o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS tags
+		-o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags
 
 backup: mrproper
 	cd .. && tar cf - linux/ | gzip -9 > backup.gz
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/boot/tools/objstrip.c linux/arch/alpha/boot/tools/objstrip.c
--- v2.4.4/linux/arch/alpha/boot/tools/objstrip.c	Tue Jul 11 19:02:37 2000
+++ linux/arch/alpha/boot/tools/objstrip.c	Mon May 21 13:41:40 2001
@@ -14,6 +14,8 @@
  * Richard L. Sites and Richard T. Witek.
  */
 #include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
 #include <unistd.h>
 
 #include <sys/fcntl.h>
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.4.4/linux/arch/alpha/config.in	Tue Apr 17 17:19:24 2001
+++ linux/arch/alpha/config.in	Thu May 24 15:20:18 2001
@@ -59,7 +59,7 @@
 	 Wildfire		CONFIG_ALPHA_WILDFIRE" Generic
 
 # clear all implied options (don't want default values for those):
-unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 CONFIG_ALPHA_EV67
+unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
 unset CONFIG_ALPHA_EISA
 unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
 unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
@@ -141,12 +141,10 @@
 then
 	define_bool CONFIG_ALPHA_EV6 y
 	define_bool CONFIG_ALPHA_TSUNAMI y
-	bool 'EV67 (or later) CPU (speed > 600MHz)?' CONFIG_ALPHA_EV67
 fi
 if [ "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ]
 then
         define_bool CONFIG_ALPHA_EV6 y
-	define_bool CONFIG_ALPHA_EV67 y
 fi
 if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ]
 then
@@ -166,7 +164,6 @@
 then
 	define_bool CONFIG_ALPHA_IRONGATE y
 	define_bool CONFIG_ALPHA_EV6 y
-	define_bool CONFIG_ALPHA_EV67 y
 fi
 
 if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
@@ -207,6 +204,13 @@
 	-o "$CONFIG_ALPHA_TITAN" = "y" -o "$CONFIG_ALPHA_GENERIC" = "y" ]
 then
 	bool 'Symmetric multi-processing support' CONFIG_SMP
+fi
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   bool 'Discontiguous Memory Support' CONFIG_DISCONTIGMEM
+   if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then
+      bool ' NUMA Support' CONFIG_NUMA
+   fi
 fi
 
 # The machine must be able to support more than 8GB physical memory
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.4.4/linux/arch/alpha/defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/alpha/defconfig	Fri May  4 15:16:28 2001
@@ -286,7 +286,7 @@
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=y
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY=5000
+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.4.4/linux/arch/alpha/kernel/alpha_ksyms.c	Fri Apr 20 18:26:15 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Thu May 24 15:25:28 2001
@@ -188,6 +188,7 @@
 EXPORT_SYMBOL(flush_tlb_all);
 EXPORT_SYMBOL(flush_tlb_mm);
 EXPORT_SYMBOL(flush_tlb_range);
+EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(smp_imb);
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(__cpu_number_map);
@@ -231,4 +232,3 @@
 EXPORT_SYMBOL_NOVERS(memset);
 
 EXPORT_SYMBOL(get_wchan);
-EXPORT_SYMBOL(flush_tlb_page);
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c
--- v2.4.4/linux/arch/alpha/kernel/core_cia.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/core_cia.c	Tue May 22 16:29:57 2001
@@ -308,66 +308,29 @@
 }
 
 /*
- * Fixup attempt number 1.
- *
- * Write zeros directly into the tag registers.
+ * On PYXIS, even if the tbia works, we cannot use it. It effectively locks
+ * the chip (as well as direct write to the tag registers) if there is a
+ * SG DMA operation in progress. This is true at least for PYXIS rev. 1,
+ * so always use the method below.
  */
-
-static void
-cia_pci_tbi_try1(struct pci_controller *hose,
-		 dma_addr_t start, dma_addr_t end)
-{
-	wmb();
-	*(vip)CIA_IOC_TB_TAGn(0) = 0;
-	*(vip)CIA_IOC_TB_TAGn(1) = 0;
-	*(vip)CIA_IOC_TB_TAGn(2) = 0;
-	*(vip)CIA_IOC_TB_TAGn(3) = 0;
-	*(vip)CIA_IOC_TB_TAGn(4) = 0;
-	*(vip)CIA_IOC_TB_TAGn(5) = 0;
-	*(vip)CIA_IOC_TB_TAGn(6) = 0;
-	*(vip)CIA_IOC_TB_TAGn(7) = 0;
-	mb();
-	*(vip)CIA_IOC_TB_TAGn(0);
-}
-
-#if 0
 /*
- * Fixup attempt number 2.  This is the method NT and NetBSD use.
+ * This is the method NT and NetBSD use.
  *
  * Allocate mappings, and put the chip into DMA loopback mode to read a
  * garbage page.  This works by causing TLB misses, causing old entries to
  * be purged to make room for the new entries coming in for the garbage page.
  */
 
-#define CIA_BROKEN_TBI_TRY2_BASE	0xE0000000
-
-static void __init
-cia_enable_broken_tbi_try2(void)
-{
-	unsigned long *ppte, pte;
-	long i;
-
-	ppte = __alloc_bootmem(PAGE_SIZE, 32768, 0);
-	pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1;
-
-	for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); ++i)
-		ppte[i] = pte;
-
-	*(vip)CIA_IOC_PCI_W3_BASE = CIA_BROKEN_TBI_TRY2_BASE | 3;
-	*(vip)CIA_IOC_PCI_W3_MASK = (PAGE_SIZE - 1) & 0xfff00000;
-	*(vip)CIA_IOC_PCI_T3_BASE = virt_to_phys(ppte) >> 2;
-}
+#define CIA_BROKEN_TBIA_BASE	0xE0000000
+#define CIA_BROKEN_TBIA_SIZE	1024
 
-static void
+/* Always called with interrupts disabled */
+void
 cia_pci_tbi_try2(struct pci_controller *hose,
 		 dma_addr_t start, dma_addr_t end)
 {
-	unsigned long flags;
 	unsigned long bus_addr;
 	int ctrl;
-	long i;
-
-	__save_and_cli(flags);
 
 	/* Put the chip into PCI loopback mode.  */
 	mb();
@@ -382,10 +345,19 @@
 	   TLB entries are not quite LRU, meaning that we need to read more
 	   times than there are actual tags.  The 2117x docs claim strict
 	   round-robin.  Oh well, we've come this far...  */
-
-	bus_addr = cia_ioremap(CIA_BROKEN_TBI_TRY2_BASE);
-	for (i = 0; i < 12; ++i, bus_addr += 32768)
-		cia_readl(bus_addr);
+	/* Even better - as seen on the PYXIS rev 1 the TLB tags 0-3 can
+	   be filled by the TLB misses *only once* after being invalidated
+	   (by tbia or direct write). Next misses won't update them even
+	   though the lock bits are cleared. Tags 4-7 are "quite LRU" though,
+	   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);
+
+	cia_readl(bus_addr + 0x00000);
+	cia_readl(bus_addr + 0x08000);
+	cia_readl(bus_addr + 0x10000);
+	cia_readl(bus_addr + 0x18000);
 
 	/* Restore normal PCI operation.  */
 	mb();
@@ -393,10 +365,26 @@
 	mb();
 	*(vip)CIA_IOC_CIA_CTRL;
 	mb();
+}
+
+static inline void
+cia_prepare_tbia_workaround(void)
+{
+	unsigned long *ppte, pte;
+	long i;
+
+	/* Use minimal 1K map. */
+	ppte = __alloc_bootmem(CIA_BROKEN_TBIA_SIZE, 32768, 0);
+	pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1;
 
-	__restore_flags(flags);
+	for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i)
+		ppte[i] = pte;
+
+	*(vip)CIA_IOC_PCI_W3_BASE = CIA_BROKEN_TBIA_BASE | 3;
+	*(vip)CIA_IOC_PCI_W3_MASK = (CIA_BROKEN_TBIA_SIZE*1024 - 1)
+				    & 0xfff00000;
+	*(vip)CIA_IOC_PCI_T3_BASE = virt_to_phys(ppte) >> 2;
 }
-#endif
 
 static void __init
 verify_tb_operation(void)
@@ -407,7 +395,11 @@
 
 	struct pci_iommu_arena *arena = pci_isa_hose->sg_isa;
 	int ctrl, addr0, tag0, pte0, data0;
-	int temp;
+	int temp, use_tbia_try2 = 0;
+
+	/* pyxis -- tbia is broken */
+	if (pci_isa_hose->dense_io_base)
+		use_tbia_try2 = 1;
 
 	/* Put the chip into PCI loopback mode.  */
 	mb();
@@ -489,22 +481,15 @@
 
 	/* Third, try to invalidate the TLB.  */
 
-	cia_pci_tbi(arena->hose, 0, -1);
-	temp = *(vip)CIA_IOC_TB_TAGn(0);
-	if (temp & 1) {
-		cia_pci_tbi_try1(arena->hose, 0, -1);
-	
+	if (! use_tbia_try2) {
+		cia_pci_tbi(arena->hose, 0, -1);
 		temp = *(vip)CIA_IOC_TB_TAGn(0);
 		if (temp & 1) {
-			printk("pci: failed tbia test; "
-			       "no usable workaround\n");
-			goto failed;
+			use_tbia_try2 = 1;
+			printk("pci: failed tbia test; workaround available\n");
+		} else {
+			printk("pci: passed tbia test\n");
 		}
-
-		alpha_mv.mv_pci_tbi = cia_pci_tbi_try1;
-		printk("pci: failed tbia test; workaround 1 succeeded\n");
-	} else {
-		printk("pci: passed tbia test\n");
 	}
 
 	/* Fourth, verify the TLB snoops the EV5's caches when
@@ -574,6 +559,19 @@
 	/* Clean up after the tests.  */
 	arena->ptes[4] = 0;
 	arena->ptes[5] = 0;
+
+	if (use_tbia_try2) {
+		alpha_mv.mv_pci_tbi = cia_pci_tbi_try2;
+
+		/* Tags 0-3 must be disabled if we use this workaraund. */
+		wmb();
+		*(vip)CIA_IOC_TB_TAGn(0) = 2;
+		*(vip)CIA_IOC_TB_TAGn(1) = 2;
+		*(vip)CIA_IOC_TB_TAGn(2) = 2;
+		*(vip)CIA_IOC_TB_TAGn(3) = 2;
+
+		printk("pci: tbia workaround enabled\n");
+	}
 	alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
 
 exit:
@@ -706,7 +704,8 @@
 	*(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000;
 	*(vip)CIA_IOC_PCI_T2_BASE = 0x40000000 >> 2;
 
-	*(vip)CIA_IOC_PCI_W3_BASE = 0;
+	/* Prepare workaround for apparently broken tbia. */
+	cia_prepare_tbia_workaround();
 }
 
 void __init
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c
--- v2.4.4/linux/arch/alpha/kernel/core_tsunami.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/core_tsunami.c	Thu May 24 15:24:37 2001
@@ -11,6 +11,7 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -222,7 +223,6 @@
 	   it's the shifted tag bits.  */
 	value = (start & 0xffff0000) >> 12;
 
-	wmb();
 	*csr = value;
 	mb();
 	*csr;
@@ -278,6 +278,16 @@
 #define FN __FUNCTION__
 
 static void __init
+tsunami_monster_window_enable(tsunami_pchip * pchip)
+{
+	volatile unsigned long * csr = &pchip->pctl.csr;
+
+	*csr |= pctl_m_mwin;
+	mb();
+	*csr;
+}
+
+static void __init
 tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
 {
 	struct pci_controller *hose;
@@ -358,7 +368,13 @@
 	 * address range.
 	 */
 	hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
-	hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0);
+	{
+		unsigned long size = 0x08000000;
+		if (max_low_pfn > (0x80000000 >> PAGE_SHIFT))
+			size = 0x40000000;
+		hose->sg_pci = iommu_arena_new(hose, 0xc0000000, size, 0);
+	}
+	
 	__direct_map_base = 0x40000000;
 	__direct_map_size = 0x80000000;
 
@@ -379,6 +395,9 @@
 	pchip->tba[3].csr  = virt_to_phys(hose->sg_pci->ptes);
 
 	tsunami_pci_tbi(hose, 0, -1);
+
+	/* Enable the Monster Window to make DAC pci64 possible. */
+	tsunami_monster_window_enable(pchip);
 }
 
 void __init
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.4.4/linux/arch/alpha/kernel/entry.S	Sun Sep  3 11:36:45 2000
+++ linux/arch/alpha/kernel/entry.S	Thu May 24 15:20:18 2001
@@ -10,7 +10,7 @@
 
 #define SIGCHLD 20
 
-#define NR_SYSCALLS 377
+#define NR_SYSCALLS 378
 
 /*
  * These offsets must match with alpha_mv in <asm/machvec.h>.
@@ -709,16 +709,14 @@
 	br	restore_all
 .end entSys
 
-#ifdef CONFIG_SMP
-        .globl  ret_from_smp_fork
+        .globl  ret_from_fork
 .align 3
-.ent ret_from_smp_fork
-ret_from_smp_fork:
+.ent ret_from_fork
+ret_from_fork:
 	lda	$26,ret_from_sys_call
 	mov	$17,$16
 	jsr	$31,schedule_tail
-.end ret_from_smp_fork
-#endif /* CONFIG_SMP */
+.end ret_from_fork
 
 .align 3
 .ent reschedule
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
--- v2.4.4/linux/arch/alpha/kernel/pci.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/pci.c	Mon May 21 13:38:41 2001
@@ -156,7 +156,7 @@
 	else if	(res->flags & IORESOURCE_MEM) {
 		/* Make sure we start at our min on all hoses */
 		if (start - hose->mem_space->start < PCIBIOS_MIN_MEM)
-			start = PCIBIOS_MIN_MEM + hose->io_space->start;
+			start = PCIBIOS_MIN_MEM + hose->mem_space->start;
 
 		/*
 		 * The following holds at least for the Low Cost
@@ -441,15 +441,15 @@
 			if (hose->index == bus) break;
 		if (!hose) return -ENODEV;
 	} else {
-	/* Special hook for ISA access.  */
-	if (bus == 0 && dfn == 0) {
-		hose = pci_isa_hose;
-	} else {
-		dev = pci_find_slot(bus, dfn);
-		if (!dev)
-			return -ENODEV;
-		hose = dev->sysdata;
-	}
+		/* Special hook for ISA access.  */
+		if (bus == 0 && dfn == 0) {
+			hose = pci_isa_hose;
+		} else {
+			dev = pci_find_slot(bus, dfn);
+			if (!dev)
+				return -ENODEV;
+			hose = dev->sysdata;
+		}
 	}
 
 	switch (which & ~IOBASE_FROM_HOSE) {
@@ -468,4 +468,12 @@
 	}
 
 	return -EOPNOTSUPP;
+}
+
+/* Return the index of the PCI controller for device PDEV. */
+int
+pci_controller_num(struct pci_dev *pdev)
+{
+        struct pci_controller *hose = pdev->sysdata;
+	return (hose ? hose->index : -ENXIO);
 }
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/pci_iommu.c linux/arch/alpha/kernel/pci_iommu.c
--- v2.4.4/linux/arch/alpha/kernel/pci_iommu.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/pci_iommu.c	Thu May 24 15:20:18 2001
@@ -175,7 +175,7 @@
 	/* If the machine doesn't define a pci_tbi routine, we have to
 	   assume it doesn't support sg mapping.  */
 	if (! alpha_mv.mv_pci_tbi) {
-		printk(KERN_INFO "pci_map_single failed: no hw sg\n");
+		printk(KERN_WARNING "pci_map_single failed: no hw sg\n");
 		return 0;
 	}
 		
@@ -186,7 +186,7 @@
 	npages = calc_npages((paddr & ~PAGE_MASK) + size);
 	dma_ofs = iommu_arena_alloc(arena, npages);
 	if (dma_ofs < 0) {
-		printk(KERN_INFO "pci_map_single failed: "
+		printk(KERN_WARNING "pci_map_single failed: "
 		       "could not allocate dma page tables\n");
 		return 0;
 	}
@@ -215,6 +215,7 @@
 pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size,
 		 int direction)
 {
+	unsigned long flags;
 	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
 	struct pci_iommu_arena *arena;
 	long dma_ofs, npages;
@@ -248,6 +249,9 @@
 	}
 
 	npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
+
+	spin_lock_irqsave(&arena->lock, flags);
+
 	iommu_arena_free(arena, dma_ofs, npages);
 
 
@@ -259,6 +263,8 @@
 	if (dma_ofs >= arena->next_entry)
 		alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
 
+	spin_unlock_irqrestore(&arena->lock, flags);
+
 	DBGA("pci_unmap_single: sg [%x,%lx] np %ld from %p\n",
 	     dma_addr, size, npages, __builtin_return_address(0));
 }
@@ -402,8 +408,20 @@
 	paddr &= ~PAGE_MASK;
 	npages = calc_npages(paddr + size);
 	dma_ofs = iommu_arena_alloc(arena, npages);
-	if (dma_ofs < 0)
-		return -1;
+	if (dma_ofs < 0) {
+		/* If we attempted a direct map above but failed, die.  */
+		if (leader->dma_address == 0)
+			return -1;
+
+		/* Otherwise, break up the remaining virtually contiguous
+		   hunks into individual direct maps.  */
+		for (sg = leader; sg < end; ++sg)
+			if (sg->dma_address == 1 || sg->dma_address == -2)
+				sg->dma_address = 0;
+
+		/* Retry.  */
+		return sg_fill(leader, end, out, arena, max_dma);
+	}
 
 	out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
 	out->dma_length = size;
@@ -503,13 +521,13 @@
 		out->dma_length = 0;
 
 	if (out - start == 0)
-		printk(KERN_INFO "pci_map_sg failed: no entries?\n");
+		printk(KERN_WARNING "pci_map_sg failed: no entries?\n");
 	DBGA("pci_map_sg: %ld entries\n", out - start);
 
 	return out - start;
 
 error:
-	printk(KERN_INFO "pci_map_sg failed: "
+	printk(KERN_WARNING "pci_map_sg failed: "
 	       "could not allocate dma page tables\n");
 
 	/* Some allocation failed while mapping the scatterlist
@@ -528,6 +546,7 @@
 pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
 	     int direction)
 {
+	unsigned long flags;
 	struct pci_controller *hose;
 	struct pci_iommu_arena *arena;
 	struct scatterlist *end;
@@ -547,6 +566,9 @@
 		arena = hose->sg_isa;
 
 	fbeg = -1, fend = 0;
+
+	spin_lock_irqsave(&arena->lock, flags);
+
 	for (end = sg + nents; sg < end; ++sg) {
 		unsigned long addr, size;
 		long npages, ofs;
@@ -586,6 +608,8 @@
 	*/
 	if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry)
 		alpha_mv.mv_pci_tbi(hose, fbeg, fend);
+
+	spin_unlock_irqrestore(&arena->lock, flags);
 
 	DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg));
 }
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.4.4/linux/arch/alpha/kernel/process.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/alpha/kernel/process.c	Thu May 24 15:20:18 2001
@@ -83,10 +83,11 @@
 
 		/* Although we are an idle CPU, we do not want to 
 		   get into the scheduler unnecessarily.  */
-		if (current->need_resched) {
-			schedule();
-			check_pgt_cache();
-		}
+		long oldval = xchg(&current->need_resched, -1UL);
+		if (!oldval)
+			while (current->need_resched < 0);
+		schedule();
+		check_pgt_cache();
 	}
 }
 
@@ -303,7 +304,7 @@
 	    struct task_struct * p, struct pt_regs * regs)
 {
 	extern void ret_from_sys_call(void);
-	extern void ret_from_smp_fork(void);
+	extern void ret_from_fork(void);
 
 	struct pt_regs * childregs;
 	struct switch_stack * childstack, *stack;
@@ -322,11 +323,7 @@
 	stack = ((struct switch_stack *) regs) - 1;
 	childstack = ((struct switch_stack *) childregs) - 1;
 	*childstack = *stack;
-#ifdef CONFIG_SMP
-	childstack->r26 = (unsigned long) ret_from_smp_fork;
-#else
-	childstack->r26 = (unsigned long) ret_from_sys_call;
-#endif
+	childstack->r26 = (unsigned long) ret_from_fork;
 	p->thread.usp = usp;
 	p->thread.ksp = (unsigned long) childstack;
 	p->thread.pal_flags = 1;	/* set FEN, clear everything else */
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.4.4/linux/arch/alpha/kernel/setup.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/setup.c	Thu May 24 15:20:18 2001
@@ -29,6 +29,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/bootmem.h>
+#include <linux/pci.h>
 
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
@@ -49,7 +50,6 @@
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/pci.h>
 #include <asm/mmu_context.h>
 #include <asm/console.h>
 
@@ -87,18 +87,6 @@
 static struct alpha_machine_vector *get_sysvec_byname(const char *);
 static void get_sysnames(long, long, char **, char **);
 
-/*
- * This is setup by the secondary bootstrap loader.  Because
- * the zero page is zeroed out as soon as the vm system is
- * initialized, we need to copy things out into a more permanent
- * place.
- */
-#define PARAM			ZERO_PGE
-#define COMMAND_LINE		((char*)(PARAM + 0x0000))
-#define COMMAND_LINE_SIZE	256
-#define INITRD_START		(*(unsigned long *) (PARAM+0x100))
-#define INITRD_SIZE		(*(unsigned long *) (PARAM+0x108))
-
 static char command_line[COMMAND_LINE_SIZE];
 char saved_command_line[COMMAND_LINE_SIZE];
 
@@ -245,6 +233,7 @@
         return end >> PAGE_SHIFT; /* Return the PFN of the limit. */
 }
 
+#ifndef CONFIG_DISCONTIGMEM
 static void __init
 setup_memory(void *kernel_end)
 {
@@ -362,6 +351,7 @@
 
 	/* Reserve the bootmap memory.  */
 	reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size);
+	printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	initrd_start = INITRD_START;
@@ -383,6 +373,9 @@
 	}
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
+#else
+extern void setup_memory(void *);
+#endif /* !CONFIG_DISCONTIGMEM */
 
 int __init
 page_is_ram(unsigned long pfn)
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.4.4/linux/arch/alpha/kernel/smp.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/alpha/kernel/smp.c	Thu May 24 15:24:37 2001
@@ -123,6 +123,22 @@
 	cpu_data[cpuid].prof_multiplier = 1;
 }
 
+static void __init
+wait_boot_cpu_to_stop(int cpuid)
+{
+	long stop = jiffies + 10*HZ;
+
+	while (time_before(jiffies, stop)) {
+	        if (!smp_secondary_alive)
+			return;
+		barrier();
+	}
+
+	printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid);
+	for (;;)
+		barrier();
+}
+
 /*
  * Where secondaries begin a life of C.
  */
@@ -131,6 +147,11 @@
 {
 	int cpuid = hard_smp_processor_id();
 
+	if (current != init_tasks[cpu_number_map(cpuid)]) {
+		printk("BUG: smp_calling: cpu %d current %p init_tasks[cpu_number_map(cpuid)] %p\n",
+		       cpuid, current, init_tasks[cpu_number_map(cpuid)]);
+	}
+
 	DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state));
 
 	/* Turn on machine checks.  */
@@ -154,12 +175,22 @@
 
 	/* Must have completely accurate bogos.  */
 	__sti();
+
+	/*
+	 * Wait boot CPU to stop with irq enabled before
+	 * running calibrate_delay().
+	 */
+	wait_boot_cpu_to_stop(cpuid);
+	mb();
 	calibrate_delay();
-	smp_store_cpu_info(cpuid);
 
-	/* Allow master to continue. */
+	smp_store_cpu_info(cpuid);
+	/*
+	 * Allow master to continue only after we written
+	 * the loops_per_jiffy.
+	 */
 	wmb();
-	smp_secondary_alive = cpuid;
+	smp_secondary_alive = 1;
 
 	/* Wait for the go code.  */
 	while (!smp_threads_ready)
@@ -203,6 +234,7 @@
 		break;
 
 	case EV6_CPU:
+	case EV67_CPU:
 		on_chip_cache = 64 + 64;
 		break;
 
@@ -246,7 +278,7 @@
 		 + hwrpb->processor_offset
 		 + cpuid * hwrpb->processor_size);
 
-	cpumask = (1L << cpuid);
+	cpumask = (1UL << cpuid);
 	if (hwrpb->txrdy & cpumask)
 		goto delay1;
 	ready1:
@@ -267,8 +299,8 @@
 	return;
 
 delay1:
-	/* Wait one second.  Note that jiffies aren't ticking yet.  */
-	for (timeout = 100000; timeout > 0; --timeout) {
+	/* Wait 10 seconds.  Note that jiffies aren't ticking yet.  */
+	for (timeout = 1000000; timeout > 0; --timeout) {
 		if (!(hwrpb->txrdy & cpumask))
 			goto ready1;
 		udelay(10);
@@ -277,8 +309,8 @@
 	goto timeout;
 
 delay2:
-	/* Wait one second.  */
-	for (timeout = 100000; timeout > 0; --timeout) {
+	/* Wait 10 seconds.  */
+	for (timeout = 1000000; timeout > 0; --timeout) {
 		if (!(hwrpb->txrdy & cpumask))
 			goto ready2;
 		udelay(10);
@@ -307,7 +339,7 @@
 	mycpu = hard_smp_processor_id();
 
 	for (i = 0; i < NR_CPUS; i++) {
-		if (!(txrdy & (1L << i)))
+		if (!(txrdy & (1UL << i)))
 			continue;
 
 		DBGS(("recv_secondary_console_msg: "
@@ -375,7 +407,7 @@
 
 #if 0
 	DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
-	      hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique));
+	      hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique));
 #endif
 	DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
 	      cpuid, idle->state, idle->thread.pal_flags));
@@ -398,9 +430,9 @@
 
 	send_secondary_console_msg("START\r\n", cpuid);
 
-	/* Wait 1 second for an ACK from the console.  Note that jiffies 
+	/* Wait 10 seconds for an ACK from the console.  Note that jiffies 
 	   aren't ticking yet.  */
-	for (timeout = 100000; timeout > 0; timeout--) {
+	for (timeout = 1000000; timeout > 0; timeout--) {
 		if (cpu->flags & 1)
 			goto started;
 		udelay(10);
@@ -447,6 +479,8 @@
 	idle = init_task.prev_task;
 	if (!idle)
 		panic("No idle process for CPU %d", cpuid);
+	if (idle == &init_task)
+		panic("idle process is init_task for CPU %d", cpuid);
 
 	idle->processor = cpuid;
 	__cpu_logical_map[cpunum] = cpuid;
@@ -468,10 +502,14 @@
 	if (secondary_cpu_start(cpuid, idle))
 		return -1;
 
+	mb();
+	/* Notify the secondary CPU it can run calibrate_delay() */
+	smp_secondary_alive = 0;
+
 	/* We've been acked by the console; wait one second for the task
 	   to start up for real.  Note that jiffies aren't ticking yet.  */
-	for (timeout = 0; timeout < 100000; timeout++) {
-		if (smp_secondary_alive != -1)
+	for (timeout = 0; timeout < 1000000; timeout++) {
+		if (smp_secondary_alive == 1)
 			goto alive;
 		udelay(10);
 		barrier();
@@ -523,7 +561,7 @@
 			if ((cpu->flags & 0x1cc) == 0x1cc) {
 				smp_num_probed++;
 				/* Assume here that "whami" == index */
-				hwrpb_cpu_present_mask |= (1L << i);
+				hwrpb_cpu_present_mask |= (1UL << i);
 				cpu->pal_revision = boot_cpu_palrev;
 			}
 
@@ -534,9 +572,9 @@
 		}
 	} else {
 		smp_num_probed = 1;
-		hwrpb_cpu_present_mask = (1L << boot_cpuid);
+		hwrpb_cpu_present_mask = (1UL << boot_cpuid);
 	}
-	cpu_present_mask = 1L << boot_cpuid;
+	cpu_present_mask = 1UL << boot_cpuid;
 
 	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
 	       smp_num_probed, hwrpb_cpu_present_mask);
@@ -589,7 +627,7 @@
 		if (smp_boot_one_cpu(i, cpu_count))
 			continue;
 
-		cpu_present_mask |= 1L << i;
+		cpu_present_mask |= 1UL << i;
 		cpu_count++;
 	}
 
@@ -600,7 +638,7 @@
 
 	bogosum = 0;
 	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_present_mask & (1L << i))
+		if (cpu_present_mask & (1UL << i))
 			bogosum += cpu_data[i].loops_per_jiffy;
 	}
 	printk(KERN_INFO "SMP: Total of %d processors activated "
@@ -798,13 +836,13 @@
 		printk(KERN_WARNING
 		       "smp_send_reschedule: Sending IPI to self.\n");
 #endif
-	send_ipi_message(1L << cpu, IPI_RESCHEDULE);
+	send_ipi_message(1UL << cpu, IPI_RESCHEDULE);
 }
 
 void
 smp_send_stop(void)
 {
-	unsigned long to_whom = cpu_present_mask ^ (1L << smp_processor_id());
+	unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id());
 #if DEBUG_IPI_MSG
 	if (hard_smp_processor_id() != boot_cpu_id)
 		printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n");
@@ -827,7 +865,7 @@
 int
 smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
 {
-	unsigned long to_whom = cpu_present_mask ^ (1L << smp_processor_id());
+	unsigned long to_whom = cpu_present_mask ^ (1UL << smp_processor_id());
 	struct smp_call_struct data;
 	long timeout;
 	
@@ -1060,7 +1098,7 @@
 	int printed = 0;
 	int cpu = smp_processor_id();
 
-	stuck = 1L << 28;
+	stuck = 1L << 30;
  try_again:
 
 	/* Use sub-sections to put the actual loop at the end
@@ -1137,8 +1175,8 @@
 
  try_again:
 
-	stuck_lock = 1<<26;
-	stuck_reader = 1<<26;
+	stuck_lock = 1<<30;
+	stuck_reader = 1<<30;
 
 	__asm__ __volatile__(
 	"1:	ldl_l	%1,%0\n"
@@ -1182,7 +1220,7 @@
 
  try_again:
 
-	stuck_lock = 1<<26;
+	stuck_lock = 1<<30;
 
 	__asm__ __volatile__(
 	"1:	ldl_l	%1,%0;"
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/sys_miata.c linux/arch/alpha/kernel/sys_miata.c
--- v2.4.4/linux/arch/alpha/kernel/sys_miata.c	Fri Oct 27 10:55:01 2000
+++ linux/arch/alpha/kernel/sys_miata.c	Sat May 19 17:43:05 2001
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/reboot.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -223,11 +224,21 @@
 static void
 miata_kill_arch(int mode)
 {
-	/* Who said DEC engineers have no sense of humor? ;-)  */
-	if (alpha_using_srm) {
-		*(vuip) PYXIS_RESET = 0x0000dead;
-		mb();
+	switch(mode) {
+	case LINUX_REBOOT_CMD_RESTART:
+		/* Who said DEC engineers have no sense of humor? ;-)  */ 
+		if (alpha_using_srm) {
+			*(vuip) PYXIS_RESET = 0x0000dead; 
+			mb(); 
+		}
+		break;
+	case LINUX_REBOOT_CMD_HALT:
+		break;
+	case LINUX_REBOOT_CMD_POWER_OFF:
+		break;
 	}
+
+	halt();
 }
 
 
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/sys_nautilus.c linux/arch/alpha/kernel/sys_nautilus.c
--- v2.4.4/linux/arch/alpha/kernel/sys_nautilus.c	Sun Mar 25 18:24:31 2001
+++ linux/arch/alpha/kernel/sys_nautilus.c	Mon May 21 13:40:39 2001
@@ -55,7 +55,6 @@
 {
 	if (alpha_using_srm) {
 		alpha_mv.device_interrupt = srm_device_interrupt;
-		alpha_mv.kill_arch = NULL;
 	}
 
 	init_i8259a_irqs();
@@ -77,7 +76,7 @@
 {
 	switch (mode) {
 	case LINUX_REBOOT_CMD_RESTART:
-		{
+		if (! alpha_using_srm) {
 			u8 t8;
 			pcibios_read_config_byte(0, 0x38, 0x43, &t8);
 			pcibios_write_config_byte(0, 0x38, 0x43, t8 | 0x80);
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.4.4/linux/arch/alpha/kernel/traps.c	Thu Feb  8 12:56:29 2001
+++ linux/arch/alpha/kernel/traps.c	Thu May 24 15:24:37 2001
@@ -291,12 +291,40 @@
 		 * is interesting.
 		 */
 		printk("%6x%c", (int)tmp & 0xffffff, (++i % 11) ? ' ' : '\n');
+#if 0
 		if (i > 40) {
 			printk(" ...");
 			break;
 		}
+#endif
 	}
 	printk("\n");
+}
+
+int kstack_depth_to_print = 24;
+
+void show_stack(unsigned long *sp)
+{
+	unsigned long *stack;
+	int i;
+
+	/*
+	 * debugging aid: "show_stack(NULL);" prints the
+	 * back trace for this cpu.
+	 */
+	if(sp==NULL)
+		sp=(unsigned long*)&sp;
+
+	stack = sp;
+	for(i=0; i < kstack_depth_to_print; i++) {
+		if (((long) stack & (THREAD_SIZE-1)) == 0)
+			break;
+		if (i && ((i % 4) == 0))
+			printk("\n       ");
+		printk("%016lx ", *stack++);
+	}
+	printk("\n");
+	dik_show_trace(sp);
 }
 
 void
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/mm/Makefile linux/arch/alpha/mm/Makefile
--- v2.4.4/linux/arch/alpha/mm/Makefile	Wed Oct 30 08:41:44 1996
+++ linux/arch/alpha/mm/Makefile	Thu May 24 15:20:18 2001
@@ -7,9 +7,10 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-OBJS	= init.o fault.o extable.o
+O_TARGET := mm.o
 
-mm.o: $(OBJS)
-	$(LD) -r -o mm.o $(OBJS)
+obj-y	:= init.o fault.o extable.o
+
+obj-$(CONFIG_DISCONTIGMEM) += numa.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/mm/extable.c linux/arch/alpha/mm/extable.c
--- v2.4.4/linux/arch/alpha/mm/extable.c	Fri Sep 22 14:07:43 2000
+++ linux/arch/alpha/mm/extable.c	Thu May 24 15:20:18 2001
@@ -45,20 +45,26 @@
 	/* There is only the kernel to search.  */
 	ret = search_one_table(__start___ex_table, __stop___ex_table - 1,
 			       addr - gp);
-	if (ret) return ret;
 #else
+	extern spinlock_t modlist_lock;
+	unsigned long flags;
 	/* The kernel is the last "module" -- no need to treat it special. */
 	struct module *mp;
+
+	ret = 0;
+	spin_lock_irqsave(&modlist_lock, flags);
 	for (mp = module_list; mp ; mp = mp->next) {
-		if (!mp->ex_table_start)
+		if (!mp->ex_table_start || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
 			continue;
 		ret = search_one_table(mp->ex_table_start,
 				       mp->ex_table_end - 1, addr - mp->gp);
-		if (ret) return ret;
+		if (ret)
+			break;
 	}
+	spin_unlock_irqrestore(&modlist_lock, flags);
 #endif
 
-	return 0;
+	return ret;
 }
 
 unsigned
@@ -71,15 +77,23 @@
 			       addr - exc_gp);
 	if (ret) return ret;
 #else
+	extern spinlock_t modlist_lock;
+	unsigned long flags;
 	/* The kernel is the last "module" -- no need to treat it special. */
 	struct module *mp;
+
+	ret = 0;
+	spin_lock_irqsave(&modlist_lock, flags);
 	for (mp = module_list; mp ; mp = mp->next) {
-		if (!mp->ex_table_start)
+		if (!mp->ex_table_start || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
 			continue;
 		ret = search_one_table(mp->ex_table_start,
 				       mp->ex_table_end - 1, addr - exc_gp);
-		if (ret) return ret;
+		if (ret)
+			break;
 	}
+	spin_unlock_irqrestore(&modlist_lock, flags);
+	if (ret) return ret;
 #endif
 
 	/*
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.4.4/linux/arch/alpha/mm/init.c	Fri Apr 13 20:26:06 2001
+++ linux/arch/alpha/mm/init.c	Thu May 24 15:20:18 2001
@@ -33,7 +33,7 @@
 #include <asm/mmu_context.h>
 #include <asm/console.h>
 
-static unsigned long totalram_pages;
+unsigned long totalram_pages;
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
@@ -115,6 +115,7 @@
 	return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED));
 }
 
+#ifndef CONFIG_DISCONTIGMEM
 void
 show_mem(void)
 {
@@ -144,6 +145,7 @@
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
 	show_buffers();
 }
+#endif
 
 static inline unsigned long
 load_PCB(struct thread_struct * pcb)
@@ -275,6 +277,7 @@
 }
 
 
+#ifndef CONFIG_DISCONTIGMEM
 /*
  * paging_init() sets up the memory map.
  */
@@ -287,16 +290,7 @@
 	dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	high_pfn = max_low_pfn;
 
-#define ORDER_MASK (~((1L << (MAX_ORDER-1))-1))
-#define ORDER_ALIGN(n)	(((n) +  ~ORDER_MASK) & ORDER_MASK)
-
-	dma_pfn = ORDER_ALIGN(dma_pfn);
-	high_pfn = ORDER_ALIGN(high_pfn);
-
-#undef ORDER_MASK
-#undef ORDER_ALIGN
-
-	if (dma_pfn > high_pfn)
+	if (dma_pfn >= high_pfn)
 		zones_size[ZONE_DMA] = high_pfn;
 	else {
 		zones_size[ZONE_DMA] = dma_pfn;
@@ -309,6 +303,7 @@
 	/* Initialize the kernel's ZERO_PGE. */
 	memset((void *)ZERO_PGE, 0, PAGE_SIZE);
 }
+#endif /* CONFIG_DISCONTIGMEM */
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
 void
@@ -327,6 +322,7 @@
 }
 #endif
 
+#ifndef CONFIG_DISCONTIGMEM
 static void __init
 printk_memory_info(void)
 {
@@ -366,6 +362,7 @@
 
 	printk_memory_info();
 }
+#endif /* CONFIG_DISCONTIGMEM */
 
 void
 free_initmem (void)
@@ -388,13 +385,14 @@
 void
 free_initrd_mem(unsigned long start, unsigned long end)
 {
+	unsigned long __start = start;
 	for (; start < end; start += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(start));
 		set_page_count(virt_to_page(start), 1);
 		free_page(start);
 		totalram_pages++;
 	}
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	printk ("Freeing initrd memory: %ldk freed\n", (end - __start) >> 10);
 }
 #endif
 
diff -u --recursive --new-file v2.4.4/linux/arch/alpha/mm/numa.c linux/arch/alpha/mm/numa.c
--- v2.4.4/linux/arch/alpha/mm/numa.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/mm/numa.c	Thu May 24 15:20:18 2001
@@ -0,0 +1,430 @@
+/*
+ *  linux/arch/alpha/mm/numa.c
+ *
+ *  DISCONTIGMEM NUMA alpha support.
+ *
+ *  Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
+
+#include <asm/hwrpb.h>
+#include <asm/pgalloc.h>
+
+plat_pg_data_t *plat_node_data[MAX_NUMNODES];
+bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+
+#undef DEBUG_DISCONTIG
+#ifdef DEBUG_DISCONTIG
+#define DBGDCONT(args...) printk(args)
+#else
+#define DBGDCONT(args...)
+#endif
+
+#define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)     ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
+#define for_each_mem_cluster(memdesc, cluster, i)		\
+	for ((cluster) = (memdesc)->cluster, (i) = 0;		\
+	     (i) < (memdesc)->numclusters; (i)++, (cluster)++)
+
+static void __init show_mem_layout(void)
+{
+	struct memclust_struct * cluster;
+	struct memdesc_struct * memdesc;
+	int i;
+
+	/* Find free clusters, and init and free the bootmem accordingly.  */
+	memdesc = (struct memdesc_struct *)
+	  (hwrpb->mddt_offset + (unsigned long) hwrpb);
+
+	printk("Raw memory layout:\n");
+	for_each_mem_cluster(memdesc, cluster, i) {
+		printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n",
+		       i, cluster->usage, cluster->start_pfn,
+		       cluster->start_pfn + cluster->numpages);
+	}
+}
+
+static void __init
+setup_memory_node(int nid, void *kernel_end)
+{
+	extern unsigned long mem_size_limit;
+	struct memclust_struct * cluster;
+	struct memdesc_struct * memdesc;
+	unsigned long start_kernel_pfn, end_kernel_pfn;
+	unsigned long bootmap_size, bootmap_pages, bootmap_start;
+	unsigned long start, end;
+	unsigned long node_pfn_start, node_pfn_end;
+	int i;
+	unsigned long node_datasz = PFN_UP(sizeof(plat_pg_data_t));
+	int show_init = 0;
+
+	/* Find the bounds of current node */
+	node_pfn_start = (nid * NODE_MAX_MEM_SIZE) >> PAGE_SHIFT;
+	node_pfn_end = node_pfn_start + (NODE_MAX_MEM_SIZE >> PAGE_SHIFT);
+	
+	/* Find free clusters, and init and free the bootmem accordingly.  */
+	memdesc = (struct memdesc_struct *)
+	  (hwrpb->mddt_offset + (unsigned long) hwrpb);
+
+	/* find the bounds of this node (min_low_pfn/max_low_pfn) */
+	min_low_pfn = ~0UL;
+	for_each_mem_cluster(memdesc, cluster, i) {
+		/* Bit 0 is console/PALcode reserved.  Bit 1 is
+		   non-volatile memory -- we might want to mark
+		   this for later.  */
+		if (cluster->usage & 3)
+			continue;
+
+		start = cluster->start_pfn;
+		end = start + cluster->numpages;
+
+		if (start >= node_pfn_end || end <= node_pfn_start)
+			continue;
+
+		if (!show_init) {
+			show_init = 1;
+			printk("Initialing bootmem allocator on Node ID %d\n", nid);
+		}
+		printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n",
+		       i, cluster->usage, cluster->start_pfn,
+		       cluster->start_pfn + cluster->numpages);
+
+		if (start < node_pfn_start)
+			start = node_pfn_start;
+		if (end > node_pfn_end)
+			end = node_pfn_end;
+
+		if (start < min_low_pfn)
+			min_low_pfn = start;
+		if (end > max_low_pfn)
+			max_low_pfn = end;
+	}
+
+	if (mem_size_limit && max_low_pfn >= mem_size_limit) {
+		printk("setup: forcing memory size to %ldK (from %ldK).\n",
+		       mem_size_limit << (PAGE_SHIFT - 10),
+		       max_low_pfn    << (PAGE_SHIFT - 10));
+		max_low_pfn = mem_size_limit;
+	}
+
+	if (min_low_pfn >= max_low_pfn)
+		return;
+
+	num_physpages += max_low_pfn - min_low_pfn;
+
+	/* Cute trick to make sure our local node data is on local memory */
+	PLAT_NODE_DATA(nid) = (plat_pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
+	/* Quasi-mark the plat_pg_data_t as in-use */
+	min_low_pfn += node_datasz;
+	if (min_low_pfn >= max_low_pfn) {
+		printk(" not enough mem to reserve PLAT_NODE_DATA");
+		return;
+	}
+	NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+
+	printk(" Detected node memory:   start %8lu, end %8lu\n",
+	       min_low_pfn, max_low_pfn);
+
+	DBGDCONT(" DISCONTIG: plat_node_data[%d]   is at 0x%p\n", nid, PLAT_NODE_DATA(nid));
+	DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata);
+
+	/* Find the bounds of kernel memory.  */
+	start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
+	end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
+	bootmap_start = -1;
+
+	if (!nid && (max_low_pfn < end_kernel_pfn || min_low_pfn > start_kernel_pfn))
+		panic("kernel loaded out of ram");
+
+	/* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned */
+	min_low_pfn = (min_low_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1);
+
+	/* We need to know how many physically contiguous pages
+	   we'll need for the bootmap.  */
+	bootmap_pages = bootmem_bootmap_pages(max_low_pfn-min_low_pfn);
+
+	/* Now find a good region where to allocate the bootmap.  */
+	for_each_mem_cluster(memdesc, cluster, i) {
+		if (cluster->usage & 3)
+			continue;
+
+		start = cluster->start_pfn;
+		end = start + cluster->numpages;
+
+		if (start >= max_low_pfn || end <= min_low_pfn)
+			continue;
+
+		if (end > max_low_pfn)
+			end = max_low_pfn;
+		if (start < min_low_pfn)
+			start = min_low_pfn;
+
+		if (start < start_kernel_pfn) {
+			if (end > end_kernel_pfn
+			    && end - end_kernel_pfn >= bootmap_pages) {
+				bootmap_start = end_kernel_pfn;
+				break;
+			} else if (end > start_kernel_pfn)
+				end = start_kernel_pfn;
+		} else if (start < end_kernel_pfn)
+			start = end_kernel_pfn;
+		if (end - start >= bootmap_pages) {
+			bootmap_start = start;
+			break;
+		}
+	}
+
+	if (bootmap_start == -1)
+		panic("couldn't find a contigous place for the bootmap");
+
+	/* Allocate the bootmap and mark the whole MM as reserved.  */
+	bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start,
+					 min_low_pfn, max_low_pfn);
+	DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n",
+		 bootmap_start, bootmap_size, bootmap_pages);
+
+	/* Mark the free regions.  */
+	for_each_mem_cluster(memdesc, cluster, i) {
+		if (cluster->usage & 3)
+			continue;
+
+		start = cluster->start_pfn;
+		end = cluster->start_pfn + cluster->numpages;
+
+		if (start >= max_low_pfn || end <= min_low_pfn)
+			continue;
+
+		if (end > max_low_pfn)
+			end = max_low_pfn;
+		if (start < min_low_pfn)
+			start = min_low_pfn;
+
+		if (start < start_kernel_pfn) {
+			if (end > end_kernel_pfn) {
+				free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start),
+					     (PFN_PHYS(start_kernel_pfn)
+					      - PFN_PHYS(start)));
+				printk(" freeing pages %ld:%ld\n",
+				       start, start_kernel_pfn);
+				start = end_kernel_pfn;
+			} else if (end > start_kernel_pfn)
+				end = start_kernel_pfn;
+		} else if (start < end_kernel_pfn)
+			start = end_kernel_pfn;
+		if (start >= end)
+			continue;
+
+		free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start));
+		printk(" freeing pages %ld:%ld\n", start, end);
+	}
+
+	/* Reserve the bootmap memory.  */
+	reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), bootmap_size);
+	printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
+
+	numnodes++;
+}
+
+void __init
+setup_memory(void *kernel_end)
+{
+	int nid;
+
+	show_mem_layout();
+
+	numnodes = 0;
+	for (nid = 0; nid < MAX_NUMNODES; nid++)
+		setup_memory_node(nid, kernel_end);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_start = INITRD_START;
+	if (initrd_start) {
+		initrd_end = initrd_start+INITRD_SIZE;
+		printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+		       (void *) initrd_start, INITRD_SIZE);
+
+		if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
+			printk("initrd extends beyond end of memory "
+			       "(0x%08lx > 0x%p)\ndisabling initrd\n",
+			       initrd_end,
+			       phys_to_virt(PFN_PHYS(max_low_pfn)));
+			initrd_start = initrd_end = 0;
+		} else {
+			/* Assume the initrd to be in the first node */
+			reserve_bootmem_node(NODE_DATA(nid), virt_to_phys((void *)initrd_start),
+					INITRD_SIZE);
+		}
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+}
+
+void __init paging_init(void)
+{
+	unsigned int    nid;
+	unsigned long   zones_size[MAX_NR_ZONES] = {0, };
+	unsigned long	dma_local_pfn;
+
+	/*
+	 * The old global MAX_DMA_ADDRESS per-arch API doesn't fit
+	 * in the NUMA model, for now we convert it to a pfn and
+	 * we interpret this pfn as a local per-node information.
+	 * This issue isn't very important since none of these machines
+	 * have legacy ISA slots anyways.
+	 */
+	dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+
+	for (nid = 0; nid < numnodes; nid++) {
+		unsigned long start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT;
+		unsigned long end_pfn = plat_node_bdata[nid].node_low_pfn;
+		unsigned long lmax_mapnr;
+
+		if (dma_local_pfn >= end_pfn - start_pfn)
+			zones_size[ZONE_DMA] = end_pfn - start_pfn;
+		else {
+			zones_size[ZONE_DMA] = dma_local_pfn;
+			zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
+		}
+		free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn<<PAGE_SHIFT, NULL);
+		lmax_mapnr = PLAT_NODE_DATA_STARTNR(nid) + PLAT_NODE_DATA_SIZE(nid);
+		if (lmax_mapnr > max_mapnr) {
+			max_mapnr = lmax_mapnr;
+			DBGDCONT("Grow max_mapnr to %ld\n", max_mapnr);
+		}
+	}
+
+	/* Initialize the kernel's ZERO_PGE. */
+	memset((void *)ZERO_PGE, 0, PAGE_SIZE);
+}
+
+#define printkdot()					\
+do {							\
+	if (!(i++ % ((100UL*1024*1024)>>PAGE_SHIFT)))	\
+		printk(".");				\
+} while(0)
+
+#define clobber(p, size) memset((p)->virtual, 0xaa, (size))
+
+void __init mem_stress(void)
+{
+	LIST_HEAD(x);
+	LIST_HEAD(xx);
+	struct page * p;
+	unsigned long i = 0;
+
+	printk("starting memstress");
+	while ((p = alloc_pages(GFP_ATOMIC, 1))) {
+		clobber(p, PAGE_SIZE*2);
+		list_add(&p->list, &x);
+		printkdot();
+	}
+	while ((p = alloc_page(GFP_ATOMIC))) {
+		clobber(p, PAGE_SIZE);
+		list_add(&p->list, &xx);
+		printkdot();
+	}
+	while (!list_empty(&x)) {
+		p = list_entry(x.next, struct page, list);
+		clobber(p, PAGE_SIZE*2);
+		list_del(x.next);
+		__free_pages(p, 1);
+		printkdot();
+	}
+	while (!list_empty(&xx)) {
+		p = list_entry(xx.next, struct page, list);
+		clobber(p, PAGE_SIZE);
+		list_del(xx.next);
+		__free_pages(p, 0);
+		printkdot();
+	}
+	printk("I'm still alive duh!\n");
+}
+
+#undef printkdot
+#undef clobber
+
+void __init mem_init(void)
+{
+	unsigned long codesize, reservedpages, datasize, initsize, pfn;
+	extern int page_is_ram(unsigned long) __init;
+	extern char _text, _etext, _data, _edata;
+	extern char __init_begin, __init_end;
+	extern unsigned long totalram_pages;
+	unsigned long nid, i;
+	mem_map_t * lmem_map;
+
+	high_memory = (void *) __va(max_mapnr <<PAGE_SHIFT);
+
+	reservedpages = 0;
+	for (nid = 0; nid < numnodes; nid++) {
+		/*
+		 * This will free up the bootmem, ie, slot 0 memory
+		 */
+		totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
+
+		lmem_map = NODE_MEM_MAP(nid);
+		pfn = NODE_DATA(nid)->node_start_paddr >> PAGE_SHIFT;
+		for (i = 0; i < PLAT_NODE_DATA_SIZE(nid); i++, pfn++)
+			if (page_is_ram(pfn) && PageReserved(lmem_map+i))
+				reservedpages++;
+	}
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_data;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, "
+		"%luk data, %luk init)\n",
+	       nr_free_pages() << (PAGE_SHIFT-10),
+	       num_physpages << (PAGE_SHIFT-10),
+	       codesize >> 10,
+	       reservedpages << (PAGE_SHIFT-10),
+	       datasize >> 10,
+	       initsize >> 10);
+#if 0
+	mem_stress();
+#endif
+}
+
+void
+show_mem(void)
+{
+	long i,free = 0,total = 0,reserved = 0;
+	long shared = 0, cached = 0;
+	int nid;
+
+	printk("\nMem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+	for (nid = 0; nid < numnodes; nid++) {
+		mem_map_t * lmem_map = NODE_MEM_MAP(nid);
+		i = PLAT_NODE_DATA_SIZE(nid);
+		while (i-- > 0) {
+			total++;
+			if (PageReserved(lmem_map+i))
+				reserved++;
+			else if (PageSwapCache(lmem_map+i))
+				cached++;
+			else if (!page_count(lmem_map+i))
+				free++;
+			else
+				shared += atomic_read(&lmem_map[i].count) - 1;
+		}
+	}
+	printk("%ld pages of RAM\n",total);
+	printk("%ld free pages\n",free);
+	printk("%ld reserved pages\n",reserved);
+	printk("%ld pages shared\n",shared);
+	printk("%ld pages swap cached\n",cached);
+	printk("%ld pages in page table cache\n",pgtable_cache_size);
+	show_buffers();
+}
diff -u --recursive --new-file v2.4.4/linux/arch/arm/def-configs/clps7500 linux/arch/arm/def-configs/clps7500
--- v2.4.4/linux/arch/arm/def-configs/clps7500	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/def-configs/clps7500	Sat May 19 17:43:05 2001
@@ -2,7 +2,9 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_ARM=y
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 CONFIG_UID16=y
 
 #
@@ -23,6 +25,7 @@
 CONFIG_ARCH_CLPS7500=y
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_FTVPCI is not set
 # CONFIG_ARCH_TBOX is not set
 # CONFIG_ARCH_SHARK is not set
@@ -30,22 +33,51 @@
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
 # CONFIG_ARCH_ACORN is not set
 # CONFIG_FOOTBRIDGE is not set
 # CONFIG_FOOTBRIDGE_HOST is not set
 # CONFIG_FOOTBRIDGE_ADDIN is not set
 CONFIG_CPU_32=y
 # CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
 CONFIG_CPU_32v3=y
-CONFIG_CPU_ARM7=y
+# CONFIG_CPU_32v4 is not set
+# CONFIG_CPU_ARM610 is not set
+CONFIG_CPU_ARM710=y
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
 # CONFIG_DISCONTIGMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
 
 #
 # General setup
 #
+CONFIG_ANGELBOOT=y
+# CONFIG_PCI is not set
+CONFIG_ISA=y
+# CONFIG_ISA_DMA is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
 CONFIG_NET=y
@@ -60,7 +92,7 @@
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PM is not set
 # CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=/dev/nfs rw"
+CONFIG_CMDLINE="mem=16M root=nfs"
 # CONFIG_ALIGNMENT_TRAP is not set
 
 #
@@ -81,34 +113,35 @@
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
 # CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOCPROBE is not set
+
+#
+# RAM/ROM Device Drivers
+#
 # CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
 # CONFIG_MTD_MTDRAM is not set
 
 #
-# MTD drivers for mapped chips
+# Linearly Mapped Flash Device Drivers
 #
 # CONFIG_MTD_CFI is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_JEDEC is not set
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
-# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_JEDEC is not set
 
 #
 # Drivers for chip mappings
 #
-# CONFIG_MTD_MIXMEM is not set
-# CONFIG_MTD_NORA is not set
-# CONFIG_MTD_OCTAGON is not set
-# CONFIG_MTD_PNC2000 is not set
-# CONFIG_MTD_RPXLITE is not set
-# CONFIG_MTD_VMAX is not set
 
 #
 # User modules and translation layers for MTD devices
@@ -122,7 +155,6 @@
 # Plug and Play configuration
 #
 # CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
 
 #
 # Block devices
@@ -130,20 +162,12 @@
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
+CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_BLK_DEV_FLD7500=y
+# CONFIG_BLK_DEV_FLD7500 is not set
 
 #
 # Networking options
@@ -159,10 +183,8 @@
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -179,6 +201,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -201,6 +224,7 @@
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_NET_SB1000 is not set
 
 #
@@ -213,16 +237,19 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
+CONFIG_NET_PCI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_CS89x0=y
+# CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
-# CONFIG_SK98LIN is not set
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
@@ -283,10 +310,6 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
 
 #
 # ISDN subsystem
@@ -294,6 +317,11 @@
 # CONFIG_ISDN is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -305,7 +333,7 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
 CONFIG_PRINTER=y
-CONFIG_LP_CONSOLE=y
+# CONFIG_LP_CONSOLE is not set
 # CONFIG_PPDEV is not set
 
 #
@@ -322,16 +350,38 @@
 #
 # Mice
 #
-# CONFIG_BUSMOUSE is not set
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
 CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
+# CONFIG_PSMOUSE is not set
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
 
 #
 # Joysticks
 #
-# CONFIG_JOYSTICK is not set
+
+#
+# Game port support
+#
+
+#
+# Gameport joysticks
+#
+
+#
+# Serial port support
+#
+
+#
+# Serial port joysticks
+#
+
+#
+# Parallel port joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -341,11 +391,6 @@
 CONFIG_CLPS7500_FLASH=y
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -353,45 +398,38 @@
 # CONFIG_DRM is not set
 
 #
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
 # File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
 CONFIG_MINIX_FS=y
 # CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
+CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -401,21 +439,10 @@
 # CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -430,11 +457,14 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
 # Console drivers
 #
+CONFIG_PC_KEYB=y
+CONFIG_PC_KEYMAP=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FB=y
 
@@ -445,15 +475,14 @@
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FB_ACORN=y
 # CONFIG_CHRONTEL_7003 is not set
-# CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_VIRTUAL is not set
 CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
 CONFIG_FBCON_CFB8=y
-# CONFIG_FBCON_CFB16 is not set
-# CONFIG_FBCON_CFB24 is not set
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
 # CONFIG_FBCON_CFB32 is not set
 # CONFIG_FBCON_AFB is not set
 # CONFIG_FBCON_ILBM is not set
@@ -487,4 +516,4 @@
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL=y
diff -u --recursive --new-file v2.4.4/linux/arch/arm/def-configs/ebsa110 linux/arch/arm/def-configs/ebsa110
--- v2.4.4/linux/arch/arm/def-configs/ebsa110	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/def-configs/ebsa110	Wed May 16 10:31:27 2001
@@ -192,8 +192,6 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
 CONFIG_IPV6=m
-CONFIG_IPV6_EUI64=y
-# CONFIG_IPV6_NO_PB is not set
 
 #
 #   IPv6: Netfilter Configuration
diff -u --recursive --new-file v2.4.4/linux/arch/arm/def-configs/integrator linux/arch/arm/def-configs/integrator
--- v2.4.4/linux/arch/arm/def-configs/integrator	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/def-configs/integrator	Sat May 19 17:43:05 2001
@@ -25,6 +25,7 @@
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 CONFIG_ARCH_INTEGRATOR=y
 # CONFIG_ARCH_RPC is not set
@@ -56,18 +57,28 @@
 #
 # Processor Type
 #
+# CONFIG_CPU_32v3 is not set
 CONFIG_CPU_32v4=y
-CONFIG_CPU_ARM720=y
-CONFIG_CPU_ARM920=y
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_ARM920T=y
 CONFIG_CPU_ARM920_CPU_IDLE=y
 CONFIG_CPU_ARM920_I_CACHE_ON=y
 CONFIG_CPU_ARM920_D_CACHE_ON=y
 # CONFIG_CPU_ARM920_WRITETHROUGH is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+# CONFIG_CPU_SA1100 is not set
 # CONFIG_DISCONTIGMEM is not set
 
 #
 # General setup
 #
+
+#
+# Please ensure that you have read the help on the next option
+#
 # CONFIG_ANGELBOOT is not set
 CONFIG_PCI_INTEGRATOR=y
 CONFIG_PCI=y
@@ -103,23 +114,32 @@
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
 # CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOCPROBE is not set
+
+#
+# RAM/ROM Device Drivers
+#
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_MTDRAM is not set
 
 #
-# MTD drivers for mapped chips
+# Linearly Mapped Flash Device Drivers
 #
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_JEDEC is not set
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
+# CONFIG_MTD_JEDEC is not set
 # CONFIG_MTD_PHYSMAP is not set
 
 #
@@ -347,6 +367,8 @@
 CONFIG_SERIAL_AMBA=y
 CONFIG_SERIAL_INTEGRATOR=y
 CONFIG_SERIAL_AMBA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
 
@@ -403,6 +425,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -457,8 +481,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -475,6 +497,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -503,7 +526,7 @@
 #
 # Kernel hacking
 #
-CONFIG_FRAME_POINTER=y
+# CONFIG_NO_FRAME_POINTER is not set
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_INFO is not set
diff -u --recursive --new-file v2.4.4/linux/arch/arm/defconfig linux/arch/arm/defconfig
--- v2.4.4/linux/arch/arm/defconfig	Mon Jun 19 17:59:33 2000
+++ linux/arch/arm/defconfig	Sat May 19 17:43:05 2001
@@ -2,50 +2,80 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
 CONFIG_UID16=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
 
 #
-# System and processor type
+# Loadable module support
 #
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
-CONFIG_FOOTBRIDGE=y
-CONFIG_HOST_FOOTBRIDGE=y
-# CONFIG_ADDIN_FOOTBRIDGE is not set
-CONFIG_ARCH_EBSA285=y
-# CONFIG_ARCH_CATS is not set
-CONFIG_ARCH_NETWINDER=y
-# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_INTEGRATOR=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
 # CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
 CONFIG_CPU_32=y
 # CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA110=y
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
-CONFIG_ISA=y
-CONFIG_ISA_DMA=y
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_ALIGNMENT_TRAP is not set
 
 #
-# Loadable module support
+# Processor Type
 #
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ARM720=y
+CONFIG_CPU_ARM920=y
+CONFIG_CPU_ARM920_CPU_IDLE=y
+CONFIG_CPU_ARM920_I_CACHE_ON=y
+CONFIG_CPU_ARM920_D_CACHE_ON=y
+# CONFIG_CPU_ARM920_WRITETHROUGH is not set
+# CONFIG_DISCONTIGMEM is not set
 
 #
 # General setup
 #
+# CONFIG_ANGELBOOT is not set
+CONFIG_PCI_INTEGRATOR=y
+CONFIG_PCI=y
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
@@ -56,296 +86,86 @@
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
 # CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=1f04 mem=32M"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
 
 #
 # Parallel port support
 #
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-# CONFIG_LEDS_CPU is not set
+# CONFIG_PARPORT is not set
 
 #
-# IEEE 1394 (FireWire) support
+# Memory Technology Devices (MTD)
 #
-# CONFIG_IEEE1394 is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
 
 #
-# I2O device support
+# MTD drivers for mapped chips
 #
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_PHYSMAP is not set
+
+#
+# Drivers for chip mappings
+#
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+
+#
+# User modules and translation layers for MTD devices
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+CONFIG_MTD_ARM=y
 
 #
 # Plug and Play configuration
 #
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=y
-
-#
-# Parallel IDE high-level drivers
-#
-CONFIG_PARIDE_PD=m
-CONFIG_PARIDE_PCD=m
-CONFIG_PARIDE_PF=m
-CONFIG_PARIDE_PT=m
-CONFIG_PARIDE_PG=m
-
-#
-# Parallel IDE protocol modules
-#
-CONFIG_PARIDE_ATEN=m
-CONFIG_PARIDE_BPCK=m
-CONFIG_PARIDE_COMM=m
-CONFIG_PARIDE_DSTR=m
-CONFIG_PARIDE_FIT2=m
-CONFIG_PARIDE_FIT3=m
-CONFIG_PARIDE_EPAT=m
-CONFIG_PARIDE_EPIA=m
-CONFIG_PARIDE_FRIQ=m
-CONFIG_PARIDE_FRPW=m
-CONFIG_PARIDE_KBIC=m
-CONFIG_PARIDE_KTTI=m
-CONFIG_PARIDE_ON20=m
-CONFIG_PARIDE_ON26=m
+# CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_STRIPED=m
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_WDT is not set
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_21285_WATCHDOG is not set
-CONFIG_977_WATCHDOG=m
-CONFIG_DS1620=y
-CONFIG_NWBUTTON=y
-CONFIG_NWBUTTON_REBOOT=y
-CONFIG_NWFLASH=m
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_DEV=y
-# CONFIG_I2C_PARPORT is not set
-
-#
-# Radio Adapters
-#
-# CONFIG_RADIO_CADET is not set
-# CONFIG_RADIO_RTRACK is not set
-# CONFIG_RADIO_RTRACK2 is not set
-# CONFIG_RADIO_AZTECH is not set
-# CONFIG_RADIO_GEMTEK is not set
-# CONFIG_RADIO_MIROPCM20 is not set
-# CONFIG_RADIO_SF16FMI is not set
-# CONFIG_RADIO_TERRATEC is not set
-# CONFIG_RADIO_TRUST is not set
-# CONFIG_RADIO_TYPHOON is not set
-# CONFIG_RADIO_ZOLTRIX is not set
-
-#
-# Video Adapters
-#
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_BWQCAM is not set
-# CONFIG_VIDEO_CQCAM is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-# CONFIG_VIDEO_BUZ is not set
-# CONFIG_VIDEO_ZR36120 is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# USB support
-#
-CONFIG_USB=m
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=m
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-
-#
-# USB Devices
-#
-CONFIG_USB_PRINTER=m
-# CONFIG_USB_SCANNER is not set
-CONFIG_USB_AUDIO=m
-CONFIG_USB_ACM=m
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-
-#
-# USB HID
-#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=m
-CONFIG_USB_MOUSE=m
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=m
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_MIX=y
-# CONFIG_INPUT_MOUSEDEV_DIGITIZER is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_CYBER2000=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-CONFIG_FBCON_VGA=y
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
 # Networking options
 #
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
+# CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
@@ -356,16 +176,10 @@
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
@@ -376,10 +190,11 @@
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -391,16 +206,6 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -412,68 +217,59 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_NET_SB1000 is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
-CONFIG_NET_VENDOR_3COM=y
-# CONFIG_EL1 is not set
-# CONFIG_EL2 is not set
-# CONFIG_ELPLUS is not set
-# CONFIG_EL16 is not set
-# CONFIG_EL3 is not set
-# CONFIG_3C515 is not set
-CONFIG_VORTEX=y
+# CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
 # CONFIG_DE4X5 is not set
-CONFIG_TULIP=m
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
-# CONFIG_EEPRO100 is not set
+CONFIG_EEPRO100=y
+CONFIG_EEPRO100_PM=y
 # CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
-CONFIG_NE2K_PCI=y
-# CONFIG_RTL8129 is not set
+# CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
 # CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
 # CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -494,71 +290,21 @@
 # CONFIG_WAN is not set
 
 #
-# ATA/IDE/MFM/RLL support
+# Amateur Radio support
 #
-CONFIG_IDE=y
+# CONFIG_HAMRADIO is not set
 
 #
-# IDE, ATA and ATAPI Block devices
+# IrDA (infrared) support
 #
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_IRDA is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# ATA/IDE/MFM/RLL support
 #
-# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_BLK_DEV_IDECS is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-CONFIG_BLK_DEV_OFFBOARD=y
-CONFIG_IDEDMA_PCI_AUTO=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC62XX_TUNING is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_CMD64X_RAID is not set
-CONFIG_BLK_DEV_CY82C693=y
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_HPT34X_AUTODMA is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_HPT366_FIP is not set
-# CONFIG_HPT366_MODE3 is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_PDC202XX=y
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_MASTER is not set
-# CONFIG_BLK_DEV_SIS5513 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_SL82C105=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-CONFIG_BLK_DEV_IDE_MODES=y
 
 #
 # SCSI support
@@ -566,72 +312,115 @@
 # CONFIG_SCSI is not set
 
 #
-# Sound
+# IEEE 1394 (FireWire) support
 #
-CONFIG_SOUND=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SOFTOSS is not set
-CONFIG_SOUND_SB=m
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-# CONFIG_SOUND_VIDC is not set
-CONFIG_SOUND_WAVEARTIST=m
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_AMBA=y
+CONFIG_SERIAL_INTEGRATOR=y
+CONFIG_SERIAL_AMBA_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-CONFIG_ADFS_FS=y
+# CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
+# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -639,77 +428,77 @@
 # CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+CONFIG_ROMFS_FS=y
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
-CONFIG_NFSD=m
+# CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
 #
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_ACORN_PARTITION=y
-# CONFIG_ACORN_PARTITION_ICS is not set
-CONFIG_ACORN_PARTITION_ADFS=y
-# CONFIG_ACORN_PARTITION_POWERTEC is not set
-# CONFIG_ACORN_PARTITION_RISCIX is not set
+# CONFIG_ACORN_PARTITION is not set
 # CONFIG_OSF_PARTITION is not set
 # CONFIG_AMIGA_PARTITION is not set
 # CONFIG_ATARI_PARTITION is not set
 # CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
-CONFIG_NLS=y
+# CONFIG_NLS is not set
 
 #
-# Native Language Support
+# Console drivers
+#
+CONFIG_KMI_KEYB=y
+CONFIG_PC_KEYMAP=y
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
 #
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=m
-# CONFIG_NLS_KOI8_R is not set
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
@@ -719,4 +508,4 @@
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL=y
diff -u --recursive --new-file v2.4.4/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.4.4/linux/arch/arm/kernel/setup.c	Fri Apr 27 14:10:31 2001
+++ linux/arch/arm/kernel/setup.c	Wed May 16 15:25:16 2001
@@ -51,7 +51,6 @@
 extern void paging_init(struct meminfo *, struct machine_desc *desc);
 extern void bootmem_init(struct meminfo *);
 extern void reboot_setup(char *str);
-extern unsigned long memparse(char *ptr, char **retptr);
 extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
 
diff -u --recursive --new-file v2.4.4/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.4.4/linux/arch/arm/lib/Makefile	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/lib/Makefile	Wed May 16 15:25:16 2001
@@ -48,3 +48,7 @@
 endif
 
 include $(TOPDIR)/Rules.make
+
+csumpartialcopy.o: csumpartialcopygeneric.S
+csumpartialcopyuser.o: csumpartialcopygeneric.S
+
diff -u --recursive --new-file v2.4.4/linux/arch/arm/lib/csumpartial.S linux/arch/arm/lib/csumpartial.S
--- v2.4.4/linux/arch/arm/lib/csumpartial.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/lib/csumpartial.S	Wed May 16 15:25:16 2001
@@ -12,57 +12,119 @@
 
 		.text
 
-/* Function: __u32 csum_partial(const char *src, int len, __u32)
+/*
+ * Function: __u32 csum_partial(const char *src, int len, __u32 sum)
  * Params  : r0 = buffer, r1 = len, r2 = checksum
  * Returns : r0 = new checksum
  */
 
+buf	.req	r0
+len	.req	r1
+sum	.req	r2
+td0	.req	r3
+td1	.req	r4	@ save before use
+td2	.req	r5	@ save before use
+td3	.req	lr
+
+.zero:		mov	r0, sum
+		add	sp, sp, #4
+		ldr	pc, [sp], #4
+
+		/*
+		 * Handle 0 to 7 bytes, with any alignment of source and
+		 * destination pointers.  Note that when we get here, C = 0
+		 */
+.less8:		teq	len, #0			@ check for zero count
+		beq	.zero
+
+		/* we must have at least one byte. */
+		tst	buf, #1			@ odd address?
+		ldrneb	td0, [buf], #1
+		subne	len, len, #1
+		adcnes	sum, sum, td0, lsl #8
+
+.less4:		tst	len, #6
+		beq	.less8_byte
+
+		/* we are now half-word aligned */
+
+.less8_wordlp:
+#ifdef __ARM_ARCH_4__
+		ldrh	td0, [buf], #2
+		sub	len, len, #2
+#else
+		ldrb	td0, [buf], #1
+		ldrb	td3, [buf], #1
+		sub	len, len, #2
+		orr	td0, td0, td3, lsl #8
+#endif
+		adcs	sum, sum, td0
+		tst	len, #6
+		bne	.less8_wordlp
+
+.less8_byte:	tst	len, #1			@ odd number of bytes
+		ldrneb	td0, [buf], #1		@ include last byte
+		adcnes	sum, sum, td0		@ update checksum
+
+.done:		adc	r0, sum, #0		@ collect up the last carry
+		ldr	td0, [sp], #4
+		tst	td0, #1			@ check buffer alignment
+		movne	td0, r0, lsl #8		@ rotate checksum by 8 bits
+		orrne	r0, td0, r0, lsr #24
+		ldr	pc, [sp], #4		@ return
+
+.not_aligned:	tst	buf, #1			@ odd address
+		ldrneb	td0, [buf], #1		@ make even
+		subne	len, len, #1
+		adcnes	sum, sum, td0, lsl #8	@ update checksum
+
+		tst	buf, #2			@ 32-bit aligned?
+#ifdef __ARM_ARCH_4__
+		ldrneh	td0, [buf], #2		@ make 32-bit aligned
+		subne	len, len, #2
+#else
+		ldrneb	td0, [buf], #1
+		ldrneb	ip, [buf], #1
+		subne	len, len, #2
+		orrne	td0, td0, ip, lsl #8
+#endif
+		adcnes	sum, sum, td0		@ update checksum
+		mov	pc, lr
+
 ENTRY(csum_partial)
-		tst	r0, #2
-		beq	1f
-		subs	r1, r1, #2
-		addmi	r1, r1, #2
-		bmi	3f
-		bic	r0, r0, #3
-		ldr	r3, [r0], #4
-		adds	r2, r2, r3, lsr #16
-		adcs	r2, r2, #0
-1:		adds	r2, r2, #0
-		bics	ip, r1, #31
+		stmfd	sp!, {buf, lr}
+		cmp	len, #8			@ Ensure that we have at least
+		blo	.less8			@ 8 bytes to copy.
+
+		adds	sum, sum, #0		@ C = 0
+		tst	buf, #3			@ Test destination alignment
+		blne	.not_aligned		@ aligh destination, return here
+
+1:		bics	ip, len, #31
 		beq	3f
-		stmfd	sp!, {r4 - r6}
-2:		ldmia	r0!, {r3 - r6}
-		adcs	r2, r2, r3
-		adcs	r2, r2, r4
-		adcs	r2, r2, r5
-		adcs	r2, r2, r6
-		ldmia	r0!, {r3 - r6}
-		adcs	r2, r2, r3
-		adcs	r2, r2, r4
-		adcs	r2, r2, r5
-		adcs	r2, r2, r6
+
+		stmfd	sp!, {r4 - r5}
+2:		ldmia	buf!, {td0, td1, td2, td3}
+		adcs	sum, sum, td0
+		adcs	sum, sum, td1
+		adcs	sum, sum, td2
+		adcs	sum, sum, td3
+		ldmia	buf!, {td0, td1, td2, td3}
+		adcs	sum, sum, td0
+		adcs	sum, sum, td1
+		adcs	sum, sum, td2
+		adcs	sum, sum, td3
 		sub	ip, ip, #32
 		teq	ip, #0
 		bne	2b
-		adcs	r2, r2, #0
-		ldmfd	sp!, {r4 - r6}
-3:		ands	ip, r1, #0x1c
-		beq	5f
-4:		ldr	r3, [r0], #4
-		sub	ip, ip, #4
-		adcs	r2, r2, r3
-		teq	ip, #0
-		bne	4b
-		adcs	r2, r2, #0
-5:		ands	ip, r1, #3
-		moveq	r0, r2
-		RETINSTR(moveq,pc,lr)
-		mov	ip, ip, lsl #3
-		ldr	r3, [r0]
-		rsb	ip, ip, #32
-		mov	r3, r3, lsl ip
-		adds	r2, r2, r3, lsr ip
-		adc	r0, r2, #0
-		RETINSTR(mov,pc,lr)
+		ldmfd	sp!, {r4 - r5}
 
+3:		tst	len, #0x1c		@ should not change C
+		beq	.less4
 
+4:		ldr	td0, [buf], #4
+		sub	len, len, #4
+		adcs	sum, sum, td0
+		tst	len, #0x1c
+		bne	4b
+		b	.less4
diff -u --recursive --new-file v2.4.4/linux/arch/arm/lib/csumpartialcopy.S linux/arch/arm/lib/csumpartialcopy.S
--- v2.4.4/linux/arch/arm/lib/csumpartialcopy.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/lib/csumpartialcopy.S	Wed May 16 15:25:16 2001
@@ -18,11 +18,11 @@
  */
 
 		.macro	save_regs
-		stmfd	sp!, {r4 - r8, fp, ip, lr, pc}
+		stmfd	sp!, {r1, r4 - r8, fp, ip, lr, pc}
 		.endm
 
 		.macro	load_regs,flags
-		LOADREGS(\flags,fp,{r4 - r8, fp, sp, pc})
+		LOADREGS(\flags,fp,{r1, r4 - r8, fp, sp, pc})
 		.endm
 
 		.macro	load1b, reg1
@@ -47,250 +47,6 @@
 		ldmia	r0!, {\reg1, \reg2, \reg3, \reg4}
 		.endm
 
-ENTRY(csum_partial_copy_nocheck)
-		mov	ip, sp
-		save_regs
-		sub	fp, ip, #4
-		cmp	r2, #4
-		blt	.too_small
-		tst	r1, #2			@ Test destination alignment
-		beq	.dst_aligned
-		load2b	ip, r8
-		subs	r2, r2, #2		@ We do not know if SRC is aligned...
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		adcs	r3, r3, #0
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1		@ Destination now aligned
-.dst_aligned:	tst	r0, #3
-		bne	.src_not_aligned
-		adds	r3, r3, #0
-		bics	ip, r2, #15		@ Routine for src & dst aligned
-		beq	2f
-1:		load4l	r4, r5, r6, r7
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r4, r5
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		tst	ip, #4
-		beq	4f
-3:		load1l	r4
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		load1l	r4
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-.exit:		tst	r2, #1
-		strneb	r4, [r1], #1
-		andne	r4, r4, #255
-		adcnes	r3, r3, r4
-		adcs	r0, r3, #0
-		load_regs	ea
+#define FN_ENTRY	ENTRY(csum_partial_copy_nocheck)
 
-.too_small:	teq	r2, #0
-		load_regs	eqea
-		cmp	r2, #2
-		blt	.too_small1
-		load2b	ip, r8
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		strb	ip, [r1], #1
-		strb	r8, [r1], #1
-		tst	r2, #1
-.too_small1:				@ C = 0
-		beq	.csum_exit
-		load1b	ip
-		strb	ip, [r1], #1
-		adcs	r3, r3, ip
-.csum_exit:	adc	r0, r3, #0
-		load_regs	ea
-
-.src_not_aligned:
-		cmp	r2, #4
-		blt	.too_small
-		and	ip, r0, #3
-		bic	r0, r0, #3
-		load1l	r4
-		cmp	ip, #2
-		beq	.src2_aligned
-		bhi	.src3_aligned
-		mov	r4, r4, lsr #8
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		mov	r7, r7, lsr #8
-		orr	r7, r7, r8, lsl #24
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #8
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #8
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #24
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #8
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		b	.exit
-
-.src2_aligned:	mov	r4, r4, lsr #16
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		mov	r7, r7, lsr #16
-		orr	r7, r7, r8, lsl #16
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #16
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #16
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #16
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #16
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		tst	r2, #1
-		adceq	r0, r3, #0
-		load_regs	eqea
-		load1b	r4
-		b	.exit
-
-.src3_aligned:	mov	r4, r4, lsr #24
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		mov	r7, r7, lsr #24
-		orr	r7, r7, r8, lsl #8
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #24
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #24
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #8
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #24
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		load1l	r4
-		strb	r4, [r1], #1
-		adcs	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		b	.exit
+#include "csumpartialcopygeneric.S"
diff -u --recursive --new-file v2.4.4/linux/arch/arm/lib/csumpartialcopygeneric.S linux/arch/arm/lib/csumpartialcopygeneric.S
--- v2.4.4/linux/arch/arm/lib/csumpartialcopygeneric.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/csumpartialcopygeneric.S	Wed May 16 15:25:16 2001
@@ -0,0 +1,327 @@
+/*
+ *  linux/arch/arm/lib/csumpartialcopygeneric.S
+ *
+ *  Copyright (C) 1995-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * unsigned int
+ * csum_partial_copy_xxx(const char *src, char *dst, int len, int sum, )
+ *  r0 = src, r1 = dst, r2 = len, r3 = sum
+ *  Returns : r0 = checksum
+ *
+ * Note that 'tst' and 'teq' preserve the carry flag.
+ */
+
+src	.req	r0
+dst	.req	r1
+len	.req	r2
+sum	.req	r3
+
+.zero:		mov	r0, sum
+		load_regs	ea
+
+		/*
+		 * Align an unaligned destination pointer.  We know that
+		 * we have >= 8 bytes here, so we don't need to check
+		 * the length.  Note that the source pointer hasn't been
+		 * aligned yet.
+		 */
+.dst_unaligned:	tst	dst, #1
+		beq	.dst_16bit
+
+		load1b	ip
+		sub	len, len, #1
+		adcs	sum, sum, ip, lsl #8	@ update checksum
+		strb	ip, [dst], #1
+		tst	dst, #2
+		moveq	pc, lr			@ dst is now 32bit aligned
+
+.dst_16bit:	load2b	r8, ip
+		sub	len, len, #2
+		adcs	sum, sum, r8
+		strb	r8, [dst], #1
+		adcs	sum, sum, ip, lsl #8
+		strb	ip, [dst], #1
+		mov	pc, lr			@ dst is now 32bit aligned
+
+		/*
+		 * Handle 0 to 7 bytes, with any alignment of source and
+		 * destination pointers.  Note that when we get here, C = 0
+		 */
+.less8:		teq	len, #0			@ check for zero count
+		beq	.zero
+
+		/* we must have at least one byte. */
+		tst	dst, #1			@ dst 16-bit aligned
+		beq	.less8_aligned
+
+		/* Align dst */
+		load1b	ip
+		sub	len, len, #1
+		adcs	sum, sum, ip, lsl #8	@ update checksum
+		strb	ip, [dst], #1
+		tst	len, #6
+		beq	.less8_byteonly
+
+1:		load2b	r8, ip
+		sub	len, len, #2
+		adcs	sum, sum, r8
+		strb	r8, [dst], #1
+		adcs	sum, sum, ip, lsl #8
+		strb	ip, [dst], #1
+.less8_aligned:	tst	len, #6
+		bne	1b
+.less8_byteonly:
+		tst	len, #1
+		beq	.done
+		load1b	r8
+		adcs	sum, sum, r8		@ update checksum
+		strb	r8, [dst], #1
+		b	.done
+
+FN_ENTRY
+		mov	ip, sp
+		save_regs
+		sub	fp, ip, #4
+
+		cmp	len, #8			@ Ensure that we have at least
+		blo	.less8			@ 8 bytes to copy.
+
+		adds	sum, sum, #0		@ C = 0
+		tst	dst, #3			@ Test destination alignment
+		blne	.dst_unaligned		@ align destination, return here
+
+		/*
+		 * Ok, the dst pointer is now 32bit aligned, and we know
+		 * that we must have more than 4 bytes to copy.  Note
+		 * that C contains the carry from the dst alignment above.
+		 */
+
+		tst	src, #3			@ Test source alignment
+		bne	.src_not_aligned
+
+		/* Routine for src & dst aligned */
+
+		bics	ip, len, #15
+		beq	2f
+
+1:		load4l	r4, r5, r6, r7
+		stmia	dst!, {r4, r5, r6, r7}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		adcs	sum, sum, r6
+		adcs	sum, sum, r7
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+
+2:		ands	ip, len, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r4, r5
+		stmia	dst!, {r4, r5}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		tst	ip, #4
+		beq	4f
+
+3:		load1l	r4
+		str	r4, [dst], #4
+		adcs	sum, sum, r4
+
+4:		ands	len, len, #3
+		beq	.done
+		load1l	r4
+		tst	len, #2
+		beq	.exit
+		adcs	sum, sum, r4, lsl #16
+		strb	r4, [dst], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [dst], #1
+		mov	r4, r4, lsr #8
+.exit:		tst	len, #1
+		strneb	r4, [dst], #1
+		andne	r4, r4, #255
+		adcnes	sum, sum, r4
+
+		/*
+		 * If the dst pointer was not 16-bit aligned, we
+		 * need to rotate the checksum here to get around
+		 * the inefficient byte manipulations in the
+		 * architecture independent code.
+		 */
+.done:		adc	r0, sum, #0
+		ldr	sum, [sp, #0]		@ dst
+		tst	sum, #1
+		movne	sum, r0, lsl #8
+		orrne	r0, sum, r0, lsr #24
+		load_regs	ea
+
+.src_not_aligned:
+		adc	sum, sum, #0		@ include C from dst alignment
+		and	ip, src, #3
+		bic	src, src, #3
+		load1l	r4
+		cmp	ip, #2
+		beq	.src2_aligned
+		bhi	.src3_aligned
+		mov	r4, r4, lsr #8		@ C = 0
+		bics	ip, len, #15
+		beq	2f
+1:		load4l	r5, r6, r7, r8
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		mov	r6, r6, lsr #8
+		orr	r6, r6, r7, lsl #24
+		mov	r7, r7, lsr #8
+		orr	r7, r7, r8, lsl #24
+		stmia	dst!, {r4, r5, r6, r7}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		adcs	sum, sum, r6
+		adcs	sum, sum, r7
+		mov	r4, r8, lsr #8
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, len, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r5, r6
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		stmia	dst!, {r4, r5}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		mov	r4, r6, lsr #8
+		tst	ip, #4
+		beq	4f
+3:		load1l	r5
+		orr	r4, r4, r5, lsl #24
+		str	r4, [dst], #4
+		adcs	sum, sum, r4
+		mov	r4, r5, lsr #8
+4:		ands	len, len, #3
+		beq	.done
+		tst	len, #2
+		beq	.exit
+		adcs	sum, sum, r4, lsl #16
+		strb	r4, [dst], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [dst], #1
+		mov	r4, r4, lsr #8
+		b	.exit
+
+.src2_aligned:	mov	r4, r4, lsr #16
+		adds	sum, sum, #0
+		bics	ip, len, #15
+		beq	2f
+1:		load4l	r5, r6, r7, r8
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		mov	r6, r6, lsr #16
+		orr	r6, r6, r7, lsl #16
+		mov	r7, r7, lsr #16
+		orr	r7, r7, r8, lsl #16
+		stmia	dst!, {r4, r5, r6, r7}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		adcs	sum, sum, r6
+		adcs	sum, sum, r7
+		mov	r4, r8, lsr #16
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, len, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r5, r6
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		stmia	dst!, {r4, r5}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		mov	r4, r6, lsr #16
+		tst	ip, #4
+		beq	4f
+3:		load1l	r5
+		orr	r4, r4, r5, lsl #16
+		str	r4, [dst], #4
+		adcs	sum, sum, r4
+		mov	r4, r5, lsr #16
+4:		ands	len, len, #3
+		beq	.done
+		tst	len, #2
+		beq	.exit
+		adcs	sum, sum, r4, lsl #16
+		strb	r4, [dst], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [dst], #1
+		tst	len, #1
+		beq	.done
+		load1b	r4
+		b	.exit
+
+.src3_aligned:	mov	r4, r4, lsr #24
+		adds	sum, sum, #0
+		bics	ip, len, #15
+		beq	2f
+1:		load4l	r5, r6, r7, r8
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		mov	r6, r6, lsr #24
+		orr	r6, r6, r7, lsl #8
+		mov	r7, r7, lsr #24
+		orr	r7, r7, r8, lsl #8
+		stmia	dst!, {r4, r5, r6, r7}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		adcs	sum, sum, r6
+		adcs	sum, sum, r7
+		mov	r4, r8, lsr #24
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, len, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r5, r6
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		stmia	dst!, {r4, r5}
+		adcs	sum, sum, r4
+		adcs	sum, sum, r5
+		mov	r4, r6, lsr #24
+		tst	ip, #4
+		beq	4f
+3:		load1l	r5
+		orr	r4, r4, r5, lsl #8
+		str	r4, [dst], #4
+		adcs	sum, sum, r4
+		mov	r4, r5, lsr #24
+4:		ands	len, len, #3
+		beq	.done
+		tst	len, #2
+		beq	.exit
+		adcs	sum, sum, r4, lsl #16
+		strb	r4, [dst], #1
+		load1l	r4
+		strb	r4, [dst], #1
+		adcs	sum, sum, r4, lsl #24
+		mov	r4, r4, lsr #8
+		b	.exit
diff -u --recursive --new-file v2.4.4/linux/arch/arm/lib/csumpartialcopyuser.S linux/arch/arm/lib/csumpartialcopyuser.S
--- v2.4.4/linux/arch/arm/lib/csumpartialcopyuser.S	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/lib/csumpartialcopyuser.S	Wed May 16 15:25:16 2001
@@ -15,10 +15,6 @@
 
 		.text
 
-/* Function: __u32 csum_partial_copy_from_user (const char *src, char *dst, int len, __u32 sum, int *err_ptr)
- * Params  : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err
- * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
- */
 #if defined(CONFIG_CPU_32)
 
 		.macro	save_regs
@@ -152,253 +148,16 @@
 #error Unknown CPU architecture
 #endif
 
-ENTRY(csum_partial_copy_from_user)
-		mov	ip, sp
-		save_regs
-		sub	fp, ip, #4
-		cmp	r2, #4
-		blt	.too_small
-		tst	r1, #2			@ Test destination alignment
-		beq	.dst_aligned
-		load2b	ip, r8
-		subs	r2, r2, #2		@ We do not know if SRC is aligned...
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		adcs	r3, r3, #0
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1		@ Destination now aligned
-.dst_aligned:	tst	r0, #3
-		bne	.src_not_aligned
-		adds	r3, r3, #0
-		bics	ip, r2, #15		@ Routine for src & dst aligned
-		beq	2f
-1:		load4l	r4, r5, r6, r7
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r4, r5
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		tst	ip, #4
-		beq	4f
-3:		load1l	r4
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		load1l	r4
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-.exit:		tst	r2, #1
-		strneb	r4, [r1], #1
-		andne	r4, r4, #255
-		adcnes	r3, r3, r4
-		adcs	r0, r3, #0
-		load_regs	ea
-
-.too_small:	teq	r2, #0
-		load_regs	eqea
-		cmp	r2, #2
-		blt	.too_small1
-		load2b	ip, r8
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		strb	ip, [r1], #1
-		strb	r8, [r1], #1
-		tst	r2, #1
-.too_small1:				@ C = 0
-		beq	.csum_exit
-		load1b	ip
-		strb	ip, [r1], #1
-		adcs	r3, r3, ip
-.csum_exit:	adc	r0, r3, #0
-		load_regs	ea
-
-.src_not_aligned:
-		cmp	r2, #4
-		blt	.too_small
-		and	ip, r0, #3
-		bic	r0, r0, #3
-		load1l	r4
-		cmp	ip, #2
-		beq	.src2_aligned
-		bhi	.src3_aligned
-		mov	r4, r4, lsr #8
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		mov	r7, r7, lsr #8
-		orr	r7, r7, r8, lsl #24
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #8
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #8
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #24
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #8
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		b	.exit
-
-.src2_aligned:	mov	r4, r4, lsr #16
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		mov	r7, r7, lsr #16
-		orr	r7, r7, r8, lsl #16
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #16
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #16
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #16
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #16
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		tst	r2, #1
-		adceq	r0, r3, #0
-		load_regs	eqea
-		load1b	r4
-		b	.exit
-
-.src3_aligned:	mov	r4, r4, lsr #24
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		mov	r7, r7, lsr #24
-		orr	r7, r7, r8, lsl #8
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #24
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #24
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #8
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #24
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		load1l	r4
-		strb	r4, [r1], #1
-		adcs	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		b	.exit
+/*
+ * unsigned int
+ * csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr)
+ *  r0 = src, r1 = dst, r2 = len, r3 = sum, [sp] = *err_ptr
+ *  Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
+ */
+
+#define FN_ENTRY	ENTRY(csum_partial_copy_from_user)
+
+#include "csumpartialcopygeneric.S"
 
 /*
  * FIXME: minor buglet here
@@ -411,13 +170,13 @@
 #endif
 		.align	4
 6001:		mov	r4, #-EFAULT
-		ldr	r5, [fp, #4]
+		ldr	r5, [fp, #4]		@ *err_ptr
 		str	r4, [r5]
-		ldmia	sp, {r1, r2}		@ retrieve original arguments
+		ldmia	sp, {r1, r2}		@ retrieve dst, len
 		add	r2, r2, r1
-		mov	r3, #0			@ zero the buffer
+		mov	r0, #0			@ zero the buffer
 6002:		teq	r2, r1
-		strneb	r3, [r1], #1
+		strneb	r0, [r1], #1
 		bne	6002b
 		load_regs	ea
 #if defined(CONFIG_CPU_32)
diff -u --recursive --new-file v2.4.4/linux/arch/arm/mach-ebsa110/io.c linux/arch/arm/mach-ebsa110/io.c
--- v2.4.4/linux/arch/arm/mach-ebsa110/io.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mach-ebsa110/io.c	Sun May 20 12:11:38 2001
@@ -20,7 +20,6 @@
  * Luckily, the work-around for this is not too horrible.  See
  * __isamem_convert_addr for the details.
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.4/linux/arch/arm/mach-sa1100/dma.h linux/arch/arm/mach-sa1100/dma.h
--- v2.4.4/linux/arch/arm/mach-sa1100/dma.h	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mach-sa1100/dma.h	Sun May 20 12:11:38 2001
@@ -7,6 +7,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/config.h>
 
 /*
  * DMA channel structure.
diff -u --recursive --new-file v2.4.4/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.4.4/linux/arch/arm/mm/fault-armv.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mm/fault-armv.c	Wed May 16 15:25:16 2001
@@ -132,7 +132,7 @@
 
 #define get8_unaligned_check(val,addr,err)		\
 	__asm__(					\
-	"1:	ldrb	%1, [%2]\n"			\
+	"1:	ldrb	%1, [%2], #1\n"			\
 	"2:\n"						\
 	"	.section .fixup,\"ax\"\n"		\
 	"	.align	2\n"				\
@@ -148,7 +148,7 @@
 
 #define get8t_unaligned_check(val,addr,err)		\
 	__asm__(					\
-	"1:	ldrbt	%1, [%2]\n"			\
+	"1:	ldrbt	%1, [%2], #1\n"			\
 	"2:\n"						\
 	"	.section .fixup,\"ax\"\n"		\
 	"	.align	2\n"				\
diff -u --recursive --new-file v2.4.4/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- v2.4.4/linux/arch/arm/vmlinux-armv.lds.in	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/vmlinux-armv.lds.in	Wed May 16 15:25:16 2001
@@ -44,11 +44,12 @@
 			*(.rodata)
 			*(.glue_7)
 			*(.glue_7t)
-			*(.kstrtab)
 		*(.got)			/* Global offset table		*/
 
 		_etext = .;		/* End of text section		*/
 	}
+
+	.kstrtab : { *(.kstrtab) }
 
 	. = ALIGN(16);
 	__ex_table : {			/* Exception table		*/
diff -u --recursive --new-file v2.4.4/linux/arch/cris/Makefile linux/arch/cris/Makefile
--- v2.4.4/linux/arch/cris/Makefile	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/Makefile	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.15 2001/02/16 17:50:04 larsv Exp $
+# $Id: Makefile,v 1.18 2001/04/17 13:58:38 orjanf Exp $
 # cris/Makefile
 #
 # This file is included by the global makefile so that you can add your own
@@ -25,8 +25,8 @@
 # regenerating stuff (even for incremental linking of subsystems!) is
 # even more nauseating.
 LD = if [ ! -e $(LD_SCRIPT).tmp -o $(LD_SCRIPT) -nt $(LD_SCRIPT).tmp ]; then \
-          sed -e s/@ETRAX_DRAM_VIRTUAL_BASE@/0x$(ETRAX_DRAM_VIRTUAL_BASE)/ \
-              -e s/@ETRAX_DRAM_SIZE_M@/$(ETRAX_DRAM_SIZE)/ \
+          sed -e s/@CONFIG_ETRAX_DRAM_VIRTUAL_BASE@/0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)/ \
+              -e s/@CONFIG_ETRAX_DRAM_SIZE_M@/$(CONFIG_ETRAX_DRAM_SIZE)/ \
               < $(LD_SCRIPT) > $(LD_SCRIPT).tmp; \
      else true; \
      fi && $(CROSS_COMPILE)ld -mcriself
@@ -42,7 +42,7 @@
 
 CFLAGS := $(CFLAGS) -march=v10 -fno-strict-aliasing -pipe -D__linux__
 
-ifdef CONFIG_KGDB
+ifdef CONFIG_ETRAX_KGDB
 CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
 CFLAGS += -fno-omit-frame-pointer
 endif
@@ -76,7 +76,7 @@
 
 cramfs:
 ## cramfs      - Creates a cramfs image
-	mkcramfs -b 8192 root cramfs.img
+	mkcramfs -b 8192 -m romfs_meta.txt root cramfs.img
 	cat vmlinux.bin cramfs.img >timage
 
 clinux: vmlinux.bin decompress.bin rescue.bin
diff -u --recursive --new-file v2.4.4/linux/arch/cris/boot/compressed/Makefile linux/arch/cris/boot/compressed/Makefile
--- v2.4.4/linux/arch/cris/boot/compressed/Makefile	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/compressed/Makefile	Tue May  1 16:04:56 2001
@@ -24,7 +24,7 @@
 
 
 vmlinuz: piggy.img decompress.bin
-	cat decompress.bin piggy.img $(TOPDIR)/cramfs.img > vmlinuz
+	cat decompress.bin piggy.img > vmlinuz
 	rm -f piggy.img
 
 head.o: head.S
diff -u --recursive --new-file v2.4.4/linux/arch/cris/boot/compressed/head.S linux/arch/cris/boot/compressed/head.S
--- v2.4.4/linux/arch/cris/boot/compressed/head.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/compressed/head.S	Tue May  1 16:04:56 2001
@@ -1,16 +1,19 @@
 /*
- *  arch/etrax100/boot/compressed/head.S
+ *  arch/cris/boot/compressed/head.S
  *
- *  Copyright (C) 1999 Axis Communications AB
+ *  Copyright (C) 1999, 2001 Axis Communications AB
  *
  *  Code that sets up the DRAM registers, calls the
  *  decompressor to unpack the piggybacked kernel, and jumps.
  *
  */
 
+#include <linux/config.h>
 #define ASSEMBLER_MACROS_ONLY
 #include <asm/sv_addr_ag.h>
 
+#define RAM_INIT_MAGIC 0x56902387
+	
 	;; Exported symbols
 	
 	.globl	_input_data
@@ -21,23 +24,28 @@
 	nop
 	di
 
-	;; We need to initialze DRAM registers before we start using the DRAM
-#include "../../lib/dram_init.S"
+;; We need to initialze DRAM registers before we start using the DRAM
 	
-dram_init_finished:
+	cmp.d	RAM_INIT_MAGIC, r8	; Already initialized?
+	beq	dram_init_finished
+	nop
+	
+#include "../../lib/dram_init.S"
 	
+dram_init_finished:	
+		
 	;; Initiate the PA and PB ports
 
-	move.b   DEF_R_PORT_PA_DATA, r0
+	move.b   CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r0
 	move.b   r0, [R_PORT_PA_DATA]
 
-	move.b   DEF_R_PORT_PA_DIR, r0
+	move.b   CONFIG_ETRAX_DEF_R_PORT_PA_DIR, r0
 	move.b   r0, [R_PORT_PA_DIR]
 
-	move.b   DEF_R_PORT_PB_DATA, r0
+	move.b   CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r0
 	move.b   r0, [R_PORT_PB_DATA]
 
-	move.b   DEF_R_PORT_PB_DIR, r0
+	move.b   CONFIG_ETRAX_DEF_R_PORT_PB_DIR, r0
 	move.b   r0, [R_PORT_PB_DIR]
 
 	;; Setup the stack to a suitably high address.
@@ -70,6 +78,7 @@
 
 	move.d	r5, [_input_data] ; for the decompressor
 
+
 	;; Clear the decompressors BSS (between _edata and _end)
 	
 	moveq	0, r0
@@ -81,19 +90,22 @@
 	nop
 	
 	;; Do the decompression and save compressed size in _inptr
-	
+
 	jsr	_decompress_kernel
 	
-	;; Put start address of cramfs in r9 so the kernel can use it
+	;; Put start address of root partition in r9 so the kernel can use it
 	;; when mounting from flash
 
 	move.d	[_input_data], r9	; flash address of compressed kernel
 	add.d	[_inptr], r9		; size of compressed kernel
-
+	 
 	;; Enter the decompressed kernel
+	move.d	RAM_INIT_MAGIC, r8	; Tell kernel that DRAM is initialized
 	jump	0x40004000	; kernel is linked to this address
 	
 	.data
 
 _input_data:
 	.dword	0		; used by the decompressor
+
+#include "../../lib/hw_settings.S"
diff -u --recursive --new-file v2.4.4/linux/arch/cris/boot/compressed/misc.c linux/arch/cris/boot/compressed/misc.c
--- v2.4.4/linux/arch/cris/boot/compressed/misc.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/compressed/misc.c	Tue May  1 16:04:56 2001
@@ -1,7 +1,7 @@
 /*
  * misc.c
  *
- * $Id: misc.c,v 1.3 2001/01/17 15:54:18 jonashg Exp $
+ * $Id: misc.c,v 1.6 2001/04/09 10:00:21 starvik Exp $
  * 
  * This is a collection of several routines from gzip-1.0.3 
  * adapted for Linux.
@@ -21,6 +21,7 @@
 #define KERNEL_LOAD_ADR 0x40004000
 
 #include <linux/config.h>
+
 #include <linux/types.h>
 #include <asm/svinto.h>
 
@@ -143,21 +144,21 @@
 static void
 puts(const char *s)
 {
-#ifndef CONFIG_DEBUG_PORT_NULL
+#ifndef CONFIG_ETRAX_DEBUG_PORT_NULL
 	while(*s) {
-#ifdef CONFIG_DEBUG_PORT0
+#ifdef CONFIG_ETRAX_DEBUG_PORT0
 		while(!(*R_SERIAL0_STATUS & (1 << 5))) ;
 		*R_SERIAL0_TR_DATA = *s++;
 #endif
-#ifdef CONFIG_DEBUG_PORT1
+#ifdef CONFIG_ETRAX_DEBUG_PORT1
 		while(!(*R_SERIAL1_STATUS & (1 << 5))) ;
 		*R_SERIAL1_TR_DATA = *s++;
 #endif
-#ifdef CONFIG_DEBUG_PORT2
+#ifdef CONFIG_ETRAX_DEBUG_PORT2
 		while(!(*R_SERIAL2_STATUS & (1 << 5))) ;
 		*R_SERIAL2_TR_DATA = *s++;
 #endif
-#ifdef CONFIG_DEBUG_PORT3
+#ifdef CONFIG_ETRAX_DEBUG_PORT3
 		while(!(*R_SERIAL3_STATUS & (1 << 5))) ;
 		*R_SERIAL3_TR_DATA = *s++;
 #endif
@@ -227,33 +228,45 @@
 void
 decompress_kernel()
 {
+	char revision;
+	
 	/* input_data is set in head.S */
 	inbuf = input_data;
 
-#ifdef CONFIG_DEBUG_PORT0
+#ifdef CONFIG_ETRAX_DEBUG_PORT0
 	*R_SERIAL0_XOFF = 0;
 	*R_SERIAL0_BAUD = 0x99;
 	*R_SERIAL0_TR_CTRL = 0x40;
 #endif
-#ifdef CONFIG_DEBUG_PORT1
+#ifdef CONFIG_ETRAX_DEBUG_PORT1
 	*R_SERIAL1_XOFF = 0;
 	*R_SERIAL1_BAUD = 0x99;
 	*R_SERIAL1_TR_CTRL = 0x40;
 #endif
-#ifdef CONFIG_DEBUG_PORT2
+#ifdef CONFIG_ETRAX_DEBUG_PORT2
+	*R_GEN_CONFIG = 0x08;
 	*R_SERIAL2_XOFF = 0;
 	*R_SERIAL2_BAUD = 0x99;
 	*R_SERIAL2_TR_CTRL = 0x40;
 #endif
-#ifdef CONFIG_DEBUG_PORT3
+#ifdef CONFIG_ETRAX_DEBUG_PORT3
+	*R_GEN_CONFIG = 0x100;
 	*R_SERIAL3_XOFF = 0;
 	*R_SERIAL3_BAUD = 0x99;
 	*R_SERIAL3_TR_CTRL = 0x40;
 #endif
-       
+
 	setup_normal_output_buffer();
 
 	makecrc();
+
+	__asm__ volatile ("move vr,%0" : "=rm" (revision));
+	if (revision < 10)
+	{
+		puts("You need an ETRAX 100LX to run linux 2.4\n");
+		while(1);
+	}
+
 	puts("Uncompressing Linux...\n");
 	gunzip();
 	puts("Done. Now booting the kernel.\n");
diff -u --recursive --new-file v2.4.4/linux/arch/cris/boot/rescue/head.S linux/arch/cris/boot/rescue/head.S
--- v2.4.4/linux/arch/cris/boot/rescue/head.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/rescue/head.S	Tue May  1 16:04:56 2001
@@ -1,66 +1,67 @@
-	;; $Id: head.S,v 1.3 2001/02/14 16:57:25 larsv Exp $
-	;; 
-	;; Rescue code, made to reside at the beginning of the
-	;; flash-memory. when it starts, it checks a partition
-	;; table at the first sector after the rescue sector.
-	;; the partition table was generated by the product builder
-	;; script and contains offsets, lengths, types and checksums
-	;; for each partition that this code should check.
-	;;
-	;; If any of the checksums fail, we assume the flash is so
-	;; corrupt that we cant use it to boot into the ftp flash
-	;; loader, and instead we initialize the serial port to
-	;; receive a flash-loader and new flash image. we dont include
-	;; any flash code here, but just accept a certain amount of
-	;; bytes from the serial port and jump into it. the downloaded
-	;; code is put in the cache.
-	;;
-	;; The partitiontable is designed so that it is transparent to
-	;; code execution - it has a relative branch opcode in the
-	;; beginning that jumps over it. each entry contains extra
-	;; data so we can add stuff later.
-	;;
-	;; Partition table format:
-	;;
-	;;     Code transparency:
-	;; 
-	;;     2 bytes    [opcode 'nop']
-	;;     2 bytes    [opcode 'di']
-	;;     4 bytes    [opcode 'ba <offset>', 8-bit or 16-bit version]
-	;;     2 bytes    [opcode 'nop', delay slot]
-	;;
-	;;     Table validation (at +10):	
-	;; 
-	;;     2 bytes    [magic/version word for partitiontable - 0xef, 0xbe]
-	;;     2 bytes    [length of all entries plus the end marker]
-	;;     4 bytes    [checksum for the partitiontable itself]
-	;;
-	;;     Entries, each with the following format, last has offset -1:	
-	;;    
-	;;        4 bytes    [offset in bytes, from start of flash]
-	;;        4 bytes    [length in bytes of partition]
-	;;        4 bytes    [checksum, simple longword sum]
-	;;        2 bytes    [partition type]
-	;;        2 bytes    [flags, only bit 0 used, ro/rw = 1/0]
-	;;        16 bytes   [reserved for future use]
-	;;
-	;;     End marker
-	;;
-	;;        4 bytes    [-1]
-	;; 
-	;;	 10 bytes    [0, padding]
-	;; 
-	;; Bit 0 in flags signifies RW or RO. The rescue code only bothers
-	;; to check the checksum for RO partitions, since the others will
-	;; change its data without updating the checksums. A 1 in bit 0
-	;; means RO, 0 means RW. That way, it is possible to set a partition
-	;; in RO mode initially, and later mark it as RW, since you can always
-	;; write 0's to the flash.
-	;;
-	;; During the wait for serial input, the status LED will flash so the
-	;; user knows something went wrong.
-	;; 
-	;; Copyright (C) 1999 Axis Communications AB
+/* $Id: head.S,v 1.7 2001/04/18 12:05:07 bjornw Exp $
+ * 
+ * Rescue code, made to reside at the beginning of the
+ * flash-memory. when it starts, it checks a partition
+ * table at the first sector after the rescue sector.
+ * the partition table was generated by the product builder
+ * script and contains offsets, lengths, types and checksums
+ * for each partition that this code should check.
+ *
+ * If any of the checksums fail, we assume the flash is so
+ * corrupt that we cant use it to boot into the ftp flash
+ * loader, and instead we initialize the serial port to
+ * receive a flash-loader and new flash image. we dont include
+ * any flash code here, but just accept a certain amount of
+ * bytes from the serial port and jump into it. the downloaded
+ * code is put in the cache.
+ *
+ * The partitiontable is designed so that it is transparent to
+ * code execution - it has a relative branch opcode in the
+ * beginning that jumps over it. each entry contains extra
+ * data so we can add stuff later.
+ *
+ * Partition table format:
+ *
+ *     Code transparency:
+ * 
+ *     2 bytes    [opcode 'nop']
+ *     2 bytes    [opcode 'di']
+ *     4 bytes    [opcode 'ba <offset>', 8-bit or 16-bit version]
+ *     2 bytes    [opcode 'nop', delay slot]
+ *
+ *     Table validation (at +10):	
+ * 
+ *     2 bytes    [magic/version word for partitiontable - 0xef, 0xbe]
+ *     2 bytes    [length of all entries plus the end marker]
+ *     4 bytes    [checksum for the partitiontable itself]
+ *
+ *     Entries, each with the following format, last has offset -1:	
+ *    
+ *        4 bytes    [offset in bytes, from start of flash]
+ *        4 bytes    [length in bytes of partition]
+ *        4 bytes    [checksum, simple longword sum]
+ *        2 bytes    [partition type]
+ *        2 bytes    [flags, only bit 0 used, ro/rw = 1/0]
+ *        16 bytes   [reserved for future use]
+ *
+ *     End marker
+ *
+ *        4 bytes    [-1]
+ * 
+ *	 10 bytes    [0, padding]
+ * 
+ * Bit 0 in flags signifies RW or RO. The rescue code only bothers
+ * to check the checksum for RO partitions, since the others will
+ * change its data without updating the checksums. A 1 in bit 0
+ * means RO, 0 means RW. That way, it is possible to set a partition
+ * in RO mode initially, and later mark it as RW, since you can always
+ * write 0's to the flash.
+ *
+ * During the wait for serial input, the status LED will flash so the
+ * user knows something went wrong.
+ * 
+ * Copyright (C) 1999,2001 Axis Communications AB
+ */
 
 #include <linux/config.h>
 #define ASSEMBLER_MACROS_ONLY
@@ -69,7 +70,7 @@
 	;; The partitiontable is looked for at the first sector after the boot
 	;; sector. Sector size is 65536 bytes in all flashes we use.
 		
-#define PTABLE_START 0x10000
+#define PTABLE_START CONFIG_ETRAX_PTABLE_SECTOR
 #define PTABLE_MAGIC 0xbeef
 
 	;; The normal Etrax100 on-chip boot ROM does serial boot at 0x380000f0.
@@ -82,28 +83,28 @@
 #define CODE_START 0x40000000
 #define CODE_LENGTH 784
 
-#ifdef CONFIG_RESCUE_SER0
+#ifdef CONFIG_ETRAX_RESCUE_SER0
 #define SERXOFF R_SERIAL0_XOFF
 #define SERBAUD R_SERIAL0_BAUD
 #define SERRECC R_SERIAL0_REC_CTRL
 #define SERRDAT R_SERIAL0_REC_DATA
 #define SERSTAT R_SERIAL0_STATUS
 #endif
-#ifdef CONFIG_RESCUE_SER1
+#ifdef CONFIG_ETRAX_RESCUE_SER1
 #define SERXOFF R_SERIAL1_XOFF
 #define SERBAUD R_SERIAL1_BAUD
 #define SERRECC R_SERIAL1_REC_CTRL
 #define SERRDAT R_SERIAL1_REC_DATA
 #define SERSTAT R_SERIAL1_STATUS
 #endif
-#ifdef CONFIG_RESCUE_SER2
+#ifdef CONFIG_ETRAX_RESCUE_SER2
 #define SERXOFF R_SERIAL2_XOFF
 #define SERBAUD R_SERIAL2_BAUD
 #define SERRECC R_SERIAL2_REC_CTRL
 #define SERRDAT R_SERIAL2_REC_DATA
 #define SERSTAT R_SERIAL2_STATUS
 #endif	
-#ifdef CONFIG_RESCUE_SER3
+#ifdef CONFIG_ETRAX_RESCUE_SER3
 #define SERXOFF R_SERIAL3_XOFF
 #define SERBAUD R_SERIAL3_BAUD
 #define SERRECC R_SERIAL3_REC_CTRL
@@ -112,7 +113,8 @@
 #endif
 
 #define NOP_DI 0xf025050f
-	
+#define RAM_INIT_MAGIC 0x56902387
+		
 	.text
 	
 	;; This is the entry point of the rescue code
@@ -221,14 +223,14 @@
 	;; setup port PA and PB default initial directions and data
 	;; (so we can flash LEDs, and so that DTR and others are set)
 	
-	move.b	DEF_R_PORT_PA_DIR, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DIR, r0
 	move.b	r0, [R_PORT_PA_DIR]
-	move.b	DEF_R_PORT_PA_DATA, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r0
 	move.b	r0, [R_PORT_PA_DATA]
 	
-	move.b	DEF_R_PORT_PB_DIR, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DIR, r0
 	move.b	r0, [R_PORT_PB_DIR]
-	move.b	DEF_R_PORT_PB_DATA, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r0
 	move.b	r0, [R_PORT_PB_DATA]
 
 	;; setup the serial port at 115200 baud
@@ -250,10 +252,10 @@
 	addq	1, r1
 #ifndef CONFIG_ETRAX_NO_LEDS
 #ifdef CONFIG_ETRAX_PA_LEDS
-	move.b	DEF_R_PORT_PA_DATA, r2
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r2
 #endif
 #ifdef CONFIG_ETRAX_PB_LEDS
-	move.b	DEF_R_PORT_PB_DATA, r2
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r2
 #endif
 	move.d	(1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), r0
 	btstq	16, r1
@@ -293,7 +295,8 @@
 	nop
 
 	;; jump into downloaded code
-	
+
+	move.d	RAM_INIT_MAGIC, r8	; Tell next product that DRAM is initialized
 	jump	CODE_START
 
 flash_ok:
@@ -303,7 +306,8 @@
 	bne	1f
 	nop
 	move.d	PTABLE_START, r7; otherwise use the ptable start
-1:	
+1:
+	move.d	RAM_INIT_MAGIC, r8	; Tell next product that DRAM is initialized
 	jump	r7		; boot!
 
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/boot/rescue/kimagerescue.S linux/arch/cris/boot/rescue/kimagerescue.S
--- v2.4.4/linux/arch/cris/boot/rescue/kimagerescue.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/rescue/kimagerescue.S	Tue May  1 16:04:56 2001
@@ -1,41 +1,42 @@
-	;; $Id: kimagerescue.S,v 1.2 2001/02/14 16:57:25 larsv Exp $
-	;; 
-	;; Rescue code to be prepended on a kimage and copied to the
-	;; rescue serial port.
-	;; This is called from the rescue code, it will copy received data to
-	;; 4000500 and after a timeout jump to it.
-	
+/* $Id: kimagerescue.S,v 1.4 2001/04/18 12:04:46 bjornw Exp $
+ * 
+ * Rescue code to be prepended on a kimage and copied to the
+ * rescue serial port.
+ * This is called from the rescue code, it will copy received data to
+ * 4004000 and after a timeout jump to it.
+ */
+
 #include <linux/config.h>
 #define ASSEMBLER_MACROS_ONLY
 #include <asm/sv_addr_ag.h>
 
-#define CODE_START 0x40000500
+#define CODE_START 0x40004000
 #define CODE_LENGTH 784
 #define TIMEOUT_VALUE 1000
 	
 		
-#ifdef CONFIG_RESCUE_SER0
+#ifdef CONFIG_ETRAX_RESCUE_SER0
 #define SERXOFF R_SERIAL0_XOFF
 #define SERBAUD R_SERIAL0_BAUD
 #define SERRECC R_SERIAL0_REC_CTRL
 #define SERRDAT R_SERIAL0_REC_DATA
 #define SERSTAT R_SERIAL0_STATUS
 #endif
-#ifdef CONFIG_RESCUE_SER1
+#ifdef CONFIG_ETRAX_RESCUE_SER1
 #define SERXOFF R_SERIAL1_XOFF
 #define SERBAUD R_SERIAL1_BAUD
 #define SERRECC R_SERIAL1_REC_CTRL
 #define SERRDAT R_SERIAL1_REC_DATA
 #define SERSTAT R_SERIAL1_STATUS
 #endif
-#ifdef CONFIG_RESCUE_SER2
+#ifdef CONFIG_ETRAX_RESCUE_SER2
 #define SERXOFF R_SERIAL2_XOFF
 #define SERBAUD R_SERIAL2_BAUD
 #define SERRECC R_SERIAL2_REC_CTRL
 #define SERRDAT R_SERIAL2_REC_DATA
 #define SERSTAT R_SERIAL2_STATUS
 #endif	
-#ifdef CONFIG_RESCUE_SER3
+#ifdef CONFIG_ETRAX_RESCUE_SER3
 #define SERXOFF R_SERIAL3_XOFF
 #define SERBAUD R_SERIAL3_BAUD
 #define SERRECC R_SERIAL3_REC_CTRL
@@ -55,14 +56,14 @@
 	;; setup port PA and PB default initial directions and data
 	;; (so we can flash LEDs, and so that DTR and others are set)
 	
-	move.b	DEF_R_PORT_PA_DIR, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DIR, r0
 	move.b	r0, [R_PORT_PA_DIR]
-	move.b	DEF_R_PORT_PA_DATA, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r0
 	move.b	r0, [R_PORT_PA_DATA]
 	
-	move.b	DEF_R_PORT_PB_DIR, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DIR, r0
 	move.b	r0, [R_PORT_PB_DIR]
-	move.b	DEF_R_PORT_PB_DATA, r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r0
 	move.b	r0, [R_PORT_PB_DATA]
 	
 	;; We need to setup the bus registers before we start using the DRAM
@@ -99,10 +100,10 @@
 	nop
 #ifndef CONFIG_ETRAX_NO_LEDS
 #ifdef CONFIG_ETRAX_PA_LEDS
-	move.b	DEF_R_PORT_PA_DATA, r2
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r2
 #endif
 #ifdef CONFIG_ETRAX_PB_LEDS
-	move.b	DEF_R_PORT_PB_DATA, r2
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r2
 #endif
 	move.d	(1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), r0
 	btstq	16, r1
diff -u --recursive --new-file v2.4.4/linux/arch/cris/boot/rescue/testrescue.S linux/arch/cris/boot/rescue/testrescue.S
--- v2.4.4/linux/arch/cris/boot/rescue/testrescue.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/rescue/testrescue.S	Tue May  1 16:04:56 2001
@@ -1,9 +1,10 @@
-	;; $Id: testrescue.S,v 1.1 2001/01/31 15:32:09 johana Exp $
-	;;
-	;; Simple testcode to download by the rescue block.
-	;; Just lits some LEDs to show it was downloaded correctly.
-	;; 
-	;; Copyright (C) 1999 Axis Communications AB
+/* $Id: testrescue.S,v 1.2 2001/04/18 12:05:07 bjornw Exp $
+ *
+ * Simple testcode to download by the rescue block.
+ * Just lits some LEDs to show it was downloaded correctly.
+ * 
+ * Copyright (C) 1999 Axis Communications AB
+ */
 
 #define ASSEMBLER_MACROS_ONLY
 #include <asm/sv_addr_ag.h>
diff -u --recursive --new-file v2.4.4/linux/arch/cris/config.in linux/arch/cris/config.in
--- v2.4.4/linux/arch/cris/config.in	Tue Apr 17 17:19:24 2001
+++ linux/arch/cris/config.in	Tue May  1 16:04:56 2001
@@ -24,14 +24,10 @@
   tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
 fi
 
-bool 'Use kernel gdb debugger' CONFIG_KGDB
+bool 'Use kernel gdb debugger' CONFIG_ETRAX_KGDB
 
 bool 'Enable Etrax100 watchdog' CONFIG_ETRAX_WATCHDOG
 
-bool 'Use serial console (on the debug port)' CONFIG_USE_SERIAL_CONSOLE
-
-bool 'Use in-kernel ifconfig/route setup' CONFIG_KERNEL_IFCONFIG
-
 endmenu
 
 mainmenu_option next_comment
@@ -46,20 +42,19 @@
 
 if [ "$CONFIG_ETRAX100LX" = "y" -o "$CONFIG_SVINTO_SIM" = "y" ]; then
 	define_bool CONFIG_CRIS_LOW_MAP y
-	define_hex  ETRAX_DRAM_VIRTUAL_BASE 60000000
+	define_hex  CONFIG_ETRAX_DRAM_VIRTUAL_BASE 60000000
 else
-	define_hex  ETRAX_DRAM_VIRTUAL_BASE c0000000
+	define_hex  CONFIG_ETRAX_DRAM_VIRTUAL_BASE c0000000
 fi
 
-int 'DRAM size (dec, in MB)' ETRAX_DRAM_SIZE 8
+int 'DRAM size (dec, in MB)' CONFIG_ETRAX_DRAM_SIZE 8
 
-int 'Max possible flash size (dec, in MB)' CONFIG_ETRAX_FLASH_LENGTH 2
 int 'Buswidth of flash in bytes' CONFIG_ETRAX_FLASH_BUSWIDTH 2
 
 choice 'Product LED port' \
 	"Port-PA-LEDs	CONFIG_ETRAX_PA_LEDS	\
 	 Port-PB-LEDs	CONFIG_ETRAX_PB_LEDS	\
-	 Mem-0x90000000-LEDs	CONFIG_ETRAX_90000000_LEDS  \
+	 Port-CSP0-LEDs	CONFIG_ETRAX_CSP0_LEDS  \
 	 None	CONFIG_ETRAX_NO_LEDS" Port-PA-LEDs
 
 if [ "$CONFIG_ETRAX_NO_LEDS" != "y" ]; then
@@ -71,38 +66,54 @@
   int '  Third red LED bit' CONFIG_ETRAX_LED3G 2
 fi
 
+if [ "$CONFIG_ETRAX_CSP0_LEDS" = "y" ]; then
+  int '  Fourth red LED bit' CONFIG_ETRAX_LED4R 2
+  int '  Fourth green LED bit' CONFIG_ETRAX_LED4G 2
+  int '  Fifth red LED bit' CONFIG_ETRAX_LED5R 2
+  int '  Fifth green LED bit' CONFIG_ETRAX_LED5G 2
+  int '  Sixth red LED bit' CONFIG_ETRAX_LED6R 2
+  int '  Sixth green LED bit' CONFIG_ETRAX_LED6G 2
+  int '  Seventh red LED bit' CONFIG_ETRAX_LED7R 2
+  int '  Seventh green LED bit' CONFIG_ETRAX_LED7G 2
+  int '  Eigth yellow LED bit' CONFIG_ETRAX_LED8Y 2
+  int '  Ninth yellow LED bit' CONFIG_ETRAX_LED9Y 2
+  int '  Tenth yellow LED bit' CONFIG_ETRAX_LED10Y 2
+  int '  Eleventh yellow LED bit' CONFIG_ETRAX_LED11Y 2
+  int '  Twelfth red LED bit' CONFIG_ETRAX_LED12R 2
+fi  
+
 choice 'Product debug-port' \
-	"Serial-0	CONFIG_DEBUG_PORT0	\
-	 Serial-1	CONFIG_DEBUG_PORT1	\
-	 Serial-2	CONFIG_DEBUG_PORT2	\
-	 Serial-3	CONFIG_DEBUG_PORT3	\
-	 disabled	CONFIG_DEBUG_PORT_NULL" Serial-0 
+	"Serial-0	CONFIG_ETRAX_DEBUG_PORT0	\
+	 Serial-1	CONFIG_ETRAX_DEBUG_PORT1	\
+	 Serial-2	CONFIG_ETRAX_DEBUG_PORT2	\
+	 Serial-3	CONFIG_ETRAX_DEBUG_PORT3	\
+	 disabled	CONFIG_ETRAX_DEBUG_PORT_NULL" Serial-0 
 
 choice 'Product rescue-port' \
-	"Serial-0	CONFIG_RESCUE_SER0	\
-	 Serial-1	CONFIG_RESCUE_SER1	\
-	 Serial-2	CONFIG_RESCUE_SER2	\
-	 Serial-3	CONFIG_RESCUE_SER3" Serial-0
-
-hex 'R_WAITSTATES' DEF_R_WAITSTATES 95a6
-hex 'R_BUS_CONFIG' DEF_R_BUS_CONFIG 104
-
-bool 'SDRAM support' CONFIG_SDRAM n
-if [ "$CONFIG_SDRAM" = "n" ]; then
-	hex 'R_DRAM_CONFIG' DEF_R_DRAM_CONFIG 1a200040
-	hex 'R_DRAM_TIMING' DEF_R_DRAM_TIMING 5611
+	"Serial-0	CONFIG_ETRAX_RESCUE_SER0	\
+	 Serial-1	CONFIG_ETRAX_RESCUE_SER1	\
+	 Serial-2	CONFIG_ETRAX_RESCUE_SER2	\
+	 Serial-3	CONFIG_ETRAX_RESCUE_SER3" Serial-0
+
+hex 'R_WAITSTATES' CONFIG_ETRAX_DEF_R_WAITSTATES 95a6
+hex 'R_BUS_CONFIG' CONFIG_ETRAX_DEF_R_BUS_CONFIG 104
+
+bool 'SDRAM support' CONFIG_ETRAX_SDRAM n
+if [ "$CONFIG_ETRAX_SDRAM" = "n" ]; then
+	hex 'R_DRAM_CONFIG' CONFIG_ETRAX_DEF_R_DRAM_CONFIG 1a200040
+	hex 'R_DRAM_TIMING' CONFIG_ETRAX_DEF_R_DRAM_TIMING 5611
 fi
 
-if [ "$CONFIG_SDRAM" = "y" ]; then
-	hex 'R_SDRAM_CONFIG' DEF_R_SDRAM_CONFIG d2fa7878
-	hex 'R_SDRAM_TIMING' DEF_R_SDRAM_TIMING 80004801
+if [ "$CONFIG_ETRAX_SDRAM" = "y" ]; then
+	hex 'R_SDRAM_CONFIG' CONFIG_ETRAX_DEF_R_SDRAM_CONFIG d2fa7878
+	hex 'R_SDRAM_TIMING' CONFIG_ETRAX_DEF_R_SDRAM_TIMING 80004801
 fi
 
-hex 'R_PORT_PA_DIR' DEF_R_PORT_PA_DIR 1c
-hex 'R_PORT_PA_DATA' DEF_R_PORT_PA_DATA 00
-hex 'R_PORT_PB_CONFIG' DEF_R_PORT_PB_CONFIG 00
-hex 'R_PORT_PB_DIR' DEF_R_PORT_PB_DIR 00
-hex 'R_PORT_PB_DATA' DEF_R_PORT_PB_DATA ff
+hex 'R_PORT_PA_DIR' CONFIG_ETRAX_DEF_R_PORT_PA_DIR 1c
+hex 'R_PORT_PA_DATA' CONFIG_ETRAX_DEF_R_PORT_PA_DATA 00
+hex 'R_PORT_PB_CONFIG' CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG 00
+hex 'R_PORT_PB_DIR' CONFIG_ETRAX_DEF_R_PORT_PB_DIR 00
+hex 'R_PORT_PB_DATA' CONFIG_ETRAX_DEF_R_PORT_PB_DATA ff
 
 endmenu
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/cris.ld linux/arch/cris/cris.ld
--- v2.4.4/linux/arch/cris/cris.ld	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/cris.ld	Tue May  1 16:04:56 2001
@@ -1,10 +1,16 @@
 /* ld script to make the Linux/CRIS kernel
  * Authors: Bjorn Wesen (bjornw@axis.com)
+ *
+ * It is VERY DANGEROUS to fiddle around with the symbols in this
+ * script. It is for example quite vital that all generated sections
+ * that are used are actually named here, otherwise the linker will
+ * put them at the end, where the init stuff is which is FREED after
+ * the kernel has booted. 
  */	
 
 SECTIONS
 {
-	. = @ETRAX_DRAM_VIRTUAL_BASE@;
+	. = @CONFIG_ETRAX_DRAM_VIRTUAL_BASE@;
 	_dram_start = .;
 	_ibr_start = .;
 	. = . + 0x4000; /* see head.S and pages reserved at the start */
@@ -75,5 +81,5 @@
 		*(.exitcall.exit)
         }
 
-	_dram_end = _dram_start + @ETRAX_DRAM_SIZE_M@*1024*1024;
+	_dram_end = _dram_start + @CONFIG_ETRAX_DRAM_SIZE_M@*1024*1024;
 }
diff -u --recursive --new-file v2.4.4/linux/arch/cris/defconfig linux/arch/cris/defconfig
--- v2.4.4/linux/arch/cris/defconfig	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/defconfig	Tue May  1 16:04:56 2001
@@ -15,10 +15,8 @@
 CONFIG_SYSVIPC=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_JAVA is not set
-# CONFIG_KGDB is not set
+# CONFIG_ETRAX_KGDB is not set
 # CONFIG_ETRAX_WATCHDOG is not set
-CONFIG_USE_SERIAL_CONSOLE=y
-# CONFIG_KERNEL_IFCONFIG is not set
 
 #
 # Hardware setup
@@ -27,8 +25,8 @@
 # CONFIG_ETRAX100LX_V2 is not set
 # CONFIG_SVINTO_SIM is not set
 CONFIG_CRIS_LOW_MAP=y
-ETRAX_DRAM_VIRTUAL_BASE=60000000
-ETRAX_DRAM_SIZE=8
+CONFIG_ETRAX_DRAM_VIRTUAL_BASE=60000000
+CONFIG_ETRAX_DRAM_SIZE=8
 CONFIG_ETRAX_FLASH_LENGTH=2
 CONFIG_ETRAX_FLASH_BUSWIDTH=2
 CONFIG_ETRAX_PA_LEDS=y
@@ -39,24 +37,24 @@
 CONFIG_ETRAX_LED1R=2
 CONFIG_ETRAX_LED2G=2
 CONFIG_ETRAX_LED2R=2
-CONFIG_DEBUG_PORT0=y
-# CONFIG_DEBUG_PORT1 is not set
-# CONFIG_DEBUG_PORT2 is not set
-# CONFIG_DEBUG_PORT3 is not set
-CONFIG_RESCUE_SER0=y
-# CONFIG_RESCUE_SER1 is not set
-# CONFIG_RESCUE_SER2 is not set
-# CONFIG_RESCUE_SER3 is not set
-DEF_R_WAITSTATES=95a6
-DEF_R_BUS_CONFIG=104
-# CONFIG_SDRAM is not set
-DEF_R_DRAM_CONFIG=1a200040
-DEF_R_DRAM_TIMING=5611
-DEF_R_PORT_PA_DIR=1d
-DEF_R_PORT_PA_DATA=f0
-DEF_R_PORT_PB_CONFIG=00
-DEF_R_PORT_PB_DIR=1e
-DEF_R_PORT_PB_DATA=f3
+CONFIG_ETRAX_DEBUG_PORT0=y
+# CONFIG_ETRAX_DEBUG_PORT1 is not set
+# CONFIG_ETRAX_DEBUG_PORT2 is not set
+# CONFIG_ETRAX_DEBUG_PORT3 is not set
+CONFIG_ETRAX_RESCUE_SER0=y
+# CONFIG_ETRAX_RESCUE_SER1 is not set
+# CONFIG_ETRAX_RESCUE_SER2 is not set
+# CONFIG_ETRAX_RESCUE_SER3 is not set
+CONFIG_ETRAX_DEF_R_WAITSTATES=95a6
+CONFIG_ETRAX_DEF_R_BUS_CONFIG=104
+# CONFIG_ETRAX_SDRAM is not set
+CONFIG_ETRAX_DEF_R_DRAM_CONFIG=1a200040
+CONFIG_ETRAX_DEF_R_DRAM_TIMING=5611
+CONFIG_ETRAX_DEF_R_PORT_PA_DIR=1d
+CONFIG_ETRAX_DEF_R_PORT_PA_DATA=f0
+CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=00
+CONFIG_ETRAX_DEF_R_PORT_PB_DIR=1e
+CONFIG_ETRAX_DEF_R_PORT_PB_DATA=f3
 
 #
 # Drivers for Etrax built-in interfaces
@@ -69,7 +67,7 @@
 # CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_ON_PB is not set
 # CONFIG_ETRAX_SERIAL_PORT2 is not set
 # CONFIG_ETRAX_SERIAL_PORT3 is not set
-# CONFIG_RS485 is not set
+# CONFIG_ETRAX_RS485 is not set
 # CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set
 # CONFIG_ETRAX_IDE is not set
 CONFIG_ETRAX_AXISFLASHMAP=y
@@ -84,15 +82,10 @@
 CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C=y
 CONFIG_ETRAX_GPIO=y
 CONFIG_ETRAX_PA_BUTTON_BITMASK=02
-CONFIG_PA_CHANGEABLE_DIR=00
-CONFIG_PA_CHANGEABLE_BITS=FF
-CONFIG_PB_CHANGEABLE_DIR=00
-CONFIG_PB_CHANGEABLE_BITS=FF
-# CONFIG_JULIETTE is not set
-# CONFIG_JULIETTE_VIDEO is not set
-# CONFIG_JULIETTE_CCD is not set
-# CONFIG_JULIETTE_SS1M is not set
-# CONFIG_JULIETTE_MEGCCD is not set
+CONFIG_ETRAX_PA_CHANGEABLE_DIR=00
+CONFIG_ETRAX_PA_CHANGEABLE_BITS=FF
+CONFIG_ETRAX_PB_CHANGEABLE_DIR=00
+CONFIG_ETRAX_PB_CHANGEABLE_BITS=FF
 # CONFIG_ETRAX_USB_HOST is not set
 
 #
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/Config.in linux/arch/cris/drivers/Config.in
--- v2.4.4/linux/arch/cris/drivers/Config.in	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/Config.in	Tue May  1 16:04:56 2001
@@ -1,5 +1,5 @@
 mainmenu_option next_comment
-comment 'Drivers for Etrax built-in interfaces'
+comment 'Drivers for ETRAX 100LX built-in interfaces'
 
 bool 'Ethernet support' CONFIG_ETRAX_ETHERNET
 if [ "$CONFIG_ETRAX_ETHERNET" = "y" ]; then
@@ -46,13 +46,13 @@
     fi 
   fi
   bool '  Serial port 3 enabled' CONFIG_ETRAX_SERIAL_PORT3
-  bool '  RS-485 support' CONFIG_RS485
-  if [ "$CONFIG_RS485" = "y" ]; then
-    bool '    RS-485 mode on PA' CONFIG_RS485_ON_PA
-    if [ "$CONFIG_RS485_ON_PA" = "y" ]; then
-      int '      RS-485 mode on PA bit' CONFIG_RS485_ON_PA_BIT 3
+  bool '  RS-485 support' CONFIG_ETRAX_RS485
+  if [ "$CONFIG_ETRAX_RS485" = "y" ]; then
+    bool '    RS-485 mode on PA' CONFIG_ETRAX_RS485_ON_PA
+    if [ "$CONFIG_ETRAX_RS485_ON_PA" = "y" ]; then
+      int '      RS-485 mode on PA bit' CONFIG_ETRAX_RS485_ON_PA_BIT 3
     fi
-    bool '    Disable serial receiver' CONFIG_RS485_DISABLE_RECEIVER
+    bool '    Disable serial receiver' CONFIG_ETRAX_RS485_DISABLE_RECEIVER
   fi
 fi
 
@@ -60,14 +60,29 @@
 if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL" = "y" ]; then 
   bool '  Synchronous serial port 0 enabled' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0
   if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0" = "y" ]; then
-    bool '    Synchronous serial port 0 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA y
+    bool '    Synchronous serial port 0 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA
   fi
   bool '  Synchronous serial port 1 enabled' CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1
   if [ "$CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1" = "y" ]; then
-    bool '    Synchronous serial port 1 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA y
+    bool '    Synchronous serial port 1 uses DMA' CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA
   fi 
 fi
 
+bool 'Parallel port support' CONFIG_ETRAX_PARPORT
+if [ "$CONFIG_ETRAX_PARPORT" = "y" ]; then
+	bool '  Parallel port 0 enabled' CONFIG_ETRAX_PARALLEL_PORT0
+	bool '  Parallel port 1 enabled' CONFIG_ETRAX_PARALLEL_PORT1
+# here we define the CONFIG_'s necessary to enable parallel port support
+	define_tristate CONFIG_PARPORT y
+        define_bool CONFIG_PARPORT_1284 y
+        define_tristate CONFIG_PRINTER y
+else
+	define_tristate CONFIG_PARPORT n
+        define_bool CONFIG_PARPORT_1284 n
+        define_tristate CONFIG_PRINTER n
+fi
+
+
 bool 'ATA/IDE support' CONFIG_ETRAX_IDE
 
 if [ "$CONFIG_ETRAX_IDE" = "y" ]; then
@@ -89,7 +104,8 @@
 	choice 'IDE reset pin' \
   	"Port_PB_Bit_7  CONFIG_ETRAX_IDE_PB7_RESET\
    	 Port_G_Bit_27  CONFIG_ETRAX_IDE_G27_RESET\
-   	 Port_CSE1_Bit_16  CONFIG_ETRAX_IDE_CSE1_16_RESET" Port_PB_Bit_7 
+	 Port_CSE1_Bit_16  CONFIG_ETRAX_IDE_CSE1_16_RESET\
+	 Port_CSP0_Bit_08   CONFIG_ETRAX_IDE_CSP0_8_RESET"  Port_PB_Bit_7
 else
 	define_bool CONFIG_IDE n
 fi
@@ -97,6 +113,7 @@
 bool 'Axis flash-map support' CONFIG_ETRAX_AXISFLASHMAP
 
 if [ "$CONFIG_ETRAX_AXISFLASHMAP" = "y" ]; then
+        int  '  Byte-offset of partition table sector' CONFIG_ETRAX_PTABLE_SECTOR 65536
 # here we define the CONFIG_'s necessary to enable MTD support
 # for the flash
 	define_bool CONFIG_MTD y
@@ -118,16 +135,25 @@
 	bool 'I2C uses PB not PB-I2C' CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
 fi
 
+bool 'I2C EEPROM (non-volatile RAM) support' CONFIG_ETRAX_I2C_EEPROM
+if [ "$CONFIG_ETRAX_I2C_EEPROM" = "y" ]; then
+  choice '  EEPROM size' \
+    "Probed CONFIG_ETRAX_I2C_EEPROM_PROBE \
+     2kB    CONFIG_ETRAX_I2C_EEPROM_2KB   \
+     8kB    CONFIG_ETRAX_I2C_EEPROM_8KB   \
+     16kB   CONFIG_ETRAX_I2C_EEPROM_16KB" Probed
+fi
+
 bool 'GPIO support' CONFIG_ETRAX_GPIO
 if [ "$CONFIG_ETRAX_GPIO" = "y" ]; then
   hex  '  PA-buttons bitmask' CONFIG_ETRAX_PA_BUTTON_BITMASK 02
-  hex  '  PA user changeable dir mask' CONFIG_PA_CHANGEABLE_DIR 00
-  hex  '  PA user changeable bits mask' CONFIG_PA_CHANGEABLE_BITS FF
-  hex  '  PB user changeable dir mask' CONFIG_PB_CHANGEABLE_DIR 00
-  hex  '  PB user changeable bits mask' CONFIG_PB_CHANGEABLE_BITS FF
+  hex  '  PA user changeable dir mask' CONFIG_ETRAX_PA_CHANGEABLE_DIR 00
+  hex  '  PA user changeable bits mask' CONFIG_ETRAX_PA_CHANGEABLE_BITS FF
+  hex  '  PB user changeable dir mask' CONFIG_ETRAX_PB_CHANGEABLE_DIR 00
+  hex  '  PB user changeable bits mask' CONFIG_ETRAX_PB_CHANGEABLE_BITS FF
 fi
 
-bool 'Juliette support' CONFIG_JULIETTE n
+bool 'ARTPEC-1 support' CONFIG_JULIETTE
 
 if [ "$CONFIG_JULIETTE" = "y" ]; then
    source arch/cris/drivers/juliette/Config.in
@@ -136,8 +162,18 @@
 bool 'USB host' CONFIG_ETRAX_USB_HOST
 if [ "$CONFIG_ETRAX_USB_HOST" = "y" ]; then
 	define_bool CONFIG_USB y
-	bool '  USB port 1 enabled' CONFIG_ETRAX_USB_HOST_PORT1 n
-	bool '  USB port 2 enabled' CONFIG_ETRAX_USB_HOST_PORT2 n
+	bool '  USB port 1 enabled' CONFIG_ETRAX_USB_HOST_PORT1
+	bool '  USB port 2 enabled' CONFIG_ETRAX_USB_HOST_PORT2
+else
+	define_bool CONFIG_USB n
+fi
+
+bool 'DS1302 Real Time Clock support' CONFIG_ETRAX_DS1302
+if [ "$CONFIG_ETRAX_DS1302" = "y" ]; then
+  bool '  DS1302 RST on Generic Port' CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+  int '  DS1302 RST bit number' CONFIG_ETRAX_DS1302_RSTBIT 2
+  int '  DS1302 SCL bit number' CONFIG_ETRAX_DS1302_SCLBIT 1
+  int '  DS1302 SDA bit number' CONFIG_ETRAX_DS1302_SDABIT 0
 fi
 
 endmenu
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/Makefile linux/arch/cris/drivers/Makefile
--- v2.4.4/linux/arch/cris/drivers/Makefile	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/Makefile	Tue May  1 16:04:56 2001
@@ -12,10 +12,13 @@
 obj-$(CONFIG_ETRAX_IDE)                += ide.o
 obj-$(CONFIG_ETRAX_AXISFLASHMAP)       += axisflashmap.o
 obj-$(CONFIG_ETRAX_I2C) 	       += i2c.o
+obj-$(CONFIG_ETRAX_I2C_EEPROM)         += eeprom.o
 obj-$(CONFIG_ETRAX_GPIO) 	       += gpio.o
 obj-$(CONFIG_ETRAX_USB_HOST)           += usb-host.o
 obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
-obj-$(CONFIG_JULIETTE)                 += juliette/juliette.o
-subdir-$(CONFIG_JULIETTE)              += juliette
+obj-$(CONFIG_ETRAX_PARPORT)            += parport.o
+obj-$(CONFIG_ETRAX_DS1302)             += ds1302.o
+
+
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/axisflashmap.c linux/arch/cris/drivers/axisflashmap.c
--- v2.4.4/linux/arch/cris/drivers/axisflashmap.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/axisflashmap.c	Tue May  1 16:04:56 2001
@@ -11,6 +11,15 @@
  * partition split defined below.
  *
  * $Log: axisflashmap.c,v $
+ * Revision 1.7  2001/04/05 13:41:46  markusl
+ * Updated according to review remarks
+ *
+ * Revision 1.6  2001/03/07 09:21:21  bjornw
+ * No need to waste .data
+ *
+ * Revision 1.5  2001/03/06 16:27:01  jonashg
+ * Probe the entire flash area for flash devices.
+ *
  * Revision 1.4  2001/02/23 12:47:15  bjornw
  * Uncached flash in LOW_MAP moved from 0xe to 0x8
  *
@@ -50,19 +59,13 @@
 #endif
 
 /*
- * WINDOW_SIZE is the total size where the flash chips are mapped,
- * my guess is that this can be the total memory area even if there
- * are many flash chips inside the area or if they are not all mounted.
- * So possibly we can get rid of the CONFIG_ here and just write something
- * like 32 MB always.
- */
-
-#define WINDOW_SIZE  (CONFIG_ETRAX_FLASH_LENGTH * 1024 * 1024)
-
-/* Byte-offset where the partition-table is placed in the first chip
+ * WINDOW_SIZE is the total size where the flash chips may be mapped.
+ * MTD probes should find all devices there and it does not matter
+ * if there are unmapped gaps or aliases (mirrors of flash devices).
+ * The MTD probes will ignore them.
  */
 
-#define PTABLE_SECTOR 65536
+#define WINDOW_SIZE  (128 * 1024 * 1024)
 
 /* 
  * Map driver
@@ -70,8 +73,6 @@
  * Ok this is the scoop - we need to access the flash both with and without
  * the cache - without when doing all the fancy flash interfacing, and with
  * when we do actual copying because otherwise it will be slow like molasses.
- * I hope this works the way it's intended, so that there won't be any cases
- * of non-synchronicity because of the different access modes below...
  */
 
 static __u8 flash_read8(struct map_info *map, unsigned long ofs)
@@ -110,12 +111,6 @@
 	*(__u32 *)(FLASH_UNCACHED_ADDR + adr) = d;
 }
 
-static void flash_copy_to(struct map_info *map, unsigned long to,
-			  const void *from, ssize_t len)
-{
-	memcpy((void *)(FLASH_CACHED_ADDR + to), from, len);
-}
-
 static struct map_info axis_map = {
 	name: "Axis flash",
 	size: WINDOW_SIZE,
@@ -127,7 +122,6 @@
 	write8: flash_write8,
 	write16: flash_write16,
 	write32: flash_write32,
-	copy_to: flash_copy_to
 };
 
 /* If no partition-table was found, we use this default-set.
@@ -139,18 +133,18 @@
 static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
 	{
 		name: "boot firmware",
-		size: PTABLE_SECTOR,
+		size: CONFIG_ETRAX_PTABLE_SECTOR,
 		offset: 0
 	},
 	{
 		name: "kernel",
 		size: 0x1a0000,
-		offset: PTABLE_SECTOR
+		offset: CONFIG_ETRAX_PTABLE_SECTOR
 	},
 	{
 		name: "filesystem",
 		size: 0x50000,
-		offset: (0x1a0000 + PTABLE_SECTOR)
+		offset: (0x1a0000 + CONFIG_ETRAX_PTABLE_SECTOR)
 	}
 };
 
@@ -214,11 +208,11 @@
 	printk(KERN_NOTICE "Axis flash mapping: %x at %x\n",
 	       WINDOW_SIZE, FLASH_CACHED_ADDR);
 
-	mymtd = do_cfi_probe(&axis_map);
+	mymtd = (struct mtd_info *)do_cfi_probe(&axis_map);
 
 #ifdef CONFIG_MTD_AMDSTD
 	if (!mymtd) {
-		mymtd = do_amd_flash_probe(&axis_map);
+		mymtd = (struct mtd_info *)do_amd_flash_probe(&axis_map);
 	}
 #endif
 
@@ -236,18 +230,15 @@
 	 */
 
 	ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR +
-		PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
+		CONFIG_ETRAX_PTABLE_SECTOR + PARTITION_TABLE_OFFSET);
 	pidx++;  /* first partition is always set to the default */
 
 	if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
-	    && (ptable_head->size
-		< (MAX_PARTITIONS
-		   * sizeof(struct partitiontable_entry) + 4))
-	    && (*(unsigned long*)
-		((void*)ptable_head
-		 + sizeof(*ptable_head)
-		 + ptable_head->size - 4)
-		==  PARTITIONTABLE_END_MARKER)) {
+	    && (ptable_head->size <
+		(MAX_PARTITIONS * sizeof(struct partitiontable_entry) + 4))
+	    && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) +
+				  ptable_head->size - 4)
+		== PARTITIONTABLE_END_MARKER)) {
 		/* Looks like a start, sane length and end of a
 		 * partition table, lets check csum etc.
 		 */
@@ -256,7 +247,7 @@
 			(struct partitiontable_entry *)
 			((unsigned long)ptable_head + sizeof(*ptable_head) +
 			 ptable_head->size);
-		unsigned long offset = PTABLE_SECTOR;
+		unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
 		unsigned char *p;
 		unsigned long csum = 0;
 		
@@ -293,16 +284,7 @@
 		       && ptable->offset != 0xffffffff
 		       && ptable < max_addr
 		       && pidx < MAX_PARTITIONS) {
-#if 0
-			/* wait with multi-chip support until we know
-			 * how mtd detects multiple chips
-			 */
-			if ((offset + ptable->offset) >= chips[0].size) {
-				partitions[pidx].start
-					= offset + chips[1].start
-					+ ptable->offset - chips[0].size;
-			}
-#endif
+
 			axis_partitions[pidx].offset = offset + ptable->offset;
 			axis_partitions[pidx].size = ptable->size;
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/ds1302.c linux/arch/cris/drivers/ds1302.c
--- v2.4.4/linux/arch/cris/drivers/ds1302.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/ds1302.c	Tue May  1 16:04:56 2001
@@ -0,0 +1,488 @@
+/*!***************************************************************************
+*!
+*! FILE NAME  : ds1302.c
+*!
+*! DESCRIPTION: Implements an interface for the DS1302 RTC through Etrax I/O
+*!
+*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status
+*!
+*! $Log: ds1302.c,v $
+*! Revision 1.3  2001/03/26 16:03:06  bjornw
+*! Needs linux/config.h
+*!
+*! Revision 1.2  2001/03/20 19:42:00  bjornw
+*! Use the ETRAX prefix on the DS1302 options
+*!
+*! Revision 1.1  2001/03/20 09:13:50  magnusmn
+*! Linux 2.4 port
+*!
+*! Revision 1.10  2000/07/05 15:38:23  bjornw
+*! Dont update kernel time when a RTC_SET_TIME is done
+*!
+*! Revision 1.9  2000/03/02 15:42:59  macce
+*! * Hack to make RTC work on all 2100/2400
+*!
+*! Revision 1.8  2000/02/23 16:59:18  torbjore
+*! added setup of R_GEN_CONFIG when RTC is connected to the generic port.
+*!
+*! Revision 1.7  2000/01/17 15:51:43  johana
+*! Added RTC_SET_CHARGE ioctl to enable trickle charger.
+*!
+*! Revision 1.6  1999/10/27 13:19:47  bjornw
+*! Added update_xtime_from_cmos which reads back the updated RTC into the kernel.
+*! /dev/rtc calls it now.
+*!
+*! Revision 1.5  1999/10/27 12:39:37  bjornw
+*! Disabled superuser check. Anyone can now set the time.
+*!
+*! Revision 1.4  1999/09/02 13:27:46  pkj
+*! Added shadow for R_PORT_PB_CONFIG.
+*! Renamed port_g_shadow to port_g_data_shadow.
+*!
+*! Revision 1.3  1999/09/02 08:28:06  pkj
+*! Made it possible to select either port PB or the generic port for the RST
+*! signal line to the DS1302 RTC.
+*! Also make sure the RST bit is configured as output on Port PB (if used).
+*!
+*! Revision 1.2  1999/09/01 14:47:20  bjornw
+*! Added support for /dev/rtc operations with ioctl RD_TIME and SET_TIME to read
+*! and set the date. Register as major 121.
+*!
+*! Revision 1.1  1999/09/01 09:45:29  bjornw
+*! Implemented a DS1302 RTC driver.
+*!
+*!
+*! ---------------------------------------------------------------------------
+*!
+*! (C) Copyright 1999, 2000, 2001  Axis Communications AB, LUND, SWEDEN
+*!
+*! $Id: ds1302.c,v 1.3 2001/03/26 16:03:06 bjornw Exp $
+*!
+*!***************************************************************************/
+
+#include <linux/config.h>
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/svinto.h>
+#include <asm/io.h>
+#include <asm/rtc.h>
+
+#define RTC_MAJOR_NR 121 /* local major, change later */
+
+/* The DS1302 might be connected to different bits on different products. 
+ * It has three signals - SDA, SCL and RST. RST and SCL are always outputs,
+ * but SDA can have a selected direction.
+ * For now, only PORT_PB is hardcoded.
+ */
+
+/* The RST bit may be on either the Generic Port or Port PB */
+#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+#define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_G_DATA,  port_g_data_shadow,  CONFIG_ETRAX_DS1302_RSTBIT, x)
+#define TK_RST_DIR(x)
+#else
+#define TK_RST_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_RSTBIT, x)
+#define TK_RST_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR,  port_pb_dir_shadow,  CONFIG_ETRAX_DS1302_RSTBIT, x)
+#endif
+
+
+#define TK_SDA_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SDABIT, x)
+#define TK_SCL_OUT(x) REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_DS1302_SCLBIT, x)
+
+#define TK_SDA_IN()   ((*R_PORT_PB_READ >> CONFIG_ETRAX_DS1302_SDABIT) & 1)
+/* 1 is out, 0 is in */
+#define TK_SDA_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR,  port_pb_dir_shadow,  CONFIG_ETRAX_DS1302_SDABIT, x)
+#define TK_SCL_DIR(x) REG_SHADOW_SET(R_PORT_PB_DIR,  port_pb_dir_shadow,  CONFIG_ETRAX_DS1302_SCLBIT, x)
+
+
+/*
+ * The reason for tempudelay and not udelay is that loops_per_usec
+ * (used in udelay) is not set when functions here are called from time.c 
+ */
+
+static void tempudelay(int time) 
+{
+	int i;
+	for(i = 0; i < time * 10000; i++);	
+}
+
+
+/* send 8 bits */
+static void
+out_byte(int x) 
+{
+	int i;
+	TK_SDA_DIR(1);
+	for (i = 8; i--;) {
+		/* the chip latches incoming bits on the rising edge of SCL */
+		TK_SCL_OUT(0);
+		TK_SDA_OUT(x & 1);
+		tempudelay(1);
+		TK_SCL_OUT(1);
+		tempudelay(1);
+		x >>= 1;
+	}
+	TK_SDA_DIR(0);
+}
+
+static unsigned char
+in_byte(void) 
+{
+	unsigned char x = 0;
+	int i;
+
+	/* Read byte. Bits come LSB first, on the falling edge of SCL.
+	 * Assume SDA is in input direction already
+	 */
+	TK_SDA_DIR(0);
+
+	for (i = 8; i--;) {
+		TK_SCL_OUT(0);
+		tempudelay(1);
+		x >>= 1;
+		x |= (TK_SDA_IN() << 7);
+		TK_SCL_OUT(1);
+		tempudelay(1);
+	}
+
+	return x;
+}
+
+/* prepares for a transaction by de-activating RST (active-low) */
+
+static void
+start(void) 
+{
+	TK_SCL_OUT(0);
+	tempudelay(1);
+	TK_RST_OUT(0);
+	tempudelay(5);
+	TK_RST_OUT(1);	
+}
+
+/* ends a transaction by taking RST active again */
+
+static void
+stop(void) 
+{
+	tempudelay(2);
+	TK_RST_OUT(0);
+}
+
+/* enable writing */
+
+static void
+ds1302_wenable(void) 
+{
+	start(); 	
+	out_byte(0x8e); /* Write control register  */
+	out_byte(0x00); /* Disable write protect bit 7 = 0 */
+	stop();
+}
+
+/* disable writing */
+
+static void
+ds1302_wdisable(void) 
+{
+	start();
+	out_byte(0x8e); /* Write control register  */
+	out_byte(0x80); /* Disable write protect bit 7 = 0 */
+	stop();
+}
+
+/* probe for the chip by writing something to its RAM and try reading it back */
+
+static int
+ds1302_probe(void) 
+{
+	int retval, res; 
+
+	TK_RST_DIR(1);
+	TK_SCL_DIR(1);
+	TK_SDA_DIR(0);
+	
+	/* try to talk to timekeeper */
+
+	ds1302_wenable();  
+	start();
+	out_byte(0xc0); /* write RAM byte 0 */	
+	out_byte(0x42); /* write something magic */
+	start();
+	out_byte(0xc1); /* read RAM byte 0 */
+
+	if((res = in_byte()) == 0x42) {
+		char buf[100];
+		stop();
+		ds1302_wdisable();
+		printk("DS1302 RTC found.\n");
+                printk("SDA, SCL, RST on PB%i, PB%i, %s%i\n",
+                       CONFIG_ETRAX_DS1302_SDABIT,
+                       CONFIG_ETRAX_DS1302_SCLBIT,
+#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+                       "GENIO",
+#else
+                       "PB",
+#endif
+                       CONFIG_ETRAX_DS1302_RSTBIT
+                       );
+                get_rtc_status(buf);
+                printk(buf);
+		retval = 1;
+	} else {
+		stop();
+		printk("DS1302 RTC not found.\n");
+		retval = 0;
+	}
+
+	return retval;
+}
+
+
+/* read a byte from the selected register in the DS1302 */
+
+unsigned char
+ds1302_readreg(int reg) 
+{
+	unsigned char x;
+
+	start();
+	out_byte(0x81 | (reg << 1)); /* Read register */
+	x = in_byte();
+	stop();
+
+	return x;
+}
+
+/* write a byte to the selected register */
+
+void
+ds1302_writereg(int reg, unsigned char val) 
+{
+	ds1302_wenable();
+	start();
+	out_byte(0x80 | (reg << 1)); /* Write register */
+	out_byte(val);
+	stop();
+	ds1302_wdisable();
+}
+
+void
+get_rtc_time(struct rtc_time *rtc_tm) 
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+
+	rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
+	rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
+	rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
+	rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
+	rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
+	rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
+
+	restore_flags(flags);
+	
+	BCD_TO_BIN(rtc_tm->tm_sec);
+	BCD_TO_BIN(rtc_tm->tm_min);
+	BCD_TO_BIN(rtc_tm->tm_hour);
+	BCD_TO_BIN(rtc_tm->tm_mday);
+	BCD_TO_BIN(rtc_tm->tm_mon);
+	BCD_TO_BIN(rtc_tm->tm_year);
+
+	/*
+	 * Account for differences between how the RTC uses the values
+	 * and how they are defined in a struct rtc_time;
+	 */
+
+	if (rtc_tm->tm_year <= 69)
+		rtc_tm->tm_year += 100;
+
+	rtc_tm->tm_mon--;
+}
+
+static unsigned char days_in_mo[] = 
+    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date) */
+
+static int
+rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	  unsigned long arg) 
+{
+        unsigned long flags;
+
+	switch(cmd) {
+		case RTC_RD_TIME:	/* Read the time/date from RTC	*/
+		{
+			struct rtc_time rtc_tm;
+						
+			get_rtc_time(&rtc_tm);						
+			if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
+				return -EFAULT;	
+			return 0;
+		}
+
+		case RTC_SET_TIME:	/* Set the RTC */
+		{
+			struct rtc_time rtc_tm;
+			unsigned char mon, day, hrs, min, sec, leap_yr;
+			unsigned char save_control, save_freq_select;
+			unsigned int yrs;
+#if 0
+			if (!suser())
+				return -EACCES;
+#endif			
+			if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
+				return -EFAULT;    	
+
+			yrs = rtc_tm.tm_year + 1900;
+			mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
+			day = rtc_tm.tm_mday;
+			hrs = rtc_tm.tm_hour;
+			min = rtc_tm.tm_min;
+			sec = rtc_tm.tm_sec;
+			
+			
+			if ((yrs < 1970) || (yrs > 2069))
+				return -EINVAL;
+
+			leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+			if ((mon > 12) || (day == 0))
+				return -EINVAL;
+
+			if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
+				return -EINVAL;
+			
+			if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+				return -EINVAL;
+
+			if (yrs >= 2000)
+				yrs -= 2000;	/* RTC (0, 1, ... 69) */
+			else
+				yrs -= 1900;	/* RTC (70, 71, ... 99) */
+
+			BIN_TO_BCD(sec);
+			BIN_TO_BCD(min);
+			BIN_TO_BCD(hrs);
+			BIN_TO_BCD(day);
+			BIN_TO_BCD(mon);
+			BIN_TO_BCD(yrs);
+
+			save_flags(flags);
+			cli();
+			CMOS_WRITE(yrs, RTC_YEAR);
+			CMOS_WRITE(mon, RTC_MONTH);
+			CMOS_WRITE(day, RTC_DAY_OF_MONTH);
+			CMOS_WRITE(hrs, RTC_HOURS);
+			CMOS_WRITE(min, RTC_MINUTES);
+			CMOS_WRITE(sec, RTC_SECONDS);
+			restore_flags(flags);
+
+			/* notice that at this point, the RTC is updated but the kernel
+			 * is still running with the old time. you need to set that
+			 * separately with settimeofday or adjtimex.
+			 */
+			return 0;
+		}
+
+		case RTC_SET_CHARGE: /* Set the RTC TRICKLE CHARGE register */
+		{
+			int tcs_val;                        
+			unsigned char save_control, save_freq_select;
+#if 0
+			if (!suser())
+				return -EACCES;
+#endif
+			
+			if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
+				return -EFAULT;
+
+			tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
+			ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
+			return 0;
+		}                
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+/*
+ *	Info exported via "/proc/rtc".
+ */
+
+int
+get_rtc_status(char *buf) 
+{
+	char *p;
+	struct rtc_time tm;
+
+	p = buf;
+
+	get_rtc_time(&tm);
+
+	/*
+	 * There is no way to tell if the luser has the RTC set for local
+	 * time or for Universal Standard Time (GMT). Probably local though.
+	 */
+
+	p += sprintf(p,
+		"rtc_time\t: %02d:%02d:%02d\n"
+		"rtc_date\t: %04d-%02d-%02d\n",
+		tm.tm_hour, tm.tm_min, tm.tm_sec,
+		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+
+	return  p - buf;
+}
+
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations rtc_fops = {
+        owner:          THIS_MODULE,
+        ioctl:          rtc_ioctl,	
+}; 
+
+/* just probe for the RTC and register the device to handle the ioctl needed */
+
+int
+ds1302_init(void) 
+{ 
+  
+ /* Ugly hack to handle both 2100 and 2400 hardware.
+    Remove...
+ */
+	if(!ds1302_probe()) {
+#ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
+    	/*
+     	* Make sure that R_GEN_CONFIG is 
+     	* setup correct.
+     	*/
+    		genconfig_shadow = ( (genconfig_shadow & ~IO_MASK(R_GEN_CONFIG, ata) ) | 
+                           ( IO_STATE( R_GEN_CONFIG, ata, select ) ) );    
+    		*R_GEN_CONFIG = genconfig_shadow;
+    		if(!ds1302_probe())
+      			return -1;
+#else
+    		return -1;
+#endif
+  	}
+  
+	if (register_chrdev(RTC_MAJOR_NR, "rtc", &rtc_fops)) {
+		printk("unable to get major %d for rtc\n", RTC_MAJOR_NR);
+		return -1;
+	}
+	return 0;
+}
+
+
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/eeprom.c linux/arch/cris/drivers/eeprom.c
--- v2.4.4/linux/arch/cris/drivers/eeprom.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/eeprom.c	Tue May  1 16:04:56 2001
@@ -0,0 +1,1161 @@
+/*!**************************************************************************
+*!
+*!  FILE NAME:      e100eeprom.c
+*!
+*!  DESCRIPTION:    Implements an interface for i2c compatible eeproms to run
+*!                  under linux.
+*!                  Supports 2k, 8k(?) and 16k
+*!                  Uses adaptive timing adjustents by Johan.Adolfsson@axis.com
+*!                  Probing results:
+*!                    8k or not is detected (the assumes 2k or 16k)
+*!                    2k or 16k detected using test reads and writes.
+*!
+*!  FUNCTIONS:
+*!
+*!  (Exported)
+*!              eeprom_init()
+*!
+*!  (Local)
+*!
+*!              eeprom_open()
+*!              eeprom_lseek()
+*!              eeprom_read()
+*!              eeprom_write()
+*!              eeprom_close()
+*!              eeprom_address()
+*!              eeprom_disable_write_protect()
+*!
+*!
+*!  $Id: eeprom.c,v 1.3 2001/03/19 16:04:46 markusl Exp $
+*!
+*!------------------------------------------------------------------------
+*!  HISTORY
+*!
+*!  DATE          NAME              CHANGES
+*!  ----          ----              -------
+*!  Aug  28 1999  Edgar Iglesias    Initial Version
+*!  Aug  31 1999  Edgar Iglesias    Allow simultaneous users.
+*!  Sep  03 1999  Edgar Iglesias    Updated probe.
+*!  Sep  03 1999  Edgar Iglesias    Added bail-out stuff if we get interrupted
+*!                                  in the spin-lock.
+*!
+*!  $Log: eeprom.c,v $
+*!  Revision 1.3  2001/03/19 16:04:46  markusl
+*!  Fixed init of fops struct
+*!
+*!  Revision 1.2  2001/03/19 10:35:07  markusl
+*!  2.4 port of eeprom driver
+*!
+*!  Revision 1.8  2000/05/18 10:42:25  edgar
+*!  Make sure to end write cycle on _every_ write
+*!
+*!  Revision 1.7  2000/01/17 17:41:01  johana
+*!  Adjusted probing and return -ENOSPC when writing outside EEPROM
+*!
+*!  Revision 1.6  2000/01/17 15:50:36  johana
+*!  Added adaptive timing adjustments and fixed autoprobing for 2k and 16k(?)
+*!  EEPROMs
+*!
+*!  Revision 1.5  1999/09/03 15:07:37  edgar
+*!  Added bail-out check to the spinlock
+*!
+*!  Revision 1.4  1999/09/03 12:11:17  bjornw
+*!  Proper atomicity (need to use spinlocks, not if's). users -> busy.
+*!
+*!
+*!        (c) 1999 Axis Communications AB, Lund, Sweden
+*!**************************************************************************/
+
+/********************** INCLUDE FILES SECTION ******************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include "i2c.h"
+
+/********************** CONSTANT AND MACRO SECTION *************************/
+#define D(x) 
+
+/* If we should use adaptive timing or not: */
+//#define EEPROM_ADAPTIVE_TIMING      
+
+#define EEPROM_MAJOR_NR 122  /* use a LOCAL/EXPERIMENTAL major for now */
+#define EEPROM_MINOR_NR 0
+
+#define MAX_WRITEDELAY_US 10000 /* 10 ms according to spec for 2KB EEPROM */
+/*
+ *  this one defines how many times to try when eeprom fails.
+ */
+#define EEPROM_RETRIES 10
+
+#define EEPROM_2KB (2 * 1024)
+/*#define EEPROM_4KB (4 * 1024)*/ /* Exists but not used in Axis products */
+#define EEPROM_8KB (8 * 1024 - 1 ) /* Last byte has write protection bit */
+#define EEPROM_16KB (16 * 1024)
+
+#define i2c_delay(x) udelay(x)
+
+/********************** TYPE DEFINITION SECTION ****************************/
+
+/*
+ *  This structure describes the attached eeprom chip.
+ *  The values are probed for.
+ */
+
+struct eeprom_type
+{
+  unsigned long size;
+  unsigned long sequential_write_pagesize;
+  unsigned char select_cmd;
+  unsigned long usec_delay_writecycles; /* Min time between write cycles (up to 10ms for some models) */
+  unsigned long int usec_delay_step; /* For adaptive algorithm */
+  int adapt_state; /* 1 = To high , 0 = Even, -1 = To low */
+  
+  /* this one is to keep the read/write operations atomic */
+  wait_queue_head_t wait_q;
+  int busy;
+  int retry_cnt_addr; /* Used to keep track of number of retries for
+                     adaptive timing adjustments */
+  int retry_cnt_read;
+
+  
+  
+};
+
+/********************** LOCAL FUNCTION DECLARATION SECTION *****************/
+
+static int  eeprom_open (struct inode * inode, struct file * file);
+static loff_t  eeprom_lseek(struct file * file, loff_t offset, int orig);
+static ssize_t  eeprom_read (struct file * file, char * buf, size_t count, loff_t *off);
+static ssize_t  eeprom_write(struct file * file, const char * buf, size_t count, loff_t *off);
+static int eeprom_close(struct inode * inode, struct file * file);
+
+static int  eeprom_address(unsigned long addr);
+static int  read_from_eeprom(char * buf, int count);
+static int eeprom_write_buf(unsigned long int addr,
+                            const char * buf, int count);
+static int eeprom_read_buf(unsigned long addr,
+                           char * buf, int count);
+
+static void eeprom_disable_write_protect(void);
+
+
+/********************** GLOBAL VARIABLE DECLARATION SECTION ****************/
+
+/********************** LOCAL VARIABLE DECLARATION SECTION *****************/
+
+/* chip description */
+static struct eeprom_type eeprom;
+
+/*
+ *  This is the exported file-operations structure
+ *  for this device.
+ */
+
+struct file_operations eeprom_fops =
+{
+  llseek:  eeprom_lseek,
+  read:    eeprom_read,
+  write:   eeprom_write,
+  open:    eeprom_open,
+  release: eeprom_close
+};
+
+/********************** FUNCTION DEFINITION SECTION ************************/
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_init
+*#                                                            
+*# PARAMETERS   : none
+*#                                                            
+*# RETURNS      : 0 if OK
+*#                                                            
+*# SIDE EFFECTS : 
+*#                                                            
+*# DESCRIPTION  : eeprom init call. Probes for different eeprom models.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version               
+*# Sep 03 1999  Edgar Iglesias  Updated probing. Added forced values.
+*#
+*#**************************************************************************/
+
+int __init eeprom_init(void)
+{
+  init_waitqueue_head(&eeprom.wait_q);
+  eeprom.busy = 0;
+
+#if CONFIG_ETRAX_I2C_EEPROM_PROBE
+#define EETEXT "Found"
+#else
+#define EETEXT "Assuming"
+#endif
+  if (register_chrdev(EEPROM_MAJOR_NR, "mem", &eeprom_fops))
+  {
+    printk("unable to get major %d for eeprom device\n", EEPROM_MAJOR_NR);
+    return -1;
+  }
+  
+  printk("EEPROM char device v0.3, (c) 2000 Axis Communications AB\n");
+
+  /*
+   *  Note: Most of this probing method was taken from the printserver (5470e)
+   *        codebase. It did not contain a way of finding the 16Kb chips
+   *        (M24128 or variants). The method used here might not work
+   *        for all models. If you encounter problems the easiest way
+   *        is probably to define your model within #ifdef's, and hard-
+   *        code it.
+   *
+   */
+
+  eeprom.size = 0;
+  eeprom.usec_delay_writecycles = 4000;/*MAX_WRITEDELAY_US / EEPROM_RETRIES;*/
+  eeprom.usec_delay_step = 128;
+  eeprom.adapt_state = 0;
+  
+#if CONFIG_ETRAX_I2C_EEPROM_PROBE
+  i2c_start();
+  i2c_outbyte(0x80);
+  if(!i2c_getack())
+  {
+    /* It's not 8k.. */
+    int success = 0;
+    unsigned char buf_2k_start[16];
+    
+    /* Im not sure this will work... :) */
+    /* assume 2Kb, if failure go for 16Kb */
+    /* Test with 16kB settings.. */
+    /* If it's a 2kB EEPROM and we address it outside it's range
+     * it will mirror the address space:
+     * 1. We read two locations (that are mirrored), 
+     *    if the content differs * it's a 16kB EEPROM.
+     * 2. if it doesn't differ - write diferent value to one of the locations,
+     *    check the other - if content still is the same it's a 2k EEPROM,
+     *    restore original data.
+     *    
+     */
+#define LOC1 8
+#define LOC2 (0x1fb) /*1fb, 3ed, 5df, 7d1 */
+
+   /* 2k settings */  
+    i2c_stop();
+    eeprom.size = EEPROM_2KB;
+    eeprom.select_cmd = 0xA0;   
+    eeprom.sequential_write_pagesize = 16;
+    if( eeprom_read_buf( 0, buf_2k_start, 16 ) == 16 )
+    {
+      D(printk("2k start: '%16.16s'\n", buf_2k_start));
+    }
+    else
+    {
+      printk("Failed to read in 2k mode!\n");  
+    }
+    
+    /* 16k settings */
+    eeprom.size = EEPROM_16KB;
+    eeprom.select_cmd = 0xA0;   
+    eeprom.sequential_write_pagesize = 64;
+
+    {
+      unsigned char loc1[4], loc2[4], tmp[4];
+      if( eeprom_read_buf(LOC2, loc2, 4) == 4)
+      {
+        if( eeprom_read_buf(LOC1, loc1, 4) == 4)
+        {
+          D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", 
+                   LOC1, loc1, LOC2, loc2));
+#if 0
+          if (memcmp(loc1, loc2, 4) != 0 )
+          {
+            /* It's 16k */
+            printk("16k detected in step 1\n");
+            eeprom.size = EEPROM_16KB;     
+            success = 1;
+          }
+          else
+#endif
+          {
+            /* Do step 2 check */
+            /* Invert value */
+            loc1[0] = ~loc1[0];
+            if (eeprom_write_buf(LOC1, loc1, 1) == 1)
+            {
+              /* If 2k EEPROM this write will actually write 10 bytes
+               * from pos 0
+               */
+              D(printk("1 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", 
+                       LOC1, loc1, LOC2, loc2));
+              if( eeprom_read_buf(LOC1, tmp, 4) == 4)
+              {
+                D(printk("2 loc1: (%i) '%4.4s' tmp '%4.4s'\n", 
+                         LOC1, loc1, tmp));
+                if (memcmp(loc1, tmp, 4) != 0 )
+                {
+                  printk("read and write differs! Not 16kB\n");
+                  loc1[0] = ~loc1[0];
+                  
+                  if (eeprom_write_buf(LOC1, loc1, 1) == 1)
+                  {
+                    success = 1;
+                  }
+                  else
+                  {
+                    printk("eeprom: Restore 2k failed during probe EEPROM might be corrupt!\n");
+                    
+                  }
+                  i2c_stop();
+                  /* Go to 2k mode and write original data */
+                  eeprom.size = EEPROM_2KB;
+                  eeprom.select_cmd = 0xA0;   
+                  eeprom.sequential_write_pagesize = 16;
+                  if( eeprom_write_buf(0, buf_2k_start, 16) == 16)
+                  {
+                  }
+                  else
+                  {
+                    printk("Failed to write back 2k start!\n");
+                  }
+                  
+                  eeprom.size = EEPROM_2KB;
+                }
+              }
+                
+              if(!success)
+              {
+                if( eeprom_read_buf(LOC2, loc2, 1) == 1)
+                {
+                  D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", 
+                           LOC1, loc1, LOC2, loc2));
+                  if (memcmp(loc1, loc2, 4) == 0 )
+                  {
+                    /* Data the same, must be mirrored -> 2k */
+                    /* Restore data */
+                    printk("2k detected in step 2\n");
+                    loc1[0] = ~loc1[0];
+                    if (eeprom_write_buf(LOC1, loc1, 1) == 1)
+                    {
+                      success = 1;
+                    }
+                    else
+                    {
+                      printk("eeprom: Restore 2k failed during probe EEPROM might be corrupt!\n");
+                      
+                    }
+                    
+                    eeprom.size = EEPROM_2KB;     
+                  }
+                  else
+                  {
+                    printk("16k detected in step 2\n");
+                    loc1[0] = ~loc1[0];
+                    /* Data differs, assume 16k */
+                    /* Restore data */
+                    if (eeprom_write_buf(LOC1, loc1, 1) == 1)
+                    {
+                      success = 1;
+                    }
+                    else
+                    {
+                      printk("eeprom: Restore 16k failed during probe EEPROM might be corrupt!\n");
+                    }
+                    
+                    eeprom.size = EEPROM_16KB;
+                  }
+                }
+              }
+            }
+          } /* read LOC1 */
+        } /* address LOC1 */
+        if (!success)
+        {
+          printk("eeprom: Probing failed!, using 2KB!\n");
+          eeprom.size = EEPROM_2KB;               
+        }
+      } /* read */
+    }
+  }
+  else
+  {
+    i2c_outbyte(0x00);
+    if(!i2c_getack())
+    {
+      /* No 8k */
+      eeprom.size = EEPROM_2KB;
+    }
+    else
+    {
+      i2c_start();
+      i2c_outbyte(0x81);
+      if (!i2c_getack())
+      {
+        eeprom.size = EEPROM_2KB;
+      }
+      else
+      {
+        /* It's a 8kB */
+        i2c_inbyte();
+        eeprom.size = EEPROM_8KB;
+      }
+    }
+  }
+  i2c_stop();
+#elif defined(CONFIG_ETRAX_I2C_EEPROM_16KB)
+  eeprom.size = EEPROM_16KB;
+#elif defined(CONFIG_ETRAX_I2C_EEPROM_8KB)
+  eeprom.size = EEPROM_8KB;
+#elif defined(CONFIG_ETRAX_I2C_EEPROM_2KB)
+  eeprom.size = EEPROM_2KB;
+#endif
+
+  switch(eeprom.size)
+  {
+   case (EEPROM_2KB):
+     printk("e100eeprom: " EETEXT " i2c compatible 2Kb eeprom.\n");
+     eeprom.sequential_write_pagesize = 16;
+     eeprom.select_cmd = 0xA0;
+     break;
+   case (EEPROM_8KB):
+     printk("e100eeprom: " EETEXT " i2c compatible 8Kb eeprom.\n");
+     eeprom.sequential_write_pagesize = 16;
+     eeprom.select_cmd = 0x80;
+     break;
+   case (EEPROM_16KB):
+     printk("e100eeprom: " EETEXT " i2c compatible 16Kb eeprom.\n");
+     eeprom.sequential_write_pagesize = 64;
+     eeprom.select_cmd = 0xA0;     
+     break;
+   default:
+     eeprom.size = 0;
+     printk("e100eeprom: Did not find a supported eeprom\n");
+     break;
+  }
+
+  
+
+  eeprom_disable_write_protect();
+
+  return 0;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_open
+*#                                                            
+*# PARAMETERS   : inode    : Pointer to the inode
+*#                file     : Pointer to the file
+*#                                                            
+*# RETURNS      : 0 if OK
+*#                                                            
+*# SIDE EFFECTS : 
+*#                                                            
+*# DESCRIPTION  : Opens the device.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version               
+*# Sep 03 1999  Edgar Iglesias  Removed users check.
+*#
+*#**************************************************************************/
+
+static int eeprom_open(struct inode * inode, struct file * file)
+{
+
+  if(MINOR(inode->i_rdev) != EEPROM_MINOR_NR)
+     return -ENXIO;
+  if(MAJOR(inode->i_rdev) != EEPROM_MAJOR_NR)
+     return -ENXIO;
+
+  if( eeprom.size > 0 )
+  {
+    /* OK */
+    return 0;
+  }
+
+  /* No EEprom found */
+  return -EFAULT;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_lseek
+*#                                                            
+*# PARAMETERS   : file     : Pointer to the file
+*#                offset   : The offset (in bytes)
+*#                orig     : look at the note
+*#                                                            
+*# RETURNS      : 0 if OK
+*#                                                            
+*# SIDE EFFECTS : 
+*#                                                            
+*# DESCRIPTION  : Changes the current file position.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version
+*# Sep 03 1999  Edgar Iglesias  Return -EOVERFLOW when beyond eeprom size.
+*#
+*#**************************************************************************/
+
+static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig)
+{
+/*
+ *  orig 0: position from begning of eeprom
+ *  orig 1: relative from current position
+ *  orig 2: position from last eeprom address
+ */
+  
+  switch (orig)
+  {
+   case 0:
+     file->f_pos = offset;
+     break;
+   case 1:
+     file->f_pos += offset;
+     break;
+   case 2:
+     file->f_pos = eeprom.size - offset;
+     break;
+   default:
+     return -EINVAL;
+  }
+
+  /* truncate position */
+  if (file->f_pos < 0)
+  {
+    file->f_pos = 0;    
+    return(-EOVERFLOW);
+  }
+  
+  if (file->f_pos >= eeprom.size)
+  {
+    file->f_pos = eeprom.size - 1;
+    return(-EOVERFLOW);
+  }
+
+  return ( file->f_pos );
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_read
+*#                                                            
+*# PARAMETERS   : inode    : Pointer to the inode
+*#                file     : Pointer to the file
+*#                buf      : Destination buffer
+*#                count    : max nr bytes to read
+*#                                                            
+*# RETURNS      : number of read bytes.
+*#                                                            
+*# SIDE EFFECTS : updates file->f_pos
+*#                                                            
+*# DESCRIPTION  : Reads data from eeprom.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Jan 17 2000  Johan Adolfsson Initial version
+*#
+*#**************************************************************************/
+static int eeprom_read_buf(unsigned long addr,
+                           char * buf, int count)
+{
+  struct file f;
+
+  f.f_pos = addr;
+  return eeprom_read(&f, buf, count, &addr);
+}
+
+
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_read
+*#                                                            
+*# PARAMETERS   : file     : Pointer to the file
+*#                buf      : Destination buffer
+*#                count    : max nr bytes to read
+*#                                                            
+*# RETURNS      : number of read bytes.
+*#                                                            
+*# SIDE EFFECTS : updates file->f_pos
+*#                                                            
+*# DESCRIPTION  : Reads data from eeprom.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version               
+*# Aug 31 1999  Edgar Iglesias  Made operation atomic with wait queues
+*# Sep 03 1999  Edgar Iglesias  Added bail-out stuff if we get interrupted
+*#                              in the spin-lock.
+*#
+*#**************************************************************************/
+
+static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t *off)
+{
+  int i, read=0;
+  unsigned long p = file->f_pos;
+
+  unsigned char page;
+
+  if(p >= eeprom.size)  /* Address i 0 - (size-1) */
+  {
+    return -EFAULT;
+  }
+  
+  while(eeprom.busy)
+  {
+    interruptible_sleep_on(&eeprom.wait_q);
+
+    /* bail out if we get interrupted */
+    if (signal_pending(current))
+      return -EINTR;
+    
+  }
+  eeprom.busy++;
+
+  page = (unsigned char) (p >> 8);
+  
+  if(!eeprom_address(p))
+  {
+    printk("eeprom: Read failed to address the eeprom: "
+           "0x%08X (%i) page: %i\n", p, p, page);
+    i2c_stop();
+    
+    /* don't forget to wake them up */
+    eeprom.busy--;
+    wake_up_interruptible(&eeprom.wait_q);  
+    return -EFAULT;
+  }
+
+  if( (p + count) > eeprom.size)
+  {
+    /* truncate count */
+    count = eeprom.size - p;
+  }
+
+  /* stop dummy write op and initiate the read op */
+  i2c_start();
+
+  /* special case for small eeproms */
+  if(eeprom.size < EEPROM_16KB)
+  {
+    i2c_outbyte( eeprom.select_cmd | 1 | (page << 1) );
+  }
+
+  /* go on with the actual read */
+  read = read_from_eeprom( buf, count);
+  
+  if(read > 0)
+  {
+    file->f_pos += read;
+  }
+
+  eeprom.busy--;
+  wake_up_interruptible(&eeprom.wait_q);
+  return read;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_write_buf
+*#                                                            
+*# PARAMETERS   : addr     : Address to write to
+*#                buf      : Data buffer to write from
+*#                count    : number bytes to write
+*#                                                            
+*# RETURNS      : number of bytes actualy written.
+*#                                                            
+*# SIDE EFFECTS : None
+*#             
+*# DESCRIPTION  : Writes data to eeprom.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Jan 17 2000  Johan Adolfsson Initial vesion
+*#
+*#**************************************************************************/
+static int eeprom_write_buf(unsigned long int addr,
+                            const char * buf, int count)
+{
+  struct file f;
+
+  f.f_pos = addr;
+  
+  return eeprom_write(&f, buf, count, &addr);
+}
+
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_write
+*#                                                            
+*# PARAMETERS   : file     : Pointer to the file
+*#                buf      : Data buffer to write from
+*#                count    : number bytes to write
+*#                                                            
+*# RETURNS      : number of bytes actualy written.
+*#                                                            
+*# SIDE EFFECTS : updates file->f_pos
+*#             
+*# DESCRIPTION  : Writes data to eeprom.
+*#                                                            
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#                                                            
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version               
+*# Aug 31 1999  Edgar Iglesias  Made operation atomic with wait queues
+*# Sep 03 1999  Edgar Iglesias  Moved the actual reading to read_from_eeprom
+*# Sep 03 1999  Edgar Iglesias  Added bail-out stuff if we get interrupted
+*#                              in the spin-lock.
+*# May 18 2000  Edgar Iglesias  Make sure to end write cycle after every write.
+*#
+*#**************************************************************************/
+
+static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,
+                            loff_t *off)
+{
+  int i, written, restart=1;
+  unsigned long p;
+
+  while(eeprom.busy)
+  {
+    interruptible_sleep_on(&eeprom.wait_q);
+    /* bail out if we get interrupted */
+    if (signal_pending(current))
+      return -EINTR;
+  }
+  eeprom.busy++;
+  for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++)
+  {
+    restart = 0;
+    written = 0;
+    p = file->f_pos;
+   
+    
+    while( (written < count) && (p < eeprom.size))
+    {
+      /* address the eeprom */
+      if(!eeprom_address(p))
+      {
+        printk("eeprom: Write failed to address the eeprom: 0x%08X (%i) \n", 
+               p, p);
+        i2c_stop();
+        
+        /* don't forget to wake them up */
+        eeprom.busy--;
+        wake_up_interruptible(&eeprom.wait_q);
+        return -EFAULT;
+      }
+#ifdef EEPROM_ADAPTIVE_TIMING      
+      /* Adaptive algorithm to adjust timing */
+      if (eeprom.retry_cnt_addr > 0)
+      {
+        /* To Low now */
+        D(printk(">D=%i d=%i\n",
+               eeprom.usec_delay_writecycles, eeprom.usec_delay_step));
+
+        if (eeprom.usec_delay_step < 4)
+        {
+          eeprom.usec_delay_step++;
+          eeprom.usec_delay_writecycles += eeprom.usec_delay_step;
+        }
+        else
+        {
+
+          if (eeprom.adapt_state > 0)
+          {
+            /* To Low before */
+            eeprom.usec_delay_step *= 2;
+            if (eeprom.usec_delay_step > 2)
+            {
+              eeprom.usec_delay_step--;
+            }
+            eeprom.usec_delay_writecycles += eeprom.usec_delay_step;
+          }
+          else if (eeprom.adapt_state < 0)
+          {
+            /* To High before (toggle dir) */
+            eeprom.usec_delay_writecycles += eeprom.usec_delay_step;
+            if (eeprom.usec_delay_step > 1)
+            {
+              eeprom.usec_delay_step /= 2;
+              eeprom.usec_delay_step--;
+            }
+          }
+        }
+
+        eeprom.adapt_state = 1;
+      }
+      else
+      {
+        /* To High (or good) now */
+        D(printk("<D=%i d=%i\n",
+               eeprom.usec_delay_writecycles, eeprom.usec_delay_step));
+        
+        if (eeprom.adapt_state < 0)
+        {
+          /* To High before */
+          if (eeprom.usec_delay_step > 1)
+          {
+            if (eeprom.usec_delay_step > 0)
+            {
+              eeprom.usec_delay_step *= 2;
+              eeprom.usec_delay_step--;
+            }
+            
+            if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step)
+            {
+              eeprom.usec_delay_writecycles -= eeprom.usec_delay_step;
+            }
+          }
+        }
+        else if (eeprom.adapt_state > 0)
+        {
+          /* To Low before (toggle dir) */
+          if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step)
+          {
+            eeprom.usec_delay_writecycles -= eeprom.usec_delay_step;
+          }
+          if (eeprom.usec_delay_step > 1)
+          {
+            eeprom.usec_delay_step /= 2;
+            eeprom.usec_delay_step--;
+          }
+          
+          eeprom.adapt_state = -1;
+        }
+
+        if (eeprom.adapt_state > -100)
+        {
+          eeprom.adapt_state--;
+        }
+        else
+        {
+          /* Restart adaption */
+          D(printk("#Restart\n"));
+          eeprom.usec_delay_step++;
+        }
+      }
+#endif /* EEPROM_ADAPTIVE_TIMING */
+      /* write until we hit a page boundary or count */
+      do
+      {
+        i2c_outbyte(buf[written]);        
+        if(!i2c_getack())
+        {
+          restart=1;
+          printk("eeprom: write error, retrying. %d\n", i);
+          i2c_stop();
+          break;
+        }
+        written++;
+        p++;        
+      } while( written < count && ( p % eeprom.sequential_write_pagesize ));
+
+      /* end write cycle */
+      i2c_stop();
+      i2c_delay(eeprom.usec_delay_writecycles);
+    } /* while */
+  } /* for  */
+
+  eeprom.busy--;
+  wake_up_interruptible(&eeprom.wait_q);
+  if (written == 0 && file->f_pos >= eeprom.size){
+    return -ENOSPC;
+  }
+  file->f_pos += written;
+  return written;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_close
+*#                                                            
+*# PARAMETERS   : inode    : Pointer to the inode
+*#                file     : Pointer to the file
+*#
+*# RETURNS      : nothing
+*#
+*# SIDE EFFECTS :
+*#
+*# DESCRIPTION  : Closes the device.
+*#
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version               
+*# Sep 03 1999  Edgar Iglesias  Removed eeprom.users stuff.
+*#
+*#**************************************************************************/
+
+static int eeprom_close(struct inode * inode, struct file * file)
+{
+  /* do nothing for now */
+  return 0;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_address
+*#                                                            
+*# PARAMETERS   : addr     : Address to be given to eeprom
+*#
+*# RETURNS      : 1 if OK, 0 if failure.
+*#
+*# SIDE EFFECTS :
+*#
+*# DESCRIPTION  : Sets the current address of the eeprom.
+*#
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Aug 28 1999  Edgar Iglesias  Initial version               
+*# Sep 03 1999  Edgar Iglesias  Corrected typo.
+*#
+*#**************************************************************************/
+
+static int eeprom_address(unsigned long addr)
+{
+  int i, j;
+  unsigned char page, offset;
+
+  page   = (unsigned char) (addr >> 8);
+  offset = (unsigned char)  addr;
+
+  for(i = 0; i < EEPROM_RETRIES; i++)
+  {
+    /* start a dummy write for addressing */
+    i2c_start();
+
+    if(eeprom.size == EEPROM_16KB)
+    {
+      i2c_outbyte( eeprom.select_cmd ); 
+      i2c_getack();
+      i2c_outbyte(page); 
+    }
+    else
+    {
+      i2c_outbyte( eeprom.select_cmd | (page << 1) ); 
+    }
+    if(!i2c_getack())
+    {
+      /* retry */
+      i2c_stop();
+      /* Must have a delay here.. 500 works, >50, 100->works 5th time*/
+      i2c_delay(MAX_WRITEDELAY_US / EEPROM_RETRIES * i);
+      /* The chip needs up to 10 ms from write stop to next start */
+     
+    }
+    else
+    {
+      i2c_outbyte(offset);
+      
+      if(!i2c_getack())
+      {
+        /* retry */
+        i2c_stop();
+      }
+      else
+        break;
+    }
+  }    
+
+  
+  eeprom.retry_cnt_addr = i;
+  D(printk("%i\n", eeprom.retry_cnt_addr));
+  if(eeprom.retry_cnt_addr == EEPROM_RETRIES)
+  {
+    /* failed */
+    return 0;
+  }
+  return 1;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: read_from_eeprom
+*#                                                            
+*# PARAMETERS   : buf      : Destination buffer.
+*#                count    : Number of bytes to read.
+*#
+*# RETURNS      : number of read bytes or -EFAULT.
+*#
+*# SIDE EFFECTS :
+*#
+*# DESCRIPTION  : Reads from current adress.
+*#
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Sep 03 1999  Edgar Iglesias  Initial version               
+*#
+*#**************************************************************************/
+
+static int read_from_eeprom(char * buf, int count)
+{
+  int i, read=0;
+
+  for(i = 0; i < EEPROM_RETRIES; i++)
+  {    
+    if(eeprom.size == EEPROM_16KB)
+    {
+      i2c_outbyte( eeprom.select_cmd | 1 );
+    }
+
+    if(i2c_getack());
+    {
+      break;
+    }
+  }
+  
+  if(i == EEPROM_RETRIES)
+  {
+    printk("eeprom: failed to read from eeprom\n");
+    i2c_stop();
+    
+    return -EFAULT;
+  }
+
+  while( (read < count))
+  {    
+    buf[read++] = i2c_inbyte();      
+
+    /*
+     *  make sure we don't ack last byte or you will get very strange
+     *  results!
+     */
+    if(read < count)
+    {
+      i2c_sendack();
+    }
+  }
+
+  /* stop the operation */
+  i2c_stop();
+
+  return read;
+}
+
+/*#**************************************************************************
+*#                                                            
+*# FUNCTION NAME: eeprom_disable_write_protect
+*#                                                            
+*# PARAMETERS   : None
+*#
+*# RETURNS      : Nothing
+*#
+*# SIDE EFFECTS :
+*#
+*# DESCRIPTION  : Disables write protection if applicable
+*#
+*#---------------------------------------------------------------------------
+*# HISTORY                                                    
+*#
+*# DATE         NAME            CHANGES                       
+*# ----         ----            -------                       
+*# Jan 14 2000  Johan Adolfsson Initial version (from PS pareerom.c)
+*#
+*#**************************************************************************/
+#define DBP_SAVE(x)
+#define ax_printf printk
+static void eeprom_disable_write_protect(void)
+{
+  /* Disable write protect */
+  if (eeprom.size == EEPROM_8KB)
+  {
+    /* Step 1 Set WEL = 1 (write 00000010 to address 1FFFh */
+    i2c_start();
+    i2c_outbyte(0xbe);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false\n"));
+    }
+    i2c_outbyte(0xFF);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 2\n"));
+    }
+    i2c_outbyte(0x02);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 3\n"));
+    }
+    i2c_stop();
+
+    i2c_delay(1000);
+
+    /* Step 2 Set RWEL = 1 (write 00000110 to address 1FFFh */
+    i2c_start();
+    i2c_outbyte(0xbe);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 55\n"));
+    }
+    i2c_outbyte(0xFF);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 52\n"));
+    }
+    i2c_outbyte(0x06);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 53\n"));
+    }
+    i2c_stop();
+    
+    /* Step 3 Set BP1, BP0, and/or WPEN bits (write 00000110 to address 1FFFh*/
+    i2c_start();
+    i2c_outbyte(0xbe);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 56\n"));
+    }
+    i2c_outbyte(0xFF);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 57\n"));
+    }
+    i2c_outbyte(0x06);
+    if(!i2c_getack())
+    {
+      DBP_SAVE(ax_printf("Get ack returns false 58\n"));
+    }
+    i2c_stop();
+    
+    /* Write protect disabled */
+  }
+}
+
+module_init(eeprom_init);
+
+/********************** END OF FILE e100eeprom.c *****************************/
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/ethernet.c linux/arch/cris/drivers/ethernet.c
--- v2.4.4/linux/arch/cris/drivers/ethernet.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/ethernet.c	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-/* $Id: ethernet.c,v 1.8 2001/02/27 13:52:48 bjornw Exp $
+/* $Id: ethernet.c,v 1.12 2001/04/05 11:43:11 tobiasa Exp $
  *
  * e100net.c: A network driver for the ETRAX 100LX network controller.
  *
@@ -7,6 +7,21 @@
  * The outline of this driver comes from skeleton.c.
  *
  * $Log: ethernet.c,v $
+ * Revision 1.12  2001/04/05 11:43:11  tobiasa
+ * Check dev before panic.
+ *
+ * Revision 1.11  2001/04/04 11:21:05  markusl
+ * Updated according to review remarks
+ *
+ * Revision 1.10  2001/03/26 16:03:06  bjornw
+ * Needs linux/config.h
+ *
+ * Revision 1.9  2001/03/19 14:47:48  pkj
+ * * Make sure there is always a pause after the network LEDs are
+ *   changed so they will not look constantly lit during heavy traffic.
+ * * Always use HZ when setting times relative to jiffies.
+ * * Use LED_NETWORK_SET() when setting the network LEDs.
+ *
  * Revision 1.8  2001/02/27 13:52:48  bjornw
  * malloc.h -> slab.h
  *
@@ -40,10 +55,13 @@
  *
  */
 
+#include <linux/config.h>
+
 #include <linux/module.h>
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
@@ -52,11 +70,7 @@
 #include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/spinlock.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 
@@ -65,11 +79,17 @@
 #include <linux/skbuff.h>
 
 #include <asm/svinto.h>     /* DMA and register descriptions */
+#include <asm/io.h>         /* LED_* I/O functions */
+#include <asm/dma.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
 
 //#define ETHDEBUG
-
 #define D(x)
 
+#define ETH_TX_DMA 0
+#define ETH_RX_DMA 1
+
 /*
  * The name of the card. Is used for messages and in the requests for
  * io regions, irqs and dma channels
@@ -126,12 +146,12 @@
 #define MDIO_PHYS_ADDR                      0x0
 
 /* Network flash constants */
-#define NET_FLASH_TIME                        2 /* 20 ms */
-#define NET_LINK_UP_CHECK_INTERVAL          200 /* 2 s   */
+#define NET_FLASH_TIME                  (HZ/50) /* 20 ms */
+#define NET_FLASH_PAUSE                (HZ/100) /* 10 ms */
+#define NET_LINK_UP_CHECK_INTERVAL       (2*HZ) /* 2 s   */
 
-/* RX_DESC_BUF_SIZE should be a multiple of four to avoid the buffer
- * alignment bug in Etrax 100 release 1
- */
+#define NO_NETWORK_ACTIVITY 0
+#define NETWORK_ACTIVITY    1
 
 #define RX_DESC_BUF_SIZE   256
 #define NBR_OF_RX_DESC     (RX_BUF_SIZE / \
@@ -146,8 +166,8 @@
 
 static unsigned char RxBuf[RX_BUF_SIZE];
 
-static etrax_dma_descr RxDescList[NBR_OF_RX_DESC];
-static etrax_dma_descr TxDesc;
+static etrax_dma_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(4)));
+static etrax_dma_descr TxDesc __attribute__ ((aligned(4)));
 
 static struct sk_buff *tx_skb;
 
@@ -155,8 +175,8 @@
 static struct timer_list speed_timer;
 static struct timer_list clear_led_timer;
 static int current_speed;
-static int led_clear_time;
-static int nolink;
+static int led_next_time;
+static int led_active;
 
 /* Index to functions, as function prototypes. */
 
@@ -184,6 +204,7 @@
 static void e100_reset_tranceiver(void);
 
 static void e100_clear_network_leds(unsigned long dummy);
+static void e100_set_network_leds(int active);
 
 #define tx_done(dev) (*R_DMA_CH0_CMD == 0)
 
@@ -201,7 +222,7 @@
 	int i;
 	int anOffset = 0;
 
-	printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000 Axis Communications AB\n");
+	printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2001 Axis Communications AB\n");
 
 	dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
 
@@ -212,6 +233,8 @@
 	if (!dev) {
 		printk("dev == NULL. Should this happen?\n");
 		dev = init_etherdev(dev, sizeof(struct net_local));
+		if (!dev)
+			panic("init_etherdev failed\n");
 	}
 
 	/* setup generic handlers and stuff in the dev struct */
@@ -272,13 +295,12 @@
 
 	/* Initialize speed indicator stuff. */
 
-	nolink = 0;
 	current_speed = 10;
 	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
 	speed_timer.function = e100_check_speed;
 	add_timer(&speed_timer);
 	clear_led_timer.function = e100_clear_network_leds;
-	clear_led_timer.expires = jiffies + 10;
+	clear_led_timer.expires = jiffies + HZ/10;
 	add_timer(&clear_led_timer);
 
 	return 0;
@@ -345,8 +367,17 @@
 
 	*R_NETWORK_MGM_CTRL = IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable);
 
-	*R_IRQ_MASK0_CLR = 0xe0000; /* clear excessive_col, over/underrun irq mask */
-	*R_IRQ_MASK2_CLR = 0xf; /* clear dma0 and 1 eop and descr irq masks */
+	*R_IRQ_MASK0_CLR =
+		IO_STATE(R_IRQ_MASK0_CLR, overrun, clr) |
+		IO_STATE(R_IRQ_MASK0_CLR, underrun, clr) |
+		IO_STATE(R_IRQ_MASK0_CLR, excessive_col, clr);
+	
+	/* clear dma0 and 1 eop and descr irq masks */
+	*R_IRQ_MASK2_CLR =
+		IO_STATE(R_IRQ_MASK2_CLR, dma0_descr, clr) |
+		IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) |
+		IO_STATE(R_IRQ_MASK2_CLR, dma1_descr, clr) |
+		IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr);
 
 	/* Reset and wait for the DMA channels */
 
@@ -383,17 +414,17 @@
 	 * and clean up on failure.
 	 */
 
-	if(request_dma(0, cardname)) {
+	if(request_dma(ETH_TX_DMA, cardname)) {
 		goto grace_exit;
 	}
 
-	if(request_dma(1, cardname)) {
+	if(request_dma(ETH_RX_DMA, cardname)) {
 	grace_exit:
 		/* this will cause some 'trying to free free irq' but what the heck... */
-		free_dma(0);
-		free_irq(NETWORK_DMARX_IRQ, NULL);
-		free_irq(NETWORK_DMATX_IRQ, NULL);
-		free_irq(NETWORK_STATUS_IRQ, NULL);
+		free_dma(ETH_TX_DMA);
+		free_irq(NETWORK_DMARX_IRQ, (void *)dev);
+		free_irq(NETWORK_DMATX_IRQ, (void *)dev);
+		free_irq(NETWORK_STATUS_IRQ, (void *)dev);
 		return -EAGAIN;
 	}
 
@@ -466,21 +497,19 @@
 e100_check_speed(unsigned long dummy)
 {
 	unsigned long data;
+	int old_speed = current_speed;
+
 	data = e100_get_mdio_reg(MDIO_BASE_STATUS_REG);
 	if (!(data & MDIO_LINK_UP_MASK)) {
-		nolink = 1;
-		LED_NETWORK_TX_SET(1); /* Make it red, link is down. */
+		current_speed = 0;
 	} else {
-		nolink = 0;
-		LED_NETWORK_TX_SET(0); /* Link is up again, clear red LED. */
 		data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG);
-		if (data & MDIO_SPEED) {
-			current_speed = 100;
-		} else {
-			current_speed = 10;
-		}
+		current_speed = (data & MDIO_SPEED ? 100 : 10);
 	}
 	
+	if (old_speed != current_speed)
+		e100_set_network_leds(NO_NETWORK_ACTIVITY);
+
 	/* Reinitialize the timer. */
 	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
 	add_timer(&speed_timer);
@@ -534,23 +563,26 @@
 static void
 e100_send_mdio_bit(unsigned char bit)
 {
-	volatile int i;
-	*R_NETWORK_MGM_CTRL = 2 | bit&1;
-	for (i=40; i; i--);
-	*R_NETWORK_MGM_CTRL = 6 | bit&1;
-	for (i=40; i; i--);
+	*R_NETWORK_MGM_CTRL =
+		IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable) |
+		IO_FIELD(R_NETWORK_MGM_CTRL, mdio, bit);
+	udelay(1);
+	*R_NETWORK_MGM_CTRL =
+		IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable) |
+		IO_MASK(R_NETWORK_MGM_CTRL, mdck) |
+		IO_FIELD(R_NETWORK_MGM_CTRL, mdio, bit);
+	udelay(1);
 }
 
 static unsigned char
 e100_receive_mdio_bit()
 {
 	unsigned char bit;
-	volatile int i;
 	*R_NETWORK_MGM_CTRL = 0;
-	bit = *R_NETWORK_STAT & 1;
-	for (i=40; i; i--);
-	*R_NETWORK_MGM_CTRL = 4;
-	for (i=40; i; i--);
+	bit = IO_EXTRACT(R_NETWORK_STAT, mdio, *R_NETWORK_STAT);
+	udelay(1);
+	*R_NETWORK_MGM_CTRL = IO_MASK(R_NETWORK_MGM_CTRL, mdck);
+	udelay(1);
 	return bit;
 }
 
@@ -566,7 +598,7 @@
 
 	cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) | (MDIO_BASE_CONTROL_REG << 2);
 
-	e100_send_mdio_cmd(cmd, 0);
+	e100_send_mdio_cmd(cmd, 1);
 	
 	data |= 0x8000;
 	
@@ -656,8 +688,8 @@
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	unsigned long irqbits = *R_IRQ_MASK2_RD;
-
-	if(irqbits & (1U << 3)) {
+ 
+	if(irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) {
 
 		/* acknowledge the eop interrupt */
 
@@ -671,10 +703,15 @@
 			 */
 			e100_rx(dev);
 			((struct net_local *)dev->priv)->stats.rx_packets++;
-			*R_DMA_CH1_CMD = 3; /* restart/continue on the channel, for safety */
-			*R_DMA_CH1_CLR_INTR = 3; /* clear dma channel 1 eop/descr irq bits */
-			/* now, we might have gotten another packet so we have to loop back
-			   and check if so */
+			/* restart/continue on the channel, for safety */
+			*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart);
+			/* clear dma channel 1 eop/descr irq bits */
+			*R_DMA_CH1_CLR_INTR =
+				IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) |
+				IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do);
+			
+			/* now, we might have gotten another packet
+			   so we have to loop back and check if so */
 		}
 	}
 }
@@ -692,8 +729,9 @@
 	unsigned long irqbits = *R_IRQ_MASK2_RD;
 	struct net_local *np = (struct net_local *)dev->priv;
 
-	if(irqbits & 2) { /* check for a dma0_eop interrupt */
-
+	/* check for a dma0_eop interrupt */
+	if(irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) { 
+		
 		/* This protects us from concurrent execution of
 		 * our dev->hard_start_xmit function above.
 		 */
@@ -727,12 +765,14 @@
 	struct net_local *np = (struct net_local *)dev->priv;
 	unsigned long irqbits = *R_IRQ_MASK0_RD;
 
-	if(irqbits & (1 << 19)) { /* check for overrun irq */
+	/* check for overrun irq */
+	if(irqbits & IO_STATE(R_IRQ_MASK0_RD, overrun, active)) { 
 		update_rx_stats(&np->stats); /* this will ack the irq */
 		D(printk("ethernet receiver overrun!\n"));
 	}
-	if(irqbits & (1 << 17)) { /* check for excessive collision irq */
-		*R_NETWORK_TR_CTRL = 1 << 8; /* clear the interrupt */
+	/* check for excessive collision irq */
+	if(irqbits & IO_STATE(R_IRQ_MASK0_RD, excessive_col, active)) { 
+		*R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr);
 		np->stats.tx_errors++;
 		D(printk("ethernet excessive collisions!\n"));
 	}
@@ -746,23 +786,19 @@
 	struct sk_buff *skb;
 	int length=0;
 	int i;
+	struct net_local *np = (struct net_local *)dev->priv;
 	struct etrax_dma_descr *mySaveRxDesc = myNextRxDesc;
 	unsigned char *skb_data_ptr;
 
-	/* light the network rx packet depending on the current speed.
-	** But only if link has been detected.
-	*/
-	if (!nolink)
-		if (current_speed == 10) {
-			LED_NETWORK_TX_SET(1);
-			LED_NETWORK_RX_SET(1);
-		} else
-			LED_NETWORK_RX_SET(1);
-  
-	/* Set the earliest time we may clear the LED */
+	if (!led_active && jiffies > led_next_time) {
+		/* light the network leds depending on the current speed. */
+		e100_set_network_leds(NETWORK_ACTIVITY);
+
+		/* Set the earliest time we may clear the LED */
+		led_next_time = jiffies + NET_FLASH_TIME;
+		led_active = 1;
+	}
 
-	led_clear_time = jiffies + NET_FLASH_TIME;
-  
 	/* If the packet is broken down in many small packages then merge
 	 * count how much space we will need to alloc with skb_alloc() for
 	 * it to fit.
@@ -790,6 +826,7 @@
 
 	skb = dev_alloc_skb(length - ETHER_HEAD_LEN);
 	if (!skb) {
+		np->stats.rx_errors++;
 		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
 		       dev->name);
 		return;
@@ -798,7 +835,7 @@
 	skb_put(skb, length - ETHER_HEAD_LEN);        /* allocate room for the packet body */
 	skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */
 
-#if 0
+#ifdef ETHDEBUG
 	printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n",
 	       skb->head, skb->data, skb->tail, skb->end);
 	printk("copying packet to 0x%x.\n", skb_data_ptr);
@@ -849,9 +886,17 @@
 	*R_NETWORK_GEN_CONFIG =
 		IO_STATE(R_NETWORK_GEN_CONFIG, phy,    mii_clk) |
 		IO_STATE(R_NETWORK_GEN_CONFIG, enable, off);
-
-	*R_IRQ_MASK0_CLR = 0xe0000; /* clear excessive_col, over/underrun irq mask */
-	*R_IRQ_MASK2_CLR = 0xf; /* clear dma0 and 1 eop and descr irq masks */
+	
+	*R_IRQ_MASK0_CLR =
+		IO_STATE(R_IRQ_MASK0_CLR, overrun, clr) |
+		IO_STATE(R_IRQ_MASK0_CLR, underrun, clr) |
+		IO_STATE(R_IRQ_MASK0_CLR, excessive_col, clr);
+	
+	*R_IRQ_MASK2_CLR =
+		IO_STATE(R_IRQ_MASK2_CLR, dma0_descr, clr) |
+		IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) |
+		IO_STATE(R_IRQ_MASK2_CLR, dma1_descr, clr) |
+		IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr);
 
 	/* Stop the receiver and the transmitter */
 
@@ -864,8 +909,8 @@
 	free_irq(NETWORK_DMATX_IRQ, (void *)dev);
 	free_irq(NETWORK_STATUS_IRQ, (void *)dev);
 
-	free_dma(0);
-	free_dma(1);
+	free_dma(ETH_TX_DMA);
+	free_dma(ETH_RX_DMA);
 
 	/* Update the statistics here. */
 
@@ -997,22 +1042,16 @@
 e100_hardware_send_packet(char *buf, int length)
 {
 	D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
-	/* light the network leds depending on the current speed.
-	** But only if link has been detected.
-	*/
-	if (!nolink) {
-		if (current_speed == 10) {
-			LED_NETWORK_TX_SET(1);
-			LED_NETWORK_RX_SET(1);
-		} else {
-			LED_NETWORK_RX_SET(1);
-		}
-	}
 
-	/* Set the earliest time we may clear the LED */
+	if (!led_active && jiffies > led_next_time) {
+		/* light the network leds depending on the current speed. */
+		e100_set_network_leds(NETWORK_ACTIVITY);
+
+		/* Set the earliest time we may clear the LED */
+		led_next_time = jiffies + NET_FLASH_TIME;
+		led_active = 1;
+	}
 
-	led_clear_time = jiffies + NET_FLASH_TIME;
-	
 	/* configure the tx dma descriptor */
 
 	TxDesc.sw_len = length;
@@ -1028,16 +1067,41 @@
 static void
 e100_clear_network_leds(unsigned long dummy)
 {
-	if (jiffies > led_clear_time) {
-		if (nolink)
-			LED_NETWORK_TX_SET(1);
-		else
-			LED_NETWORK_TX_SET(0);
-		LED_NETWORK_RX_SET(0); 
+        if (led_active && jiffies > led_next_time) {
+		e100_set_network_leds(NO_NETWORK_ACTIVITY);
+
+		/* Set the earliest time we may set the LED */
+		led_next_time = jiffies + NET_FLASH_PAUSE;
+		led_active = 0;
 	}
-	
-	clear_led_timer.expires = jiffies + 10;
+
+        clear_led_timer.expires = jiffies + HZ/10;
 	add_timer(&clear_led_timer);
+}
+
+static void
+e100_set_network_leds(int active)
+{
+#ifdef CONFIG_LED_OFF_DURING_ACTIVITY
+	int light_leds = (active == NO_NETWORK_ACTIVITY);
+#else
+	int light_leds = (active == NETWORK_ACTIVITY);
+#endif
+
+	if (!current_speed) {
+		/* Make LED red, link is down */
+		LED_NETWORK_SET(LED_RED);
+	}
+	else if (light_leds) {
+		if (current_speed == 10) {
+			LED_NETWORK_SET(LED_ORANGE);
+		} else {
+			LED_NETWORK_SET(LED_GREEN);
+		}
+	}
+	else {
+		LED_NETWORK_SET(LED_OFF);
+	}
 }
 
 static struct net_device dev_etrax_ethernet;  /* only got one */
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/gpio.c linux/arch/cris/drivers/gpio.c
--- v2.4.4/linux/arch/cris/drivers/gpio.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/gpio.c	Sat May 19 17:43:05 2001
@@ -1,4 +1,4 @@
-/* $Id: gpio.c,v 1.4 2001/02/27 13:52:48 bjornw Exp $
+/* $Id: gpio.c,v 1.7 2001/04/04 13:30:08 matsfg Exp $
  *
  * Etrax general port I/O device
  *
@@ -9,6 +9,15 @@
  *             Johan Adolfsson  (read/set directions)
  *
  * $Log: gpio.c,v $
+ * Revision 1.7  2001/04/04 13:30:08  matsfg
+ * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
+ *
+ * Revision 1.6  2001/03/26 16:03:06  bjornw
+ * Needs linux/config.h
+ *
+ * Revision 1.5  2001/03/26 14:22:03  bjornw
+ * Namechange of some config options
+ *
  * Revision 1.4  2001/02/27 13:52:48  bjornw
  * malloc.h -> slab.h
  *
@@ -25,6 +34,7 @@
  */
 
 #include <linux/config.h>
+
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -78,25 +88,25 @@
 	&port_pa_data_shadow, &port_pb_data_shadow };
 
 /* What direction bits that are user changeable 1=changeable*/
-#ifndef CONFIG_PA_CHANGEABLE_DIR
-#define CONFIG_PA_CHANGEABLE_DIR 0x00
+#ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR
+#define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00
 #endif
-#ifndef CONFIG_PB_CHANGEABLE_DIR
-#define CONFIG_PB_CHANGEABLE_DIR 0x00
+#ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR
+#define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00
 #endif
 
-#ifndef CONFIG_PA_CHANGEABLE_BITS
-#define CONFIG_PA_CHANGEABLE_BITS 0xFF
+#ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS
+#define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF
 #endif
-#ifndef CONFIG_PB_CHANGEABLE_BITS
-#define CONFIG_PB_CHANGEABLE_BITS 0xFF
+#ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS
+#define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF
 #endif
 
 
-static unsigned char changeable_dir[2] = { CONFIG_PA_CHANGEABLE_DIR,
-                                           CONFIG_PB_CHANGEABLE_DIR };
-static unsigned char changeable_bits[2] = { CONFIG_PA_CHANGEABLE_BITS,
-                                            CONFIG_PB_CHANGEABLE_BITS };
+static unsigned char changeable_dir[2] = { CONFIG_ETRAX_PA_CHANGEABLE_DIR,
+                                           CONFIG_ETRAX_PB_CHANGEABLE_DIR };
+static unsigned char changeable_bits[2] = { CONFIG_ETRAX_PA_CHANGEABLE_BITS,
+                                            CONFIG_ETRAX_PB_CHANGEABLE_BITS };
 
 static volatile unsigned char *dir[2] = { R_PORT_PA_DIR, R_PORT_PB_DIR };
 
@@ -240,7 +250,7 @@
 		default:
 			if(priv->minor == LEDS)
 				return gpio_leds_ioctl(cmd, arg);
-			else
+                        else
 				return -EINVAL;
 	}
 	
@@ -252,7 +262,12 @@
 {
 	unsigned char green;
 	unsigned char red;
-
+        static int initialized = 0;
+        if(!initialized)
+        {
+          initialized = 1;
+          init_ioremap();
+        }
 	switch (_IOC_NR(cmd)) {
 		case IO_LEDACTIVE_SET:
 			green = ((unsigned char) arg) & 1;
@@ -260,6 +275,11 @@
 			LED_ACTIVE_SET_G(green);
 			LED_ACTIVE_SET_R(red);
 			break;
+                case IO_LED_SETBIT:                 
+                        LED_BIT_SET(arg);
+                       break;
+                case IO_LED_CLRBIT:
+                        LED_BIT_CLR(arg);
 		default:
 			return -EINVAL;
 	}
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/i2c.c linux/arch/cris/drivers/i2c.c
--- v2.4.4/linux/arch/cris/drivers/i2c.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/i2c.c	Sat May 19 17:43:05 2001
@@ -12,6 +12,12 @@
 *!                                 don't use PB_I2C if DS1302 uses same bits,
 *!                                 use PB.
 *! $Log: i2c.c,v $
+*! Revision 1.7  2001/04/04 13:11:36  markusl
+*! Updated according to review remarks
+*!
+*! Revision 1.6  2001/03/19 12:43:00  markusl
+*! Made some symbols unstatic (used by the eeprom driver)
+*!
 *! Revision 1.5  2001/02/27 13:52:48  bjornw
 *! malloc.h -> slab.h
 *!
@@ -37,7 +43,7 @@
 *! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN
 *!
 *!***************************************************************************/
-/* $Id: i2c.c,v 1.5 2001/02/27 13:52:48 bjornw Exp $ */
+/* $Id: i2c.c,v 1.7 2001/04/04 13:11:36 markusl Exp $ */
 /****************** INCLUDE FILES SECTION ***********************************/
 
 #include <linux/module.h>
@@ -144,50 +150,50 @@
 
 /* generate i2c start condition */
 
-static void
+void
 i2c_start(void)
 {
-	//
-	// SCL=1 SDA=1
-	//
+	/*
+	 * SCL=1 SDA=1
+	 */
 	i2c_dir_out();
 	i2c_delay(CLOCK_HIGH_TIME/6);
 	i2c_data(I2C_DATA_HIGH);
 	i2c_clk(I2C_CLOCK_HIGH);
 	i2c_delay(CLOCK_HIGH_TIME);
-	//
-	// SCL=1 SDA=0
-	//
+	/*
+	 * SCL=1 SDA=0
+	 */
 	i2c_data(I2C_DATA_LOW);
 	i2c_delay(START_CONDITION_HOLD_TIME);
-	//
-	// SCL=0 SDA=0
-	//
+	/*
+	 * SCL=0 SDA=0
+	 */
 	i2c_clk(I2C_CLOCK_LOW);
 	i2c_delay(CLOCK_LOW_TIME);
 }
 
 /* generate i2c stop condition */
 
-static void
+void
 i2c_stop(void)
 {
 	i2c_dir_out();
 
-	//
-	// SCL=0 SDA=0
-	//
+	/*
+	 * SCL=0 SDA=0
+	 */
 	i2c_clk(I2C_CLOCK_LOW);
 	i2c_data(I2C_DATA_LOW);
 	i2c_delay(CLOCK_LOW_TIME*2);
-	//
-	// SCL=1 SDA=0
-	//
+	/*
+	 * SCL=1 SDA=0
+	 */
 	i2c_clk(I2C_CLOCK_HIGH);
 	i2c_delay(CLOCK_HIGH_TIME*2);
-	//
-	// SCL=1 SDA=1
-	//
+	/*
+	 * SCL=1 SDA=1
+	 */
 	i2c_data(I2C_DATA_HIGH);
 	i2c_delay(STOP_CONDITION_HOLD_TIME);
 
@@ -196,7 +202,7 @@
 
 /* write a byte to the i2c interface */
 
-static void
+void
 i2c_outbyte(unsigned char x)
 {
 	int i;
@@ -219,78 +225,75 @@
 	i2c_data(I2C_DATA_LOW);
 	i2c_delay(CLOCK_LOW_TIME/2);
 
-	//
-	// enable input
-	//
+	/*
+	 * enable input
+	 */
 	i2c_dir_in();
 }
 
 /* read a byte from the i2c interface */
 
-static unsigned char
+unsigned char
 i2c_inbyte(void)
 {
 	unsigned char aBitByte = 0;
 	int i;
 	int iaa;
-	//int dd= 0;
 
-	//
-	// enable output
-	//
+	/*
+	 * enable output
+	 */
 	i2c_dir_out();
-	//
-	// Release data bus by setting
-	// data high
-	//
+	/*
+	 * Release data bus by setting
+	 * data high
+	 */
 	i2c_data(I2C_DATA_HIGH);
-	//
-	// enable input
-	//
+	/*
+	 * enable input
+	 */
 	i2c_dir_in();
-	//
-	// Use PORT PB instead of I2C
-	// for input. (I2C not working)
-	//
+	/*
+	 * Use PORT PB instead of I2C
+	 * for input. (I2C not working)
+	 */
 	i2c_clk(1);
 	i2c_data(1);
-/*	*R_PORT_PB_DATA = *R_PORT_PB_READ | 0x03;*/
-	//
-	// get bits
-	//
+	/*
+	 * get bits
+	 */
 	for (i = 0; i < 8; i++) {
 		i2c_delay(CLOCK_LOW_TIME/2);
-		//
-		// low clock period
-		//
+		/*
+		 * low clock period
+		 */
 		i2c_clk(I2C_CLOCK_HIGH);
-		//
-		// switch off I2C
-		//
+		/*
+		 * switch off I2C
+		 */
 		i2c_data(1);
 		i2c_disable();
 		i2c_dir_in();
-		//
-		// wait before getting bit
-		//
+		/*
+		 * wait before getting bit
+		 */
 		i2c_delay(CLOCK_HIGH_TIME/2);
 		aBitByte = (aBitByte << 1);
 		iaa = i2c_getbit();
 		aBitByte = aBitByte | iaa ;
-		//if (iaa > 0) dd++;
-		//
-		// wait
-		//
+		/*
+		 * wait
+		 */
 		i2c_delay(CLOCK_HIGH_TIME/2);
-		//
-		// end clock puls
-		//
+		/*
+		 * end clock puls
+		 */
 		i2c_enable();
 		i2c_dir_out();
 		i2c_clk(I2C_CLOCK_LOW);
-		//
-		// low clock period
-		//
+		/*
+		 * low clock period
+		 */
 		i2c_delay(CLOCK_LOW_TIME/2);
 	}
 	i2c_dir_out();
@@ -305,49 +308,47 @@
 *#
 *#--------------------------------------------------------------------------*/
 
-static int
+int
 i2c_getack(void)
 {
 	int ack = 1;
-	//
-	// enable output
-	//
+	/*
+	 * enable output
+	 */
 	i2c_dir_out();
-	//
-	// Release data bus by setting
-	// data high
-	//
+	/*
+	 * Release data bus by setting
+	 * data high
+	 */
 	i2c_data(I2C_DATA_HIGH);
-	//
-	// enable input
-	//
+	/*
+	 * enable input
+	 */
 	i2c_dir_in();
 	i2c_delay(CLOCK_HIGH_TIME/4);
-	//
-	// generate ACK clock pulse
-	//
+	/*
+	 * generate ACK clock pulse
+	 */
 	i2c_clk(I2C_CLOCK_HIGH);
-	//
-	// Use PORT PB instead of I2C
-	// for input. (I2C not working)
-	//
+	/*
+	 * Use PORT PB instead of I2C
+	 * for input. (I2C not working)
+	 */
 	i2c_clk(1);
 	i2c_data(1);
-  
-/*	*R_PORT_PB_DATA = *R_PORT_PB_READ | 0x03;*/
-	//
-	// switch off I2C
-	//
+	/*
+	 * switch off I2C
+	 */
 	i2c_data(1);
 	i2c_disable();
 	i2c_dir_in();
-	//
-	// now wait for ack
-	//
+	/*
+	 * now wait for ack
+	 */
 	i2c_delay(CLOCK_HIGH_TIME/2);
-	//
-	// check for ack
-	//
+	/*
+	 * check for ack
+	 */
 	if(i2c_getbit())
 		ack = 0;
 	i2c_delay(CLOCK_HIGH_TIME/2);
@@ -357,20 +358,20 @@
 		i2c_delay(CLOCK_HIGH_TIME/2);
 	}
 
-	//
-	// end clock pulse
-	//
+	/*
+	 * end clock pulse
+	 */
 	i2c_enable();
 	i2c_dir_out();
 	i2c_clk(I2C_CLOCK_LOW);
 	i2c_delay(CLOCK_HIGH_TIME/4);
-	//
-	// enable output
-	//
+	/*
+	 * enable output
+	 */
 	i2c_dir_out();
-	//
-	// remove ACK clock pulse
-	//
+	/*
+	 * remove ACK clock pulse
+	 */
 	i2c_data(I2C_DATA_HIGH);
 	i2c_delay(CLOCK_LOW_TIME/2);
 	return ack;
@@ -383,32 +384,32 @@
 *# DESCRIPTION  : Send ACK on received data
 *#
 *#--------------------------------------------------------------------------*/
-static void
+void
 i2c_sendack(void)
 {
-	//
-	// enable output
-	//
+	/*
+	 * enable output
+	 */
 	i2c_delay(CLOCK_LOW_TIME);
 	i2c_dir_out();
-	//
-	// set ack pulse high
-	//
+	/*
+	 * set ack pulse high
+	 */
 	i2c_data(I2C_DATA_LOW);
-	//
-	// generate clock pulse
-	//
+	/*
+	 * generate clock pulse
+	 */
 	i2c_delay(CLOCK_HIGH_TIME/6);
 	i2c_clk(I2C_CLOCK_HIGH);
 	i2c_delay(CLOCK_HIGH_TIME);
 	i2c_clk(I2C_CLOCK_LOW);
 	i2c_delay(CLOCK_LOW_TIME/6);
-	//
-	// reset data out
-	//
+	/*
+	 * reset data out
+	 */
 	i2c_data(I2C_DATA_HIGH);
 	i2c_delay(CLOCK_LOW_TIME);
-	//
+	
 	i2c_dir_in();
 }
 
@@ -424,20 +425,22 @@
 	     unsigned char theValue)
 {
 	int error, cntr = 3;
+	unsigned long flags;
 		
 	do {
 		error = 0;
-		//
-		// we don't like to be interrupted
-		//
+		/*
+		 * we don't like to be interrupted
+		 */
+		save_flags(flags);
 		cli();
-		//
-		// generate start condition
-		//
+		/*
+		 * generate start condition
+		 */
 		i2c_start();
-		//
-		// dummy preamble
-		//
+		/*
+		 * dummy preamble
+		 */
 		i2c_outbyte(0x01);
 		i2c_data(I2C_DATA_HIGH);
 		i2c_clk(I2C_CLOCK_HIGH);
@@ -452,42 +455,42 @@
 		i2c_delay(CLOCK_LOW_TIME);
 
 		i2c_start();
-		//
-		// send slave address
-		//
+		/*
+		 * send slave address
+		 */
 		i2c_outbyte(theSlave);
-		//
-		// wait for ack
-		//
+		/*
+		 * wait for ack
+		 */
 		if(!i2c_getack())
 			error = 1;
-		//
-		// now select register
-		//
+		/*
+		 * now select register
+		 */
 		i2c_dir_out();
 		i2c_outbyte(theReg);
-		//
-		// now it's time to wait for ack
-		//
+		/*
+		 * now it's time to wait for ack
+		 */
 		if(!i2c_getack())
 			error |= 2;
-		//
-		// send register register data
-		//
+		/*
+		 * send register register data
+		 */
 		i2c_outbyte(theValue);
-		//
-		// now it's time to wait for ack
-		//
+		/*
+		 * now it's time to wait for ack
+		 */
 		if(!i2c_getack())
 			error |= 4;
-		//
-		// end byte stream
-		//
+		/*
+		 * end byte stream
+		 */
 		i2c_stop();
-		//
-		// enable interrupt again
-		//
-		sti();
+		/*
+		 * enable interrupt again
+		 */
+		restore_flags(flags);
 		
 	} while(error && cntr--);
 	
@@ -508,20 +511,22 @@
 {
 	unsigned char b = 0;
 	int error, cntr = 3;
+	unsigned long flags;
 		
 	do {
 		error = 0;
-		//
-		// we don't like to be interrupted
-		//
+		/*
+		 * we don't like to be interrupted
+		 */
+		save_flags(flags);
 		cli();
-		//
-		// generate start condition
-		//
+		/*
+		 * generate start condition
+		 */
 		i2c_start();
-		//
-		// dummy preamble
-		//
+		/*
+		 * dummy preamble
+		 */
 		i2c_outbyte(0x01);
 		i2c_data(I2C_DATA_HIGH);
 		i2c_clk(I2C_CLOCK_HIGH);
@@ -537,55 +542,56 @@
     
 		i2c_start();
     
-		//
-		// send slave address
-		//
+		/*
+		 * send slave address
+		 */
 		i2c_outbyte(theSlave);
-		//
-		// wait for ack
-		//
+		/*
+		 * wait for ack
+		 */
 		if(!i2c_getack())
 			error = 1;
-		//
-		// now select register
-		//
+		/*
+		 * now select register
+		 */
 		i2c_dir_out();
 		i2c_outbyte(theReg);
-		//
-		// now it's time to wait for ack
-		//
+		/*
+		 * now it's time to wait for ack
+		 */
 		if(!i2c_getack())
 			error = 1;
-		//
-		// repeat start condition
-		//
+		/*
+		 * repeat start condition
+		 */
 		i2c_delay(CLOCK_LOW_TIME);
 		i2c_start();
-		//
-		// send slave address
-		//
+		/*
+		 * send slave address
+		 */
 		i2c_outbyte(theSlave | 0x01);
-		//
-		// wait for ack
-		//
+		/*
+		 * wait for ack
+		 */
 		if(!i2c_getack())
 			error = 1;
-		//
-		// fetch register
-		//
+		/*
+		 * fetch register
+		 */
 		b = i2c_inbyte();
-		//
-		// send Ack
-		//
+		/*
+		 * send Ack
+		 */
 		i2c_sendack();
-		//
-		// end sequence
-		//
+		/*
+		 * end sequence
+		 */
 		i2c_stop();
-		//
-		// enable interrupt again
-		//
-		sti();	
+		/*
+		 * enable interrupt again
+		 */
+		restore_flags(flags);
+		
 	} while(error && cntr--);
 
 	return b;
@@ -616,7 +622,7 @@
 
 	switch (_IOC_NR(cmd)) {
 		case I2C_WRITEREG:
-			// write to an i2c slave
+			/* write to an i2c slave */
 			D(printk("i2cw %d %d %d\n", 
 				 I2C_ARGSLAVE(arg),
 				 I2C_ARGREG(arg),
@@ -628,7 +634,7 @@
 		case I2C_READREG:
 		{
 			unsigned char val;
-			// read from an i2c slave
+			/* read from an i2c slave */
 			D(printk("i2cr %d %d ", 
 				I2C_ARGSLAVE(arg),
 				I2C_ARGREG(arg)));
@@ -682,6 +688,8 @@
 	}
 
 	printk("I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
+	
+	return 0;
 }
 
 /* this makes sure that i2c_init is called during boot */
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/i2c.h linux/arch/cris/drivers/i2c.h
--- v2.4.4/linux/arch/cris/drivers/i2c.h	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/i2c.h	Sat May 19 17:43:05 2001
@@ -1,16 +1,16 @@
-/* $Id: i2c.h,v 1.2 2001/01/18 15:49:30 bjornw Exp $ */
+/* $Id: i2c.h,v 1.3 2001/03/19 12:43:01 markusl Exp $ */
 
 /* High level I2C actions */
 int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
 unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg);
 
 /* Low level I2C */
-static void i2c_start(void);
-static void i2c_stop(void);
-static void i2c_outbyte(unsigned char x);
-static unsigned char i2c_inbyte(void);
-static int i2c_getack(void);
-static void i2c_sendack(void);
+void i2c_start(void);
+void i2c_stop(void);
+void i2c_outbyte(unsigned char x);
+unsigned char i2c_inbyte(void);
+int i2c_getack(void);
+void i2c_sendack(void);
 
 
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/parport.c linux/arch/cris/drivers/parport.c
--- v2.4.4/linux/arch/cris/drivers/parport.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/parport.c	Tue May  1 16:04:56 2001
@@ -0,0 +1,591 @@
+/* $Id: parport.c,v 1.4 2001/04/06 13:04:02 hugo Exp $
+ * 
+ * Elinux parallel port driver
+ * NOTE!
+ *   Since par0 shares DMA with ser2 and par 1 shares DMA with ser3
+ *   this should be handled if both are enabled at the same time.
+ *   THIS IS NOT HANDLED YET!
+ *
+ * Copyright (c) 2001 Axis Communications AB
+ * 
+ * Author: Fredrik Hugosson
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <asm/svinto.h>
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+static inline int DPRINTK(void *nothing, ...) {return 0;}
+#endif
+
+/*
+ * Etrax100 DMAchannels:
+ * Par0 out : DMA2
+ * Par0 in  : DMA3
+ * Par1 out : DMA4
+ * Par1 in  : DMA5
+ * NOTE! par0 is hared with ser2 and par1 is shared with ser3 regarding
+ *       DMA and DMA irq
+ */
+
+//#define CONFIG_PAR0_INT 1
+//#define CONFIG_PAR1_INT 1
+
+#define SETF(var, reg, field, val) \
+	var = (var & ~IO_MASK(##reg##, field)) | IO_FIELD(##reg##, field, val)
+
+#define SETS(var, reg, field, val) \
+	var = (var & ~IO_MASK(##reg##, field)) | IO_STATE(##reg##, field, val)
+
+struct etrax100par_struct {
+	/* parallell port control */
+	volatile u32 *reg_ctrl_data; /* R_PARx_CTRL_DATA */
+	const volatile u32 *reg_status_data; /* R_PARx_STATUS_DATA */
+	volatile u32 *reg_config; /* R_PARx_CONFIG */
+	volatile u32 *reg_delay; /* R_PARx_DELAY */
+	
+	/* DMA control */
+	int odma;
+	unsigned long dma_irq;  /* bitnr in R_IRQ_MASK2 for dmaX_descr */
+
+	volatile char *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR, output */
+	volatile u32 *ofirstadr;   /* adr to R_DMA_CHx_FIRST, output */
+	volatile char *ocmdadr;     /* adr to R_DMA_CHx_CMD, output */
+	
+	volatile char *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR, input */
+	volatile u32 *ifirstadr;   /* adr to R_DMA_CHx_FIRST, input */
+	volatile char *icmdadr;     /* adr to R_DMA_CHx_CMD, input */
+	const volatile u8 *istatusadr;  /* adr to R_DMA_CHx_STATUS, input */
+	volatile u32 *ihwswadr;    /* adr to R_DMA_CHx_HWSW, input */
+
+	/* Non DMA interrupt stuff */
+	unsigned long int_irq; /* R_VECT_MASK_RD */
+	const volatile u32 *irq_mask_rd; /* R_IRQ_MASKX_RD */
+	volatile u32 *irq_mask_clr; /* R_IRQ_MASKX_RD */
+	const volatile u32 *irq_read; /* R_IRQ_READX */
+	volatile u32 *irq_mask_set; /* R_IRQ_MASKX_SET */
+	unsigned long irq_mask_tx;  /* bitmask in R_IRQ_ for tx (ready) int */
+	unsigned long irq_mask_rx;  /* bitmask in R_IRQ_ for rx (data) int */
+	unsigned long irq_mask_ecp_cmd;  /* mask in R_IRQ_ for ecp_cmd int */
+	unsigned long irq_mask_peri;  /* bitmask in R_IRQ_ for peri int */
+	int portnr;
+  
+	/* ----- end of fields initialised in port_table[] below ----- */
+
+	//  struct etrax_dma_descr tr_descr;
+	//  unsigned char tr_buf[LP_BUFFER_SIZE];
+	//  const unsigned char *tr_buf_curr; /* current char sent */
+	//  const unsigned char *tr_buf_last; /* last char in buf */
+  
+	//  int fifo_magic; /* fifo amount - bytes left in dma buffer */
+	//  unsigned char         fifo_didmagic; /* a fifo eop has been forced */
+	//  volatile int          tr_running; /* 1 if output is running */
+	
+	struct parport *port;
+  
+	/* Shadow registers */
+	volatile unsigned long reg_ctrl_data_shadow; /* for R_PARx_CTRL_DATA */
+	volatile unsigned long reg_config_shadow;    /* for R_PARx_CONFIG */
+	volatile unsigned long reg_delay_shadow;    /* for R_PARx_DELAY */
+};
+
+/* Always have the complete structs here, even if the port is not used!
+ *  (that way we can index this by the port number)
+ */
+static struct etrax100par_struct port_table[] = {
+	{ 
+		R_PAR0_CTRL_DATA,
+		R_PAR0_STATUS_DATA,
+		R_PAR0_CONFIG,
+		R_PAR0_DELAY,
+		/* DMA interrupt stuff */
+		2,
+		1U << 4, /* uses DMA 2 and 3 */
+		R_DMA_CH2_CLR_INTR,
+		R_DMA_CH2_FIRST,
+		R_DMA_CH2_CMD,
+		R_DMA_CH3_CLR_INTR,
+		R_DMA_CH3_FIRST,
+		R_DMA_CH3_CMD,
+		R_DMA_CH3_STATUS,
+		R_DMA_CH3_HWSW,
+		/* Non DMA interrupt stuff */
+		IO_BITNR(R_VECT_MASK_RD, par0),
+		R_IRQ_MASK0_RD,
+		R_IRQ_MASK0_CLR,
+		R_IRQ_READ0,
+		R_IRQ_MASK0_SET,
+		IO_FIELD(R_IRQ_MASK0_RD, par0_ready, 1U), /* tx (ready)*/
+		IO_FIELD(R_IRQ_MASK0_RD, par0_data, 1U), /* rx (data)*/
+		IO_FIELD(R_IRQ_MASK0_RD, par0_ecp_cmd, 1U), /* ecp_cmd */
+		IO_FIELD(R_IRQ_MASK0_RD, par0_peri, 1U), /* peri */
+		0
+	},
+	{
+		R_PAR1_CTRL_DATA,
+		R_PAR1_STATUS_DATA,
+		R_PAR1_CONFIG,
+		R_PAR1_DELAY,
+		/* DMA interrupt stuff */
+		4,
+		1U << 8, /* uses DMA 4 and 5 */
+		
+		R_DMA_CH4_CLR_INTR,
+		R_DMA_CH4_FIRST,
+		R_DMA_CH4_CMD,
+		R_DMA_CH5_CLR_INTR,
+		R_DMA_CH5_FIRST,
+		R_DMA_CH5_CMD,
+		R_DMA_CH5_STATUS,
+		R_DMA_CH5_HWSW,
+		/* Non DMA interrupt stuff */
+		IO_BITNR(R_VECT_MASK_RD, par1),
+		R_IRQ_MASK1_RD,
+		R_IRQ_MASK1_CLR,
+		R_IRQ_READ1,
+		R_IRQ_MASK1_SET,
+		IO_FIELD(R_IRQ_MASK1_RD, par1_ready, 1U), /* tx (ready)*/
+		IO_FIELD(R_IRQ_MASK1_RD, par1_data, 1U), /* rx (data)*/
+		IO_FIELD(R_IRQ_MASK1_RD, par1_ecp_cmd, 1U), /* ecp_cmd */
+		IO_FIELD(R_IRQ_MASK1_RD, par1_peri, 1U), /* peri */
+		1
+	}
+};
+
+
+#define NR_PORTS (sizeof(port_table)/sizeof(struct etrax100par_struct))
+
+static void
+parport_etrax_write_data(struct parport *p, unsigned char value)
+{
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	DPRINTK("* E100 PP %d: etrax_write_data %02X\n", p->portnum, value);
+	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, data, value);
+	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
+}
+
+
+static unsigned char
+parport_etrax_read_data(struct parport *p)
+{
+	unsigned char ret;
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	ret = IO_EXTRACT(R_PAR0_STATUS_DATA, data, *info->reg_status_data);
+
+	DPRINTK("* E100 PP %d: etrax_read_data %02X\n", p->portnum, ret);
+	return ret;
+}
+
+
+static void
+parport_etrax_write_control(struct parport *p, unsigned char control)
+{
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	DPRINTK("* E100 PP %d: etrax_write_control %02x\n", p->portnum, control);
+  
+	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, strb,
+	     (control & PARPORT_CONTROL_STROBE) > 0);
+	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, autofd,
+	     (control & PARPORT_CONTROL_AUTOFD) > 0);
+	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, init,
+	     (control & PARPORT_CONTROL_INIT) > 0);
+	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, seli,
+	     (control & PARPORT_CONTROL_SELECT) > 0);
+
+	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
+}
+
+
+static unsigned char
+parport_etrax_read_control( struct parport *p)
+{
+	unsigned char ret = 0;
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	if (IO_EXTRACT(R_PAR0_CTRL_DATA, strb, info->reg_ctrl_data_shadow))
+		ret |= PARPORT_CONTROL_STROBE;
+	if (IO_EXTRACT(R_PAR0_CTRL_DATA, autofd, info->reg_ctrl_data_shadow))
+		ret |= PARPORT_CONTROL_AUTOFD;
+	if (IO_EXTRACT(R_PAR0_CTRL_DATA, init, info->reg_ctrl_data_shadow))
+		ret |= PARPORT_CONTROL_INIT;
+	if (IO_EXTRACT(R_PAR0_CTRL_DATA, seli, info->reg_ctrl_data_shadow))
+		ret |= PARPORT_CONTROL_SELECT;
+
+	DPRINTK("* E100 PP %d: etrax_read_control %02x\n", p->portnum, ret);
+	return ret;
+}
+
+
+static unsigned char
+parport_etrax_frob_control(struct parport *p, unsigned char mask,
+                           unsigned char val)
+{
+	unsigned char old;
+
+	DPRINTK("* E100 PP %d: frob_control mask %02x, value %02x\n",
+		p->portnum, mask, val);
+	old = parport_etrax_read_control(p);
+	parport_etrax_write_control(p, (old & ~mask) ^ val);
+	return old;
+}
+
+
+static unsigned char
+parport_etrax_read_status(struct parport *p)
+{
+	unsigned char ret = 0;
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	if (IO_EXTRACT(R_PAR0_STATUS_DATA, fault, *info->reg_status_data))
+		ret |= PARPORT_STATUS_ERROR;
+	if (IO_EXTRACT(R_PAR0_STATUS_DATA, sel, *info->reg_status_data))
+		ret |= PARPORT_STATUS_SELECT;
+	if (!IO_EXTRACT(R_PAR0_STATUS_DATA, perr, *info->reg_status_data))
+		ret |= PARPORT_STATUS_PAPEROUT;
+	if (IO_EXTRACT(R_PAR0_STATUS_DATA, ack, *info->reg_status_data))
+		ret |= PARPORT_STATUS_ACK;
+	if (!IO_EXTRACT(R_PAR0_STATUS_DATA, busy, *info->reg_status_data))
+		ret |= PARPORT_STATUS_BUSY;
+
+	DPRINTK("* E100 PP %d: status register %04x\n",
+		p->portnum, *info->reg_status_data);
+	DPRINTK("* E100 PP %d: read_status %02x\n", p->portnum, ret);
+	return ret;
+}
+
+
+static void
+parport_etrax_enable_irq(struct parport *p)
+{
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+	*info->irq_mask_set = info->irq_mask_tx;
+	DPRINTK("* E100 PP %d: enable irq\n", p->portnum);
+}
+
+
+static void
+parport_etrax_disable_irq(struct parport *p)
+{
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+	*info->irq_mask_clr = info->irq_mask_tx;
+	DPRINTK("* E100 PP %d: disable irq\n", p->portnum);
+}
+
+
+static void
+parport_etrax_data_forward(struct parport *p)
+{
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	DPRINTK("* E100 PP %d: forward mode\n", p->portnum);
+	SETS(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, oe, enable);
+	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
+}
+
+
+static void
+parport_etrax_data_reverse(struct parport *p)
+{
+	struct etrax100par_struct *info =
+		(struct etrax100par_struct *)p->private_data;
+
+	DPRINTK("* E100 PP %d: reverse mode\n", p->portnum);
+	SETS(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, oe, disable);
+	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
+}
+
+
+static void
+parport_etrax_init_state(struct pardevice *dev, struct parport_state *s)
+{
+	DPRINTK("* E100 PP: parport_etrax_init_state\n");
+}
+
+
+static void
+parport_etrax_save_state(struct parport *p, struct parport_state *s)
+{
+	DPRINTK("* E100 PP: parport_etrax_save_state\n");
+}
+
+
+static void
+parport_etrax_restore_state(struct parport *p, struct parport_state *s)
+{
+	DPRINTK("* E100 PP: parport_etrax_restore_state\n");
+}
+
+
+static void
+parport_etrax_inc_use_count(void)
+{
+	MOD_INC_USE_COUNT;
+}
+
+
+static void
+parport_etrax_dec_use_count(void)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+
+static struct
+parport_operations pp_etrax_ops = {
+	parport_etrax_write_data,
+	parport_etrax_read_data,
+
+	parport_etrax_write_control,
+	parport_etrax_read_control,
+	parport_etrax_frob_control,
+
+	parport_etrax_read_status,
+
+	parport_etrax_enable_irq,
+	parport_etrax_disable_irq,
+
+	parport_etrax_data_forward, 
+	parport_etrax_data_reverse, 
+
+	parport_etrax_init_state,
+	parport_etrax_save_state,
+	parport_etrax_restore_state,
+
+	parport_etrax_inc_use_count,
+	parport_etrax_dec_use_count,
+
+	parport_ieee1284_epp_write_data,
+	parport_ieee1284_epp_read_data,
+	parport_ieee1284_epp_write_addr,
+	parport_ieee1284_epp_read_addr,
+
+	parport_ieee1284_ecp_write_data,
+	parport_ieee1284_ecp_read_data,
+	parport_ieee1284_ecp_write_addr,
+
+	parport_ieee1284_write_compat,
+	parport_ieee1284_read_nibble,
+	parport_ieee1284_read_byte,
+};
+
+	
+static void 
+parport_etrax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct etrax100par_struct *info = (struct etrax100par_struct *)
+		((struct parport *)dev_id)->private_data;
+	DPRINTK("* E100 PP %d: Interrupt received\n",
+		((struct parport *)dev_id)->portnum);
+	*info->irq_mask_clr = info->irq_mask_tx;
+	parport_generic_irq(irq, (struct parport *)dev_id, regs);
+}
+
+/* ----------- Initialisation code --------------------------------- */
+
+static void 
+parport_etrax_show_parallel_version(void)
+{
+	printk("ETRAX 100LX parallel port driver v1.0, (c) 2001 Axis Communications AB\n");
+}
+
+#ifdef CONFIG_ETRAX_PAR0_DMA
+#define PAR0_USE_DMA 1
+#else
+#define PAR0_USE_DMA 0
+#endif
+
+#ifdef CONFIG_ETRAX_PAR1_DMA
+#define PAR1_USE_DMA 1
+#else
+#define PAR1_USE_DMA 0
+#endif
+
+static void 
+parport_etrax_init_registers(void)
+{
+	struct etrax100par_struct *info;
+	int i;
+
+	/* The different times below will be (value*160 + 20) ns,    */
+	/* i.e. 20ns-4.98us. E.g. if setup is set to 00110 (0x6),    */
+	/* the setup time will be (6*160+20) = 980ns.                */
+
+	for (i = 0, info = port_table; i < 2; i++, info++) {
+#ifndef CONFIG_ETRAX_PARALLEL_PORT0
+		if (i == 0)
+			continue;
+#endif
+#ifndef CONFIG_ETRAX_PARALLEL_PORT1
+		if (i == 1)
+			continue;
+#endif
+		info->reg_config_shadow = 
+			IO_STATE(R_PAR0_CONFIG, iseli, inv)       |
+			IO_STATE(R_PAR0_CONFIG, iautofd, inv)     |
+			IO_STATE(R_PAR0_CONFIG, istrb, inv)       |
+			IO_STATE(R_PAR0_CONFIG, iinit, inv)       |
+			IO_STATE(R_PAR0_CONFIG, rle_in, disable)  |
+			IO_STATE(R_PAR0_CONFIG, rle_out, disable) |
+			IO_STATE(R_PAR0_CONFIG, enable, on)       |
+			IO_STATE(R_PAR0_CONFIG, force, off)       |
+			IO_STATE(R_PAR0_CONFIG, ign_ack, wait)    |
+			IO_STATE(R_PAR0_CONFIG, oe_ack, wait_oe)  |
+			IO_STATE(R_PAR0_CONFIG, mode, manual);
+
+		if ((i == 0 && PAR0_USE_DMA) || (i == 1 && PAR1_USE_DMA))
+			info->reg_config_shadow |=
+				IO_STATE(R_PAR0_CONFIG, dma, enable);
+		else
+			info->reg_config_shadow |=
+				IO_STATE(R_PAR0_CONFIG, dma, disable);
+
+		*info->reg_config = info->reg_config_shadow;
+
+		info->reg_ctrl_data_shadow = 
+			IO_STATE(R_PAR0_CTRL_DATA, peri_int, nop)    |
+			IO_STATE(R_PAR0_CTRL_DATA, oe, enable)       |
+			IO_STATE(R_PAR0_CTRL_DATA, seli, inactive)   |
+			IO_STATE(R_PAR0_CTRL_DATA, autofd, inactive) |
+			IO_STATE(R_PAR0_CTRL_DATA, strb, inactive)   |
+			IO_STATE(R_PAR0_CTRL_DATA, init, inactive)   |
+			IO_STATE(R_PAR0_CTRL_DATA, ecp_cmd, data)    |
+			IO_FIELD(R_PAR0_CTRL_DATA, data, 0);
+		*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
+
+		/* Clear peri int without setting shadow */
+		*info->reg_ctrl_data = info->reg_ctrl_data_shadow |
+			IO_STATE(R_PAR0_CTRL_DATA, peri_int, ack);
+
+		info->reg_delay_shadow = 
+			IO_FIELD(R_PAR0_DELAY, setup, 5)  |
+			IO_FIELD(R_PAR0_DELAY, strobe, 5) |
+			IO_FIELD(R_PAR0_DELAY, hold, 5);
+		*info->reg_delay = info->reg_delay_shadow;
+	}
+
+#ifdef CONFIG_ETRAX_PARALLEL_PORT0
+#ifdef CONFIG_ETRAX_PAR0_DMA
+	RESET_DMA(2);
+	WAIT_DMA(2);
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+	printk(" Warning - DMA clash with ser2!\n");
+#endif /* SERIAL_PORT2 */
+#endif /* DMA */
+#endif /* PORT0 */
+
+#ifdef CONFIG_ETRAX_PARALLEL_PORT1
+#ifdef CONFIG_ETRAX_PAR1_DMA
+	RESET_DMA(4);
+	WAIT_DMA(4);
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
+	printk(" Warning - DMA clash with ser3!\n");
+#endif /* SERIAL_PORT3 */
+#endif /* DMA */
+#endif /* PORT1 */
+} 
+
+
+int __init
+parport_etrax_init(void)
+{
+	struct parport *p;
+	int port_exists = 0;
+	int i;
+	struct etrax100par_struct *info;
+        const char *names[] = { "parallel 0 tx+rx", "parallel 1 tx+rx" };
+
+	parport_etrax_show_parallel_version();
+	parport_etrax_init_registers();
+
+        for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
+#ifndef CONFIG_ETRAX_PARALLEL_PORT0
+		if (i == 0)
+			continue;
+#endif
+#ifndef CONFIG_ETRAX_PARALLEL_PORT1
+		if (i == 1)
+			continue;
+#endif
+                p = parport_register_port((unsigned long)0, info->int_irq,
+                                          PARPORT_DMA_NONE, &pp_etrax_ops);
+                if (!p)
+			continue;
+
+                info->port = p;
+                p->private_data = info;
+                /* Axis FIXME: Set mode flags. */
+                /* p->modes = PARPORT_MODE_TRISTATE | PARPORT_MODE_SAFEININT; */
+
+	        if(request_irq(info->int_irq, parport_etrax_interrupt,
+                               SA_SHIRQ, names[i], p)) {
+	        	parport_unregister_port (p);
+                        continue;
+                }
+
+                printk(KERN_INFO "%s: ETRAX 100LX port %d using irq\n",
+                       p->name, i);
+                parport_proc_register(p);
+                parport_announce_port(p);
+                port_exists = 1;
+        }
+
+	return port_exists;
+}
+
+void __exit
+parport_etrax_exit(void)
+{
+	int i;
+	struct etrax100par_struct *info;
+
+        for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
+#ifndef CONFIG_ETRAX_PARALLEL_PORT0
+		if (i == 0)
+			continue;
+#endif
+#ifndef CONFIG_ETRAX_PARALLEL_PORT1
+		if (i == 1)
+			continue;
+#endif
+		if (info->int_irq != PARPORT_IRQ_NONE)
+			free_irq(info->int_irq, info->port);
+		parport_proc_unregister(info->port);
+		parport_unregister_port(info->port);
+        }
+}
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/serial.c linux/arch/cris/drivers/serial.c
--- v2.4.4/linux/arch/cris/drivers/serial.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/serial.c	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-/* $Id: serial.c,v 1.10 2001/03/05 13:14:07 bjornw Exp $
+/* $Id: serial.c,v 1.12 2001/04/19 12:23:07 bjornw Exp $
  *
  * Serial port driver for the ETRAX 100LX chip
  *
@@ -7,6 +7,15 @@
  *      Many, many authors. Based once upon a time on serial.c for 16x50.
  *
  * $Log: serial.c,v $
+ * Revision 1.12  2001/04/19 12:23:07  bjornw
+ * CONFIG_RS485 -> CONFIG_ETRAX_RS485
+ *
+ * Revision 1.11  2001/04/05 14:29:48  markusl
+ * Updated according to review remarks i.e.
+ * -Use correct types in port structure to avoid compiler warnings
+ * -Try to use IO_* macros whenever possible
+ * -Open should never return -EBUSY
+ *
  * Revision 1.10  2001/03/05 13:14:07  bjornw
  * Another spelling fix
  *
@@ -190,7 +199,7 @@
  *
  */
 
-static char *serial_version = "$Revision: 1.10 $";
+static char *serial_version = "$Revision: 1.12 $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -299,6 +308,18 @@
 #define REG_BAUD 3
 #define REG_XOFF 4  /* this is a 32 bit register */
 
+/*
+ * General note regarding the use of IO_* macros in this file: 
+ *
+ * We will use the bits defined for DMA channel 6 when using various
+ * IO_* macros (e.g. IO_STATE, IO_MASK, IO_EXTRACT) and _assume_ they are
+ * the same for all channels (which of course they are).
+ *
+ * We will also use the bits defined for serial port 0 when writing commands
+ * to the different ports, as these bits too are the same for all ports.
+ */
+
+
 /* this is the data for the four serial ports in the etrax100 */
 /*  DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) */
 /* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */
@@ -343,9 +364,9 @@
 
 
 /* RS-485 */
-#if defined(CONFIG_RS485)
-#if defined(CONFIG_RS485_ON_PA)
-static int rs485_pa_bit = CONFIG_RS485_ON_PA_BIT;
+#if defined(CONFIG_ETRAX_RS485)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
+static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;
 #endif
 #endif
   
@@ -421,8 +442,8 @@
   }
 };
 
-#if defined(CONFIG_RS485) && defined(CONFIG_RS485_ON_PA)
-unsigned char rs485_pa_port = CONFIG_RS485_ON_PA_BIT;
+#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_RS485_ON_PA)
+unsigned char rs485_pa_port = CONFIG_ETRAX_RS485_ON_PA_BIT;
 #endif
 
 #define E100_RTS_MASK 0x20
@@ -668,7 +689,8 @@
 {
 #ifndef CONFIG_SVINTO_SIM
 	/* disable the receiver */
-	info->port[REG_REC_CTRL] = (info->rx_ctrl &= ~0x40);
+	info->port[REG_REC_CTRL] = info->rx_ctrl &=
+		~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable);
 #endif
 }
 
@@ -677,7 +699,8 @@
 {
 #ifndef CONFIG_SVINTO_SIM
 	/* enable the receiver */
-	info->port[REG_REC_CTRL] = (info->rx_ctrl |= 0x40);
+	info->port[REG_REC_CTRL] = info->rx_ctrl |=
+		IO_MASK(R_SERIAL0_REC_CTRL, rec_enable);
 #endif
 }
 
@@ -747,14 +770,14 @@
 }
 #endif
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 /* Enable RS-485 mode on selected port. This is UGLY. */
 static int
 e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r)
 {
 	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
 
-#if defined(CONFIG_RS485_ON_PA)	
+#if defined(CONFIG_ETRAX_RS485_ON_PA)	
 	*R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);
 #endif
 
@@ -766,7 +789,6 @@
 	return 0;
 }
 
-/* Enable RS-485 mode on selected port. This is UGLY. */
 static int
 e100_write_rs485(struct tty_struct *tty,struct rs485_write *r)
 {
@@ -782,7 +804,7 @@
 	 * the receiver before initiating a DMA transfer
 	 */
 	e100_rts(info, info->rs485.rts_on_send);
-#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
 	e100_disable_rx(info);
 	e100_disable_rxdma_irq(info);
 #endif
@@ -824,14 +846,16 @@
 	max_j = jiffies + (delay_ms * HZ)/1000 + 10;
 
 	while (jiffies < max_j ) {
-	  if (info->port[REG_STATUS] & 0x20) {
+	  if (info->port[REG_STATUS] &
+	      IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
 	    for( i=0 ; i<100; i++ ) {};
-	    if (info->port[REG_STATUS] & 0x20) {
+	    if (info->port[REG_STATUS] &
+		IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
 	      /* ~25 for loops per usec */
-	      stop_delay = 25 * (1000000 / info->baud);
+	      stop_delay = 1000000 / info->baud;
 	      if(cflags & CSTOPB) 
 		stop_delay *= 2;
-	      for( i=0 ; i<stop_delay; i++ ) {};
+	      udelay(stop_delay);
 	      break;
 	    }
 	  }
@@ -839,7 +863,7 @@
 
 	e100_rts(info, info->rs485.rts_after_sent);
 	
-#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
 	e100_enable_rx(info);
 	e100_enable_rxdma_irq(info);
 #endif
@@ -942,7 +966,9 @@
 	return;
 #endif
 	/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
-	*info->oclrintradr = 3;
+	*info->oclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
 
 #ifdef SERIAL_DEBUG_INTR
 	if(info->line == SERIAL_DEBUG_LINE)
@@ -987,19 +1013,20 @@
 		/* our job here is done, don't schedule any new DMA transfer */
 		info->tr_running = 0;
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 		/* Check if we should toggle RTS now */
 		if (info->rs485.enabled)
 		{
 			/* Make sure fifo is empty */
 			int in_fifo = 0 ;
 			do{
-				in_fifo = (*info->ostatusadr) & 0x007F ;
+				in_fifo = IO_EXTRACT(R_DMA_CH6_STATUS, avail,
+						    *info->ostatusadr);
 			}  while (in_fifo > 0) ;
 			/* Any way to really check transmitter empty? (TEMT) */
 			/* Control RTS to set to RX mode */
 			e100_rts(info, info->rs485.rts_after_sent); 
-#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
 			e100_enable_rx(info);
 			e100_enable_rxdma_irq(info);
 #endif
@@ -1060,7 +1087,9 @@
 
 	/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
 
-	*info->iclrintradr = 3;
+	*info->iclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
 
 	if(!tty) /* something wrong... */
 		return;
@@ -1088,7 +1117,9 @@
 		/* read the status register so we can detect errors */
 		rstat = info->port[REG_STATUS];
 
-		if(rstat & 0xe) {
+		if(rstat & (IO_MASK(R_SERIAL0_STATUS, overrun) |
+			    IO_MASK(R_SERIAL0_STATUS, par_err) |
+			    IO_MASK(R_SERIAL0_STATUS, framing_err))) {
 			/* if we got an error, we must reset it by reading the
 			 * data_in field
 			 */
@@ -1148,7 +1179,7 @@
 	descr->status = 0;
 
 	*info->ifirstadr = virt_to_phys(descr);
-	*info->icmdadr = 1; /* start */
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
 
 #ifdef SERIAL_HANDLE_EARLY_ERRORS
 	e100_enable_serial_data_irq(info);
@@ -1170,8 +1201,9 @@
 
 	/* reset the input dma channel to be sure it works */
 	
-	*info->icmdadr = 4;
-	while((*info->icmdadr & 7) == 4);
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+	while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+	      IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
 
 	descr = &info->rec_descr;
 	
@@ -1186,7 +1218,8 @@
 	info->tty->flip.count = 0;
 
 	*info->ifirstadr = virt_to_phys(descr);
-	*info->icmdadr = 1; /* start */
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
+	
 }
 
 
@@ -1293,7 +1326,7 @@
 static struct timer_list flush_timer;
 
 static void 
-timed_flush_handler(void)
+timed_flush_handler(unsigned long ptr)
 {
 	struct e100_serial *info;
 	int i;
@@ -1381,7 +1414,7 @@
 				PROCSTAT(early_errors_cnt[info->line]++);
 
 				/* restart the DMA */
-				*info->icmdadr = 3;
+				*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
 			} 
 			else { /* it was a valid byte, now let the dma do the rest */
 #ifdef SERIAL_DEBUG_INTR
@@ -1472,7 +1505,7 @@
 	if (info->flags & ASYNC_INITIALIZED) {
 		free_page(page);
 		restore_flags(flags);
-		return -EBUSY;
+		return 0;
 	}
 	
 	if (info->xmit.buf)
@@ -1518,14 +1551,22 @@
 	 * Reset the DMA channels and make sure their interrupts are cleared
 	 */
 	
-	*info->icmdadr = 4; /* reset command */
-	*info->ocmdadr = 4; /* reset command */
-	
-	while((*info->icmdadr & 7) == 4); /* wait until reset cycle is complete */
-	while((*info->ocmdadr & 7) == 4);
-	
-	*info->iclrintradr = 3; /* make sure the irqs are cleared */
-	*info->oclrintradr = 3;
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+	*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+
+	/* wait until reset cycle is complete */
+	while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+	      IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+
+	while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
+	      IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+	
+	*info->iclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
+	*info->oclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
 	
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1597,8 +1638,8 @@
 
 	/* reset both dma channels */
 
-	*info->icmdadr = 4;
-	*info->ocmdadr = 4;
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+	*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
 
 #endif /* CONFIG_SVINTO_SIM */
 
@@ -1658,42 +1699,51 @@
 #ifndef CONFIG_SVINTO_SIM
 	info->port[REG_BAUD] = cflag_to_etrax_baud(cflag);
 	/* start with default settings and then fill in changes */
-	
-	info->rx_ctrl &= ~(0x07); /* 8 bit, no/even parity */
-	info->tx_ctrl &= ~(0x37); /* 8 bit, no/even parity, 1 stop bit, no cts */
+
+	/* 8 bit, no/even parity */
+	info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) |
+			   IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) |
+			   IO_MASK(R_SERIAL0_REC_CTRL, rec_par));
+
+	/* 8 bit, no/even parity, 1 stop bit, no cts */
+	info->tx_ctrl &= ~(IO_MASK(R_SERIAL0_TR_CTRL, tr_bitnr) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, tr_par_en) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, tr_par) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, stop_bits) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, auto_cts));
 	
 	if ((cflag & CSIZE) == CS7) {
 		/* set 7 bit mode */
-		info->tx_ctrl |= 0x01;
-		info->rx_ctrl |= 0x01;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit);
 	}
 	
 	if (cflag & CSTOPB) {
 		/* set 2 stop bit mode */
-		info->tx_ctrl |= 0x10;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, two_bits);
 	}	  
 	
 	if (cflag & PARENB) {
 		/* enable parity */
-		info->tx_ctrl |= 0x02;
-		info->rx_ctrl |= 0x02;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
 	}
 	
 	if (cflag & PARODD) {
 		/* set odd parity */
-		info->tx_ctrl |= 0x04;
-		info->rx_ctrl |= 0x04;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
 	}
 	
 	if (cflag & CRTSCTS) {
 		/* enable automatic CTS handling */
-		info->tx_ctrl |= 0x20;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, active);
 	}
 	
 	/* make sure the tx and rx are enabled */
 	
-	info->tx_ctrl |= 0x40;
-	info->rx_ctrl |= 0x40;
+	info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable);
+	info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
 
 	/* actually write the control regs to the hardware */
 	
@@ -2330,7 +2380,7 @@
 				return -EFAULT;
 			return 0;
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 		case TIOCSERSETRS485:
 			error = verify_area(VERIFY_WRITE, (void *) arg,
 					sizeof(struct rs485_control));
@@ -2488,10 +2538,10 @@
 
 	/* port closed */
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 	if (info->rs485.enabled) {
 		info->rs485.enabled = 0;
-#if defined(CONFIG_RS485_ON_PA)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
 		*R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit);
 #endif
 	}
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/serial.h linux/arch/cris/drivers/serial.h
--- v2.4.4/linux/arch/cris/drivers/serial.h	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/serial.h	Tue May  1 16:04:56 2001
@@ -25,26 +25,26 @@
 
 struct e100_serial {
 	int                   baud;
-	volatile unsigned char *	port; /* R_SERIALx_CTRL */
-	unsigned long	        irq;  /* bitnr in R_IRQ_MASK2 for dmaX_descr */
+	volatile u8 *port;             /* R_SERIALx_CTRL */
+	u32 irq;                       /* bitnr in R_IRQ_MASK2 for dmaX_descr */
 
-	volatile char *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR, output */
-	volatile unsigned long *ofirstadr;   /* adr to R_DMA_CHx_FIRST, output */
-	volatile char *ocmdadr;     /* adr to R_DMA_CHx_CMD, output */
-	const volatile unsigned short *ostatusadr;  /* adr to R_DMA_CHx_STATUS, output */
-	volatile unsigned long  *ohwswadr;    /* adr to R_DMA_CHx_HWSW, output */
+	volatile u8 *oclrintradr;      /* adr to R_DMA_CHx_CLR_INTR, output */
+	volatile u32 *ofirstadr;       /* adr to R_DMA_CHx_FIRST, output */
+	volatile u8 *ocmdadr;          /* adr to R_DMA_CHx_CMD, output */
+	const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS, output */
+	volatile u32 *ohwswadr;        /* adr to R_DMA_CHx_HWSW, output */
 
-	volatile char *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR, input */
-	volatile unsigned long *ifirstadr;   /* adr to R_DMA_CHx_FIRST, input */
-	volatile char *icmdadr;     /* adr to R_DMA_CHx_CMD, input */
-	const volatile unsigned short *istatusadr;  /* adr to R_DMA_CHx_STATUS, input */
-	volatile unsigned long  *ihwswadr;    /* adr to R_DMA_CHx_HWSW, input */
+	volatile u8 *iclrintradr;      /* adr to R_DMA_CHx_CLR_INTR, input */
+	volatile u32 *ifirstadr;       /* adr to R_DMA_CHx_FIRST, input */
+	volatile u8 *icmdadr;          /* adr to R_DMA_CHx_CMD, input */
+	const volatile u8 *istatusadr; /* adr to R_DMA_CHx_STATUS, input */
+	volatile u32 *ihwswadr;        /* adr to R_DMA_CHx_HWSW, input */
 
 	int			flags; 		/* defined in tty.h */
 
-	unsigned char           rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
-	unsigned char           tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
-	unsigned char           iseteop; /* bit number for R_SET_EOP for the input dma */
+	u8           rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
+	u8           tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
+	u8           iseteop; /* bit number for R_SET_EOP for the input dma */
 /* end of fields defined in rs_table[] in .c-file */
 	unsigned char           fifo_didmagic; /* a fifo eop has been forced */
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/sync_serial.c linux/arch/cris/drivers/sync_serial.c
--- v2.4.4/linux/arch/cris/drivers/sync_serial.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/sync_serial.c	Tue May  1 16:04:56 2001
@@ -2,8 +2,9 @@
  * Simple synchronous serial port driver for ETRAX 100LX.
  *
  * Synchronous serial ports are used for continous streamed data like audio.
- * The deault setting for this driver is compatible with the STA 013 MP3 decoder
- * The driver can easily be tuned to fit other audio encoder/decoders and SPI
+ * The default setting for this driver is compatible with the STA 013 MP3
+ * decoder. The driver can easily be tuned to fit other audio encoder/decoders
+ * and SPI
  *
  * Copyright (c) 2001 Axis Communications AB
  * 
@@ -29,37 +30,43 @@
 #include <asm/sync_serial.h>
 
 /* The receiver is a bit tricky beacuse of the continous stream of data. */
-/*									 */
-/* Two DMA descriptors are linked together. Each DMA descriptor is	 */
-/* responsible for one half of a common buffer.				 */
-/*									 */
-/* ------------------------------					 */
-/* |   ----------   ----------	|					 */
-/* --> | Descr1 |-->| Descr2 |---					 */
-/*     ----------   ----------						 */
-/*	 |	       |						 */
-/*	 v	       v						 */
-/*	 -----------------------------					 */
-/*	 |	      BUFFER	     |					 */
-/*	 -----------------------------					 */
-/*	 |		|						 */
-/*	readp	      writep						 */
-/*									 */
+/*                                                                       */
+/* Two DMA descriptors are linked together. Each DMA descriptor is       */
+/* responsible for one half of a common buffer.                          */
+/*                                                                       */
+/* ------------------------------                                        */
+/* |   ----------   ----------	|                                        */
+/* --> | Descr1 |-->| Descr2 |---                                        */
+/*     ----------   ----------                                           */
+/*         |            |                                                */
+/*         v            v                                                */
+/*   -----------------------------                                       */
+/*   |        BUFFER             |                                       */
+/*   -----------------------------                                       */
+/*      |             |                                                  */
+/*    readp          writep                                              */
+/*                                                                       */
 /* If the application keeps up the pace readp will be right after writep.*/
-/* If the application can't keep the pace we have to throw away data.	 */ 
+/* If the application can't keep the pace we have to throw away data.    */ 
 /* The idea is that readp should be ready with the data pointed out by	 */
 /* Descr1 when the DMA has filled in Descr2. Otherwise we will discard	 */
 /* the rest of the data pointed out by Descr1 and set readp to the start */
-/* of Descr2								 */
+/* of Descr2                                                             */
 
 #define SYNC_SERIAL_MAJOR 125
 
-#define IN_BUFFER_SIZE 8192
+/* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */
+/* words can be handled */
+
+#define IN_BUFFER_SIZE 12288
 #define OUT_BUFFER_SIZE 4096
 
+#define DEFAULT_FRAME_RATE 0
+#define DEFAULT_WORD_RATE 7
+
 #define DEBUG(x) 
 
-/* Define some macros to access Etrax 100 registers */
+/* Define some macros to access ETRAX 100 registers */
 #define SETF(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
 					  IO_FIELD(##reg##, field, val)
 #define SETS(var, reg, field, val) var = (var & ~IO_MASK(##reg##, field)) | \
@@ -81,10 +88,8 @@
 	char data_avail_bit; /* In R_IRQ_MASK1_RD */
 	char transmitter_ready_bit; /* In R_IRQ_MASK1_RD */
 	char ready_irq_bit; /* In R_IRQ_MASK1_SET and R_IRQ_MASK1_CLR */
-	char input_dma_eop_bit;   /* In R_IRQ_MASK2_RD */
 	char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */
 	char output_dma_bit; /* In R_IRQ_MASK2_RD */
-	char eop_bit; /* In R_SET_EOP */
 
 	int enabled;  /* 1 if port is enabled */
 	int use_dma;  /* 1 if port uses dma */
@@ -125,7 +130,6 @@
 static void tr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static void rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static void manual_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static void flush_handler(void);
 
 /* The ports */
 static struct sync_port ports[]=
@@ -133,40 +137,36 @@
 	{
 		R_SYNC_SERIAL1_STATUS,  /* status */
 		R_SYNC_SERIAL1_CTRL,    /* ctrl_data */
-		R_DMA_CH8_FIRST,	    /* output_dma_first */
-		R_DMA_CH8_CMD,	    /* output_dma_cmd */
-		R_DMA_CH8_CLR_INTR,	    /* output_dma_clr_irq */
-		R_DMA_CH9_FIRST,	    /* input_dma_first */
-		R_DMA_CH9_CMD,	    /* input_dma_cmd */
-		R_DMA_CH9_CLR_INTR,	    /* input_dma_clr_irq */
+		R_DMA_CH8_FIRST,        /* output_dma_first */
+		R_DMA_CH8_CMD,          /* output_dma_cmd */
+		R_DMA_CH8_CLR_INTR,     /* output_dma_clr_irq */
+		R_DMA_CH9_FIRST,        /* input_dma_first */
+		R_DMA_CH9_CMD,          /* input_dma_cmd */
+		R_DMA_CH9_CLR_INTR,     /* input_dma_clr_irq */
 		R_SYNC_SERIAL1_TR_DATA, /* data_out */
 		R_SYNC_SERIAL1_REC_DATA,/* data in */
 		IO_BITNR(R_IRQ_MASK1_RD, ser1_data),   /* data_avail_bit */
 		IO_BITNR(R_IRQ_MASK1_RD, ser1_ready),  /* transmitter_ready_bit */
 		IO_BITNR(R_IRQ_MASK1_SET, ser1_ready), /* ready_irq_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma9_eop),	   /* input_dma_eop_bit */
 		IO_BITNR(R_IRQ_MASK2_RD, dma9_descr),  /* input_dma_descr_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma8_eop),	   /* output_dma_bit */
-		IO_BITNR(R_SET_EOP, ch9_eop)	   /* eop_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma8_eop),    /* output_dma_bit */
 	},
 	{
 		R_SYNC_SERIAL3_STATUS,  /* status */
 		R_SYNC_SERIAL3_CTRL,    /* ctrl_data */
-		R_DMA_CH4_FIRST,	    /* output_dma_first */
-		R_DMA_CH4_CMD,	    /* output_dma_cmd */
-		R_DMA_CH4_CLR_INTR,	    /* output_dma_clr_irq */
-		R_DMA_CH5_FIRST,	    /* input_dma_first */
-		R_DMA_CH5_CMD,	    /* input_dma_cmd */
-		R_DMA_CH5_CLR_INTR,	    /* input_dma_clr_irq */
+		R_DMA_CH4_FIRST,        /* output_dma_first */
+		R_DMA_CH4_CMD,          /* output_dma_cmd */
+		R_DMA_CH4_CLR_INTR,     /* output_dma_clr_irq */
+		R_DMA_CH5_FIRST,        /* input_dma_first */
+		R_DMA_CH5_CMD,          /* input_dma_cmd */
+		R_DMA_CH5_CLR_INTR,     /* input_dma_clr_irq */
 		R_SYNC_SERIAL3_TR_DATA, /* data_out */
 		R_SYNC_SERIAL3_REC_DATA,/* data in */
 		IO_BITNR(R_IRQ_MASK1_RD, ser3_data),   /* data_avail_bit */
 		IO_BITNR(R_IRQ_MASK1_RD, ser3_ready),  /* transmitter_ready_bit */
 		IO_BITNR(R_IRQ_MASK1_SET, ser3_ready), /* ready_irq_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma5_eop),	   /* input_dma_eop_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma5_descr),  /* input_dma_eop_bit */
-		IO_BITNR(R_IRQ_MASK2_RD, dma4_eop),	   /* output_dma_bit */
-		IO_BITNR(R_SET_EOP, ch5_eop)	   /* eop_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma5_descr),  /* input_dma_descr_bit */
+		IO_BITNR(R_IRQ_MASK2_RD, dma4_eop),    /* output_dma_bit */
 	}
 };
 
@@ -174,9 +174,6 @@
 static unsigned sync_serial_prescale_shadow = 0;
 static unsigned gen_config_ii_shadow = 0;
 
-/* Timer used to flush data from the DMA */
-static struct timer_list flush_timer;
-
 #define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
 
 static struct file_operations sync_serial_fops = {
@@ -213,24 +210,25 @@
 #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)
 	ports[0].use_dma = 1;
 	initialize_port(0);
-	if(request_irq(24, tr_interrupt, 0, "synchronous serial 1 dma tr", NULL))
+	if(request_irq(24, tr_interrupt, 0, "synchronous serial 1 dma tr", &ports[0]))
 		 panic("Can't allocate sync serial port 1 IRQ");
-	if(request_irq(25, rx_interrupt, 0, "synchronous serial 1 dma rx", NULL))
+	if(request_irq(25, rx_interrupt, 0, "synchronous serial 1 dma rx", &ports[0]))
 		panic("Can't allocate sync serial port 1 IRQ");
 	RESET_DMA(8); WAIT_DMA(8);
 	RESET_DMA(9); WAIT_DMA(9);
-	*R_DMA_CH8_CLR_INTR = 3;  /* Clear IRQ */
-	*R_DMA_CH9_CLR_INTR = 3;  /* Clear IRQ */
+	*R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
+	  IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do); 
+	*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do) |
+	  IO_STATE(R_DMA_CH9_CLR_INTR, clr_descr, do); 
 	*R_IRQ_MASK2_SET =
 	  IO_STATE(R_IRQ_MASK2_SET, dma8_eop, set) |
 	  IO_STATE(R_IRQ_MASK2_SET, dma8_descr, set) |
-          IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) | 
           IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set);
 	start_dma_in(&ports[0]);
 #else
 	ports[0].use_dma = 0;
 	initialize_port(0);
-	if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", NULL))
+	if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", &ports[0]))
 		panic("Can't allocate sync serial manual irq");
 	*R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, ser1_data, set);	 
 #endif
@@ -243,18 +241,19 @@
 #if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)
 	ports[1].use_dma = 1;
 	initialize_port(1);
-	if(request_irq(20, tr_interrupt, 0, "synchronous serial 3 dma tr", NULL))
+	if(request_irq(20, tr_interrupt, 0, "synchronous serial 3 dma tr", &ports[1]))
 		panic("Can't allocate sync serial port 1 IRQ");
-	if(request_irq(21, rx_interrupt, 0, "synchronous serial 3 dma rx", NULL))
+	if(request_irq(21, rx_interrupt, 0, "synchronous serial 3 dma rx", &ports[1]))
 		panic("Can't allocate sync serial port 1 IRQ");
 	RESET_DMA(4); WAIT_DMA(4);
 	RESET_DMA(5); WAIT_DMA(5);
-	*R_DMA_CH4_CLR_INTR = 3;  /* Clear IRQ */
-	*R_DMA_CH5_CLR_INTR = 3;  /* Clear IRQ */
+	*R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
+	  IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do); 
+	*R_DMA_CH5_CLR_INTR = IO_STATE(R_DMA_CH5_CLR_INTR, clr_eop, do) |
+	  IO_STATE(R_DMA_CH5_CLR_INTR, clr_descr, do); 
 	*R_IRQ_MASK2_SET =
 	  IO_STATE(R_IRQ_MASK2_SET, dma4_eop, set) |
 	  IO_STATE(R_IRQ_MASK2_SET, dma4_descr, set) |
-	  IO_STATE(R_IRQ_MASK2_SET, dma5_eop, set) | 
 	  IO_STATE(R_IRQ_MASK2_SET, dma5_descr, set);
 	start_dma_in(&ports[1]);
 #else
@@ -262,7 +261,7 @@
 	initialize_port(1);
 	if (port[0].use_dma) /* Port 0 uses dma, we must manual allocate IRQ */
 	{
-		if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", NULL))
+		if (request_irq(8, manual_interrupt, SA_SHIRQ, "synchronous serial manual irq", &ports[1]))
 			panic("Can't allocate sync serial manual irq");
 	}
 	*R_IRQ_MASK1_SET = IO_STATE(R_IRQ_MASK1_SET, ser3_data, set);	 
@@ -278,22 +277,14 @@
 	  IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec) | 
 	  IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) | 
 	  IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4) | 
-	  IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, 0) | 
-	  IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, 7) | 
+	  IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, DEFAULT_FRAME_RATE) | 
+	  IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE) | 
 	  IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal));
 
 	/* Select synchronous ports */
 	*R_GEN_CONFIG_II = gen_config_ii_shadow;
 
-	/*Initialize DMA flush timer if dma is used */
-	if (ports[0].use_dma || ports[1].use_dma) 
-	{
-		init_timer(&flush_timer);
-		flush_timer.function = flush_handler;
-		mod_timer(&flush_timer, jiffies + 10);
-	}
-
-	printk("Etrax100LX synchronous serial port driver\n");
+	printk("ETRAX 100LX synchronous serial port driver\n");
 	return 0;
 }
 
@@ -321,9 +312,9 @@
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, word)    |
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on)	     |
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, normal)    |
-	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, running)   |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped)   |
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb)	     |
-	  IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, enable)   |
+	  IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable)  |
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit)  |
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8)    |
 	  IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8)     |
@@ -365,27 +356,43 @@
 
 static int sync_serial_release(struct inode *inode, struct file *file)
 {
-	ports[MINOR(inode->i_rdev)].busy = 0;
+	int dev = MINOR(inode->i_rdev);
+	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+	{
+		DEBUG(printk("Invalid minor %d\n", dev));
+		return -ENODEV;
+	}
+	ports[dev].busy = 0;
 	return 0;
 }
 
 static int sync_serial_ioctl(struct inode *inode, struct file *file,
 		  unsigned int cmd, unsigned long arg)
 {
+	int return_val = 0;
 	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
-	sync_port* port = &ports[dev];
+  sync_port* port;
+        
+	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+	{
+		DEBUG(printk("Invalid minor %d\n", dev));
+		return -1;
+	}
+        port = &ports[dev];
 
 	/* Disable port while changing config */
 	if (dev)
 	{
 		RESET_DMA(4); WAIT_DMA(4);
-		*R_DMA_CH4_CLR_INTR = 3;  
+		*R_DMA_CH4_CLR_INTR = IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
+                  IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do); 
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
 	}
 	else
 	{
 		RESET_DMA(8); WAIT_DMA(8);
-		*R_DMA_CH8_CLR_INTR = 3;  
+		*R_DMA_CH8_CLR_INTR = IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
+                  IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);  
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
 	}
 	*R_GEN_CONFIG_II = gen_config_ii_shadow;
@@ -516,7 +523,7 @@
 			}
 			break;
 		default:
-			return -EINVAL;
+			return_val = -1;
 	}
 	/* Set config and enable port */
 	*port->ctrl_data = port->ctrl_data_shadow;
@@ -527,15 +534,23 @@
 		SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
 
 	*R_GEN_CONFIG_II = gen_config_ii_shadow;
-	return 0;
+	return return_val;
 }
 
 static ssize_t sync_serial_manual_write(struct file * file, const char * buf, 
                                         size_t count, loff_t *ppos)
 {
+	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	sync_port* port = &ports[MINOR(file->f_dentry->d_inode->i_rdev)];
+	sync_port* port;
 
+	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+	{
+		DEBUG(printk("Invalid minor %d\n", dev));
+		return -ENODEV;
+	}
+
+	port = &ports[dev];
 	copy_from_user(port->out_buffer, buf, count);
 	port->outp = port->out_buffer;
 	port->out_count = count;
@@ -547,17 +562,36 @@
 	schedule();
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->out_wait_q, &wait);
+	if (signal_pending(current))
+	{
+		return -EINTR;
+	}
 	return count;
 }
 
 static ssize_t sync_serial_write(struct file * file, const char * buf, 
                                  size_t count, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	sync_port *port = &ports[MINOR(file->f_dentry->d_inode->i_rdev)];
+	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);	
+	sync_port *port;
+
+	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+	{
+		DEBUG(printk("Invalid minor %d\n", dev));
+		return -ENODEV;
+	}
+	port = &ports[dev];
 
 	DEBUG(printk("Write dev %d count %d\n", port->port_nbr, count));
 
+	count = count > OUT_BUFFER_SIZE ? OUT_BUFFER_SIZE : count;
+
+	/* Make sure transmitter is running */
+	SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
+	SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, enable);
+	*port->ctrl_data = port->ctrl_data_shadow;
+
 	if (!port->use_dma)
 	{
 		return sync_serial_manual_write(file, buf, count, ppos); 
@@ -570,26 +604,47 @@
 	schedule();
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->out_wait_q, &wait);
+	if (signal_pending(current))
+	{
+		return -EINTR;
+	}
 	return count;
 }
 
 static ssize_t sync_serial_read(struct file * file, char * buf, 
 				size_t count, loff_t *ppos)
 {
+	int dev = MINOR(file->f_dentry->d_inode->i_rdev);
 	int avail;
-	sync_port *port = &ports[MINOR(file->f_dentry->d_inode->i_rdev)];
+	sync_port *port;
 	char* start; 
 	char* end;
 	unsigned long flags;	
 
-	DEBUG(printk("Read dev %d count\n"));
+	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+	{
+		DEBUG(printk("Invalid minor %d\n", dev));
+		return -ENODEV;
+	}
+	port = &ports[dev];
+
+	DEBUG(printk("Read dev %d count %d\n", dev, count));
+
+	/* Make sure receiver is running */
+	SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, running);
+	SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, enable);
+	*port->ctrl_data = port->ctrl_data_shadow;
 
 	/* Calculate number of available bytes */
 	while (port->readp == port->writep) /* No data */
 	{
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
-			interruptible_sleep_on(&port->in_wait_q);
+		interruptible_sleep_on(&port->in_wait_q);
+		if (signal_pending(current))
+		{
+			return -EINTR;
+		}
 	}
 	
 	/* Save pointers to avoid that they are modified by interrupt */
@@ -673,12 +728,12 @@
 		return;
 	}
 	port->in_descr1.hw_len = 0;
-	port->in_descr1.ctrl = d_eop | d_int;
+	port->in_descr1.ctrl = d_int;
 	port->in_descr1.status = 0;
 	port->in_descr1.next = virt_to_phys(&port->in_descr2);
 	port->in_descr2.hw_len = 0;
 	port->in_descr2.next = virt_to_phys(&port->in_descr1);
-	port->in_descr2.ctrl = d_eop | d_int;
+	port->in_descr2.ctrl = d_int;
 	port->in_descr2.status = 0;
 
 	/* Find out which descriptor to start */
@@ -766,22 +821,6 @@
 			start_dma_in(port);
 			wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
 		}
-		else if (ireg & (1 << port->input_dma_eop_bit)) /* EOP interrupt */
-		{
-			/* EOP interrupt means that DMA has not reached end of descriptor */
-			*port->input_dma_clr_irq = 
-			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) | 
-			  IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
-
-			/* Find out the current descriptor */
-			if (port->writep >= port->in_buffer + IN_BUFFER_SIZE/2)
-				port->writep += port->in_descr2.hw_len;
-			else
-				port->writep += port->in_descr1.hw_len;
-
-			start_dma_in(port);
-			wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
-		}
 	}
 }
 
@@ -853,21 +892,6 @@
 			}
 		}
 	}
-}
-
-static void flush_handler(void)
-{
-	int i;
-	
-	for (i = 0; i < NUMBER_OF_PORTS; i++)
-	{
-		if (ports[i].enabled)
-		{
-			*R_SET_EOP = 1 << ports[i].eop_bit;  
-		}
-	}
-	/* restart flush timer */
-	mod_timer(&flush_timer, jiffies + 10);
 }
 
 module_init(etrax_sync_serial_init);
diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/usb-host.c linux/arch/cris/drivers/usb-host.c
--- v2.4.4/linux/arch/cris/drivers/usb-host.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/usb-host.c	Tue May  1 16:04:56 2001
@@ -623,7 +623,7 @@
 
 				traffic_ep->nep = tmp_ep->nep;
 				tmp_ep->nep = virt_to_phys(traffic_ep);
-				dbg_intr("One ep successfully inserted");
+				dbg_intr("One ep sucessfully inserted");
 			}
 			i++;
 		}
@@ -1804,7 +1804,7 @@
 						r_usb_ept_data);
 			
 			if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
-				/* no_error means that this urb was successfully sent or that we have
+				/* no_error means that this urb was sucessfully sent or that we have
 				   some undefinde error*/
 				
 				if (IO_EXTRACT(R_USB_EPT_DATA, error_count_out, r_usb_ept_data) == 3 ||
@@ -1888,9 +1888,9 @@
 						/*
 						  This means that the endpoint has no error, is disabled
 						  and had inserted traffic,
-						  i.e. transfer successfully completed
+						  i.e. transfer sucessfully completed
 						*/
-						dbg_ctrl("Last SB for CTRL %d sent successfully", epid);
+						dbg_ctrl("Last SB for CTRL %d sent sucessfully", epid);
 						handle_control_transfer_attn(epid, 0);
 					}
 				}
@@ -1905,9 +1905,9 @@
 						/*
 						  This means that the endpoint has no error, is disabled
 						  and had inserted traffic,
-						  i.e. transfer successfully completed
+						  i.e. transfer sucessfully completed
 						*/
-						dbg_bulk("Last SB for BULK %d sent successfully", epid);
+						dbg_bulk("Last SB for BULK %d sent sucessfully", epid);
 						handle_bulk_transfer_attn(epid, 0);
 					}
 				}
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/Makefile linux/arch/cris/kernel/Makefile
--- v2.4.4/linux/arch/cris/kernel/Makefile	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/Makefile	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 2001/01/10 21:11:07 bjornw Exp $
+# $Id: Makefile,v 1.4 2001/04/17 13:58:39 orjanf Exp $
 #
 # Makefile for the linux kernel.
 #
@@ -18,7 +18,7 @@
            ptrace.o setup.o time.o sys_cris.o shadows.o \
 	   debugport.o semaphore.o
 
-obj-$(CONFIG_KGDB) += kgdb.o
+obj-$(CONFIG_ETRAX_KGDB) += kgdb.o
 
 clean:
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/debugport.c linux/arch/cris/kernel/debugport.c
--- v2.4.4/linux/arch/cris/kernel/debugport.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/debugport.c	Tue May  1 16:04:56 2001
@@ -12,6 +12,12 @@
  *    init_etrax_debug()
  *
  * $Log: debugport.c,v $
+ * Revision 1.6  2001/04/17 13:58:39  orjanf
+ * * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
+ *
+ * Revision 1.5  2001/03/26 14:22:05  bjornw
+ * Namechange of some config options
+ *
  * Revision 1.4  2000/10/06 12:37:26  bjornw
  * Use physical addresses when talking to DMA
  *
@@ -29,7 +35,7 @@
 
 /* Which serial-port is our debug port ? */
 
-#if defined(CONFIG_DEBUG_PORT0) || defined(CONFIG_DEBUG_PORT_NULL)
+#if defined(CONFIG_ETRAX_DEBUG_PORT0) || defined(CONFIG_ETRAX_DEBUG_PORT_NULL)
 #define DEBUG_PORT_IDX 0
 #define DEBUG_OCMD R_DMA_CH6_CMD
 #define DEBUG_FIRST R_DMA_CH6_FIRST
@@ -43,7 +49,7 @@
 #define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma6_descr, clr)
 #endif
 
-#ifdef CONFIG_DEBUG_PORT1
+#ifdef CONFIG_ETRAX_DEBUG_PORT1
 #define DEBUG_PORT_IDX 1
 #define DEBUG_OCMD R_DMA_CH8_CMD
 #define DEBUG_FIRST R_DMA_CH8_FIRST
@@ -57,7 +63,7 @@
 #define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma8_descr, clr)
 #endif
 
-#ifdef CONFIG_DEBUG_PORT2
+#ifdef CONFIG_ETRAX_DEBUG_PORT2
 #define DEBUG_PORT_IDX 2
 #define DEBUG_OCMD R_DMA_CH2_CMD
 #define DEBUG_FIRST R_DMA_CH2_FIRST
@@ -71,7 +77,7 @@
 #define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma2_descr, clr)
 #endif
 
-#ifdef CONFIG_DEBUG_PORT3
+#ifdef CONFIG_ETRAX_DEBUG_PORT3
 #define DEBUG_PORT_IDX 3
 #define DEBUG_OCMD R_DMA_CH4_CMD
 #define DEBUG_FIRST R_DMA_CH4_FIRST
@@ -97,7 +103,7 @@
 	unsigned long flags; 
 	int in_progress;
 	
-#ifdef CONFIG_DEBUG_PORT_NULL
+#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
         /* no debug printout at all */
         return;
 #endif
@@ -111,7 +117,7 @@
 	save_flags(flags);
 	cli();
 
-#ifdef CONFIG_KGDB
+#ifdef CONFIG_ETRAX_KGDB
 	/* kgdb needs to output debug info using the gdb protocol */
 	putDebugString(buf, len);
 	restore_flags(flags);
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/entry.S linux/arch/cris/kernel/entry.S
--- v2.4.4/linux/arch/cris/kernel/entry.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/entry.S	Sun May 20 12:11:38 2001
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.15 2001/03/05 13:14:30 bjornw Exp $
+/* $Id: entry.S,v 1.22 2001/04/17 13:58:39 orjanf Exp $
  *
  *  linux/arch/cris/entry.S
  *
@@ -7,6 +7,40 @@
  *  Authors:	Bjorn Wesen (bjornw@axis.com)
  *
  *  $Log: entry.S,v $
+ *  Revision 1.22  2001/04/17 13:58:39  orjanf
+ *  * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
+ *
+ *  Revision 1.21  2001/04/17 11:33:29  orjanf
+ *  Updated according to review:
+ *  * Included asm/sv_addr_ag.h to get macro for internal register.
+ *  * Corrected comment regarding system call argument passing.
+ *  * Removed comment about instruction being in a delay slot.
+ *  * Added comment about SYMBOL_NAME macro.
+ *
+ *  Revision 1.20  2001/04/12 08:51:07  hp
+ *  - Add entry for sys_fcntl64.  In fact copy last piece from i386 including ...
+ *  - .rept to fill table to safe state with sys_ni_syscall.
+ *
+ *  Revision 1.19  2001/04/04 09:43:32  orjanf
+ *  * Moved do_sigtrap from traps.c to entry.S.
+ *  * LTASK_PID need not be global anymore.
+ *
+ *  Revision 1.18  2001/03/26 09:25:02  markusl
+ *  Updated after review, should now handle USB interrupts correctly.
+ *
+ *  Revision 1.17  2001/03/21 16:12:55  bjornw
+ *  * Always make room for the cpu status record in the frame, in order to
+ *    use the same framelength and layout for both mmu busfaults and normal
+ *    irqs. No need to check for the explicit CRIS_FRAME_FIXUP type anymore.
+ *  * Fixed bug with using addq for popping the stack in the epilogue - it
+ *    destroyed the flag register. Use instructions that don't affect the
+ *    flag register instead.
+ *  * Removed write to R_PORT_PA_DATA during spurious_interrupt
+ *
+ *  Revision 1.16  2001/03/20 19:43:02  bjornw
+ *  * Get rid of esp0 setting
+ *  * Give a 7th argument to a systemcall - the stackframe
+ *
  *  Revision 1.15  2001/03/05 13:14:30  bjornw
  *  Spelling fix
  *
@@ -78,9 +112,11 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/sys.h>
-			
+#include <asm/sv_addr_ag.h>
+	
 	;; functions exported from this file
 	
 	.globl _system_call
@@ -95,10 +131,11 @@
 	.globl _spurious_interrupt
 	.globl _hw_bp_trigs
 	.globl _mmu_bus_fault
-				
+	.globl _do_sigtrap
+	.globl _gdb_handle_breakpoint
+			
 	.globl _sys_call_table
 	
-	.globl LTASK_PID	
 	;; syscall error codes
 	
 LENOSYS = 38
@@ -115,11 +152,6 @@
 
 PT_TRACESYS_BIT	  = 1
 
-	;; Offset for esp0 into task_struct: current->thread.esp0.
-	;; FIXME: In need of padding somewhere, to get dword-alignment.
-
-THREAD_ESP0	  = 597
-	
 	;; some pt_regs offsets (from ptrace.h)
 	
 LORIG_R10	= 4
@@ -182,7 +214,7 @@
 	;; Since we can't have system calls inside interrupts, it should not matter
 	;; that we don't stack IRP.
 	;; 
-	;; In r1 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,r0
+	;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,mof,srp
 	;;
 	;; This function looks on the _surface_ like spaghetti programming, but it's
 	;; really designed so that the fast-path does not force cache-loading of non-used
@@ -190,7 +222,7 @@
 
 _system_call:
 	;; stack-frame similar to the irq heads, which is reversed in ret_from_sys_call
-	push	brp		; this is normally push irp
+	move	brp,[sp=sp-16]	; instruction pointer and room for a fake SBFS frame
 	push	srp
 	push	dccr
 	push	mof
@@ -202,15 +234,11 @@
 	movs.w	-LENOSYS,r0
 	move.d	r0,[sp+LR10]	; put the default return value in r10 in the frame
 
-	;; Perform "current->thread.esp0 = sp".
-	;; This used to be a separate function; set_esp0(ssp).
-	movs.w -8192,r0		; THREAD_SIZE == 8192
-	and.d sp,r0
-
-	move.d sp,[r0+THREAD_ESP0]
-
 	;; check if this process is syscall-traced
 
+	movs.w	-8192,r0	; THREAD_SIZE == 8192
+	and.d	sp,r0
+	
 	move.d	[r0+LTASK_PTRACE],r0
 	btstq	PT_TRACESYS_BIT, r0
 	bmi	tracesys
@@ -222,6 +250,11 @@
 	bcc	_ret_from_sys_call
 	lslq	2,r9		;  multiply by 4, in the delay slot
 
+	;; as a bonus 7th parameter, we give the location on the stack
+	;; of the register structure itself. some syscalls need this.
+
+	push	sp
+	
 	;; the parameter carrying registers r10, r11, r12 and 13 are intact.
 	;; the fifth and sixth parameters (if any) was in mof and srp 
 	;; respectively, and we need to put them on the stack.
@@ -230,8 +263,8 @@
 	push	mof
 	
 	jsr	[r9+_sys_call_table]	; actually do the system call
-	addq	2*4,sp		; pop the mof and srp parameters
-	move.d	r10,[sp+LR10]	; save the return value
+	addq	3*4,sp			; pop the mof, srp and regs parameters
+	move.d	r10,[sp+LR10]		; save the return value
 
 	moveq	1,r9		; "parameter" to ret_from_sys_call to show it was a sys call
 	
@@ -274,31 +307,20 @@
 	pop	mof		; multiply overflow register 
 	pop	dccr		; condition codes
 	pop	srp		; subroutine return pointer
-	jmpu	[sp+]		; return by popping irp and jumping there
-	;; jmpu takes the U-flag into account to see if we return to
-	;; user-mode or kernel mode.
+	;; now we have a 4-word SBFS frame which we do not want to restore
+	;; using RBF since it was not stacked with SBFS. instead we would like to
+	;; just get the PC value to restart it with, and skip the rest of
+	;; the frame.
+	move	[sp=sp+16], p8	; pop the SBFS frame from the sp
+	jmpu	[sp-16]		; return through the irp field in the sbfs frame
 
 RBFexit:
-	cmpq	2, r10		; was it CRIS_FRAME_FIXUP ?
-	beq	2f
 	movem	[sp+],r13	; registers r0-r13, in delay slot
 	pop	mof		; multiply overflow register 
 	pop	dccr		; condition codes
 	pop	srp		; subroutine return pointer
 	rbf	[sp+]		; return by popping the CPU status
 
-2:	pop	mof		; multiply overflow register
-	pop	dccr		; condition codes
-	pop	srp		; subroutine return pointer
-	;; now we have a 4-word SBFS frame which we do not want to restore
-	;; using RBF since we have made a fixup. instead we would like to
-	;; just get the PC value to restart it with, and skip the rest of
-	;; the frame.
-	pop	irp		; fixup location will be here
-	reti			; return to IRP, taking U-flag into account
-	addq	12,sp		; Skip rest of SBFS frame.
-
-
 tracesys:
 	;; this first invocation of syscall_trace _requires_ that
 	;; LR10 in the frame contains -LENOSYS (as is set in the beginning
@@ -332,13 +354,19 @@
 	move	[sp+LMOF],      mof
 	move	[sp+LSRP],      srp
 
+	;; as a bonus 7th parameter, we give the location on the stack
+	;; of the register structure itself. some syscalls need this.
+
+	push	sp
+	
 	;; the fifth and sixth parameters needs to be put on the stack for
 	;; the system call to find them
 
 	push	srp
 	push	mof
+
 	jsr	r9		; actually call the system-call
-	addq	2*4,sp		; pop the r0 parameter
+	addq	3*4,sp		; pop the srp, mof and regs parameters
 
 1:	move.d	r10,[sp+LR10]	; save the return value
 
@@ -354,8 +382,7 @@
 	
 LTHREAD_KSP	= 0
 LTHREAD_USP	= 4
-LTHREAD_ESP0	= 8
-LTHREAD_DCCR	= 12
+LTHREAD_DCCR	= 8
 	
 	;; _resume performs the actual task-switching, by switching stack pointers
 	;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct
@@ -468,8 +495,6 @@
 _IRQ1_interrupt:
 _spurious_interrupt:	
 	di
-	move.b	4,r0
-	move.b	r0,[0xb0000030]
 basse2:	ba	basse2
 	nop
 
@@ -479,7 +504,7 @@
 	
 _multiple_interrupt:
 	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
-	push	irp
+	move	irp,[sp=sp-16]	; instruction pointer and room for a fake SBFS frame
 	push	srp
 	push	dccr
 	push	mof
@@ -491,15 +516,15 @@
 	
 	move.d	_irq_shortcuts + 8,r1
 	moveq	2,r2		; first bit we care about is the timer0 irq
-	move.d	[0xb00000d8],r0	; read the irq bits that triggered the multiple irq
+	move.d	[R_VECT_MASK_RD],r0	; read the irq bits that triggered the multiple irq
 multloop:	
 	btst	r2,r0		; check for the irq given by bit r2
 	bmi	do_shortcut	; actually do the shortcut
 	nop
-	addq	1,r2		; next vector bit - remember this is in the delay slot!
+	addq	1,r2		; next vector bit
 	addq	4,r1		; next vector
-	cmpq	26,r2
-	bne	multloop	; process all irq's up to and including number 25
+	cmp.b	32,r2
+	bne	multloop	; process all irq's up to and including number 31
 	nop
 	
 	;; strange, we didn't get any set vector bits.. oh well, just return
@@ -513,6 +538,48 @@
 	nop
 	jump	[r1]		; jump to the irq handlers shortcut
 
+_do_sigtrap:
+	;; 
+	;; SIGTRAP the process that executed the break instruction.
+	;; Make a frame that Rexit in entry.S expects.
+	;;
+	move	brp,[sp=sp-16]		; Push BRP while faking a cpu status record.
+	push	srp			; Push subroutine return pointer.
+	push	dccr			; Push condition codes.
+	push	mof			; Push multiply overflow reg.
+	di				; Need to disable irq's at this point.
+	subq	14*4,sp			; Make room for r0-r13.
+	movem	r13,[sp]		; Push the r0-r13 registers.
+	push	r10			; Push orig_r10.
+	clear.d	[sp=sp-4]		; Frametype - this is a normal stackframe.
+
+	movs.w	-8192,r9		; THREAD_SIZE == 8192
+	and.d	sp,r9
+	move.d	[r9+LTASK_PID],r10	; current->pid as arg1.
+	moveq	5,r11			; SIGTRAP as arg2.
+	jsr	_sys_kill       
+	jump	_ret_from_intr		; Use the return routine for interrupts.
+
+_gdb_handle_breakpoint:	
+	push	dccr
+	push	r0
+#ifdef CONFIG_ETRAX_KGDB
+	move	dccr,r0			; U-flag not affected by previous insns. 
+	btstq	8,r0			; Test the U-flag.
+	bmi	_ugdb_handle_breakpoint	; Go to user mode debugging. 
+	nop				; Empty delay slot (cannot pop r0 here). 
+	pop	r0			; Restore r0.
+	ba	_kgdb_handle_breakpoint	; Go to kernel debugging. 
+	pop	dccr			; Restore dccr in delay slot.
+#endif
+	
+_ugdb_handle_breakpoint:	
+	move	brp,r0			; Use r0 temporarily for calculation.
+	subq	2,r0			; Set to address of previous instruction.
+	move	r0,brp
+	pop	r0			; Restore r0. 
+	ba	_do_sigtrap		; SIGTRAP the offending process. 
+	pop	dccr			; Restore dccr in delay slot.
 	
 	.data
 
@@ -521,8 +588,11 @@
 _hw_bp_trig_ptr:
 	.dword _hw_bp_trigs
 
-/* linux/linkage.h got it wrong for this compiler currently */
-	
+/* Because we compile this file with -traditional, we need to redefine
+   token-concatenation to the traditional trick, using an empty comment.
+   Normally (in other files, with ISO C as in gcc default) this is done
+   with the ## preprocessor operator.  */
+
 #undef SYMBOL_NAME
 #define SYMBOL_NAME(X) _/**/X
 		
@@ -748,6 +818,8 @@
 	.long SYMBOL_NAME(sys_mincore)
 	.long SYMBOL_NAME(sys_madvise)
 	.long SYMBOL_NAME(sys_getdents64)       /* 220 */
+	.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
@@ -756,9 +828,7 @@
          * been shrunk every time we add a new system call.
          */
 
-	;; TODO: this needs to actually generate sys_ni_syscall entires
-	;; since we now have removed the check for NULL entries in this
-	;; table in system_call!
-	
-	.space (NR_syscalls-220)*4
+	.rept NR_syscalls-221
+		.long SYMBOL_NAME(sys_ni_syscall)
+	.endr
 	
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/head.S linux/arch/cris/kernel/head.S
--- v2.4.4/linux/arch/cris/kernel/head.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/head.S	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.20 2001/02/23 12:47:56 bjornw Exp $
+/* $Id: head.S,v 1.29 2001/04/18 12:51:59 orjanf Exp $
  * 
  * Head of the kernel - alter with care
  *
@@ -7,6 +7,40 @@
  * Authors:	Bjorn Wesen (bjornw@axis.com)
  * 
  * $Log: head.S,v $
+ * Revision 1.29  2001/04/18 12:51:59  orjanf
+ * * Reverted review change regarding the use of bcs/bcc.
+ * * Removed non-working LED-clearing code.
+ *
+ * Revision 1.28  2001/04/17 13:58:39  orjanf
+ * * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
+ *
+ * Revision 1.27  2001/04/17 11:42:35  orjanf
+ * Changed according to review:
+ * * Added comment explaining memory map bug.
+ * * Changed bcs and bcc to blo and bhs, respectively.
+ * * Removed mentioning of Stallone and Olga boards.
+ *
+ * Revision 1.26  2001/04/06 12:31:07  jonashg
+ * Check for cramfs in flash before RAM instead of RAM before flash.
+ *
+ * Revision 1.25  2001/04/04 06:23:53  starvik
+ * Initialize DRAM if not already initialized
+ *
+ * Revision 1.24  2001/04/03 11:12:00  starvik
+ * Removed dram init (done by rescue or etrax100boot
+ * Corrected include
+ *
+ * Revision 1.23  2001/04/03 09:53:03  starvik
+ * Include hw_settings.S
+ *
+ * Revision 1.22  2001/03/26 14:23:26  bjornw
+ * Namechange of some config options
+ *
+ * Revision 1.21  2001/03/08 12:14:41  bjornw
+ * * Config name for ETRAX IDE was renamed
+ * * Removed G27 auto-setting when JULIETTE is chosen (need to make this
+ *   a new config option later)
+ *
  * Revision 1.20  2001/02/23 12:47:56  bjornw
  * MMU regs during LOW_MAP updated to reflect a newer reality
  *
@@ -76,7 +110,8 @@
 #include <asm/sv_addr_ag.h>
 
 #define CRAMFS_MAGIC 0x28cd3d45
-	
+#define RAM_INIT_MAGIC 0x56902387
+		
 	;; exported symbols
 		
 	.globl	_etrax_irv
@@ -92,9 +127,9 @@
 	;; since etrax actually starts at address 2 when booting from flash, we
 	;; put a nop (2 bytes) here first so we dont accidentally skip the di
 	;;
-	;; NOTICE! The register r9 is used as a parameter carrying register from
-	;; the decompressor (if the kernel was compressed). It should not be
-	;; used in the code below until it is read.
+	;; NOTICE! The registers r8 and r9 are used as a parameter carrying
+	;; information from the decompressor (if the kernel was compressed). 
+	;; They should not be used in the code below until it is read.
 	
 	nop	
 	di
@@ -109,6 +144,7 @@
 	;;
 	;; Due to a bug in Etrax-100 LX version 1 we need to map the memory
 	;; slightly different. We also let the simulator get this mapping for now.
+	;; (The bug is that you can't remap bit 31.)
 
 #ifdef CONFIG_CRIS_LOW_MAP
 	move.d	0x0004b098, r0	; kseg mappings, temporary map of 0xc0->0x40
@@ -161,8 +197,14 @@
 	
 inflash:
 	;; We need to initialze DRAM registers before we start using the DRAM
-#include "../lib/dram_init.S"	
 
+	cmp.d	RAM_INIT_MAGIC, r8	; Already initialized?
+	beq	dram_init_finished
+	nop
+	
+#include "../lib/dram_init.S"
+
+dram_init_finished:		
 	;; Copy text+data to DRAM
 	;; This is fragile - the calculation of r4 as the image size depends
 	;; on that the labels below actually are the first and last positions
@@ -218,7 +260,39 @@
 	moveq	0, r0
 	move.d	r0, [_romfs_length] ; default if there is no cramfs
 	
-	;; First check if there is a cramfs (magic value)
+	;; The kernel could have been unpacked to DRAM by the loader, but
+	;; the cramfs image could still be in the Flash directly after the
+	;; compressed kernel image. The loader passes the address of the
+	;; byte succeeding the last compressed byte in the flash in the
+	;; register r9 when starting the kernel. Check if r9 points to a
+	;; decent cramfs image!
+	;; (Notice that if this is not booted from the loader, r9 will be
+	;;  garbage but we do sanity checks on it, the chance that it points
+	;;  to a cramfs magic is small.. )
+	
+	cmp.d	0x0ffffff8, r9
+	bcc	no_romfs_in_flash	; r9 points outside the flash area
+	nop
+	move.d	[r9], r0	; cramfs_super.magic
+	cmp.d	CRAMFS_MAGIC, r0
+	bne	no_romfs_in_flash
+	nop
+	move.d	[r9+4], r0	; cramfs_super.length
+	move.d	r0, [_romfs_length]
+#ifdef CONFIG_CRIS_LOW_MAP
+	add.d   0x50000000, r9	; add flash start in virtual memory (cached)
+#else
+	add.d   0xf0000000, r9	; add flash start in virtual memory (cached)
+#endif
+	move.d	r9, [_romfs_start]
+
+	moveq	1, r0
+	move.d	r0, [_romfs_in_flash]
+	
+	jump	start_it	; enter code, cached this time
+
+no_romfs_in_flash:
+	;; Check if there is a cramfs (magic value).
 	;; Notice that we check for cramfs magic value - which is
 	;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does
 	;; not need this mechanism anyway)
@@ -226,7 +300,7 @@
 	move.d	__vmlinux_end, r0 ; the image will be after the vmlinux end address
 	move.d	[r0], r1	; cramfs assumes same endian on host/target
 	cmp.d	CRAMFS_MAGIC, r1; magic value in cramfs superblock
-	bne	no_romfs_in_ram
+	bne	1f
 	nop
 
 	;; Ok. What is its size ? 
@@ -263,40 +337,6 @@
 	move.d	r0, [_romfs_in_flash]
 
 	jump	start_it	; better skip the additional cramfs check below
-			
-no_romfs_in_ram:
-
-	;; We have still one other possibility at this point - the kernel
-	;; could have been unpacked to DRAM by the loader, but the cramfs
-	;; image was still in the Flash directly after the compressed kernel
-	;; image. The loader passes the address of the byte succeeding the
-	;; last compressed byte in the flash in the register r9 when starting
-	;; the kernel. Check if r9 points to a decent cramfs image!
-	;; (Notice that if this is not booted from the loader, r9 will be
-	;;  garbage but we do sanity checks on it, the chance that it points
-	;;  to a cramfs magic is small.. )
-	
-	cmp.d	0x0ffffff8, r9
-	bcc	1f		; r9 points outside the flash area
-	nop
-	move.d	[r9], r0	; cramfs_super.magic
-	cmp.d	CRAMFS_MAGIC, r0
-	bne	1f
-	nop
-	move.d	[r9+4], r0	; cramfs_super.length
-	move.d	r0, [_romfs_length]
-#ifdef CONFIG_CRIS_LOW_MAP
-	add.d   0x50000000, r9	; add flash start in virtual memory (cached)
-#else
-	add.d   0xf0000000, r9	; add flash start in virtual memory (cached)
-#endif
-	move.d	r9, [_romfs_start]
-
-	moveq	1, r0
-	move.d	r0, [_romfs_in_flash]
-1:	
-	
-	jump	start_it	; enter code, cached this time
 	
 start_it:
 	;; the kernel stack is overlayed with the task structure for each
@@ -368,10 +408,10 @@
 	;; Etrax product HW genconfig setup
 
 	moveq	0,r0
-#if !defined(CONFIG_KGDB) && !defined(CONFIG_DMA_MEMCPY)
+#if !defined(CONFIG_ETRAX_KGDB) && !defined(CONFIG_DMA_MEMCPY)
 	or.d	0x140000,r0	; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
 #endif
-#if !defined(CONFIG_KGDB) || !defined(CONFIG_DEBUG_PORT1)	
+#if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT1)	
 	or.d	0xc00000,r0	; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
 #endif	
 #ifdef CONFIG_DMA_MEMCPY
@@ -389,7 +429,7 @@
 #if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
 	or.w	0x80,r0	; parport 1 enabled using DMA 4/5
 #endif
-#ifdef CONFIG_BLK_DEV_ETRAXIDE
+#ifdef CONFIG_ETRAX_IDE
 	or.d	0x3c02,r0	; DMA channels 2 and 3 to ATA, ATA enabled
 #endif
 	
@@ -405,9 +445,6 @@
 	
 #ifdef CONFIG_JULIETTE
 	or.d	0x3c000,r0	; DMA channels 4 and 5 to EXTDMA0, for Juliette
-#ifndef CONFIG_BLK_DEV_ETRAXIDE
-	or.d	0x41,r0		; HACK for now! To make G27 connected for the RTC
-#endif
 #endif
 	move.d	r0,[_genconfig_shadow] ; init a shadow register of R_GEN_CONFIG
 
@@ -447,20 +484,20 @@
 	;; setup port PA and PB default initial directions and data
 	;; including their shadow registers
 		
-	move.b	DEF_R_PORT_PA_DIR,r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DIR,r0
 	move.b	r0,[_port_pa_dir_shadow]
 	move.b	r0,[R_PORT_PA_DIR]
-	move.b	DEF_R_PORT_PA_DATA,r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PA_DATA,r0
 	move.b	r0,[_port_pa_data_shadow]
 	move.b	r0,[R_PORT_PA_DATA]
 	
-	move.b	DEF_R_PORT_PB_CONFIG,r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG,r0
 	move.b	r0,[_port_pb_config_shadow]
 	move.b	r0,[R_PORT_PB_CONFIG]
-	move.b	DEF_R_PORT_PB_DIR,r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DIR,r0
 	move.b	r0,[_port_pb_dir_shadow]
 	move.b	r0,[R_PORT_PB_DIR]
-	move.b	DEF_R_PORT_PB_DATA,r0
+	move.b	CONFIG_ETRAX_DEF_R_PORT_PB_DATA,r0
 	move.b	r0,[_port_pb_data_shadow]
 	move.b	r0,[R_PORT_PB_DATA]
 	move.d  0, r0
@@ -499,12 +536,6 @@
 	move.b	0x40,r0			; tr enable
 	move.b	r0,[R_SERIAL1_TR_CTRL]
 
-#ifdef CONFIG_ETRAX_90000000_LEDS
-	;; clear LED's on Stallone and Olga boards
-	moveq	-1,r0
-	move.d	r0,[_port_90000000_shadow]
-	move.d	r0,[0x90000000]
-#endif
 	
 #ifdef CONFIG_ETRAX_SERIAL_PORT3	
 	;; setup the serial port 3 at 115200 baud for debug purposes
@@ -544,3 +575,5 @@
 #else	
 _swapper_pg_dir = 0xc0002000
 #endif
+	
+#include "../lib/hw_settings.S"
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/irq.c linux/arch/cris/kernel/irq.c
--- v2.4.4/linux/arch/cris/kernel/irq.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/irq.c	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.11 2001/02/27 13:52:52 bjornw Exp $
+/* $Id: irq.c,v 1.14 2001/04/17 13:58:39 orjanf Exp $
  *
  *	linux/arch/cris/kernel/irq.c
  *
@@ -160,7 +160,7 @@
 BUILD_IRQ(23, 0x800000)
 BUILD_IRQ(24, 0x1000000)
 BUILD_IRQ(25, 0x2000000)
-/* IRQ 26-30 are resereved */	
+/* IRQ 26-30 are reserved */
 BUILD_IRQ(31, 0x80000000)
  
 /*
@@ -261,11 +261,11 @@
         irq_enter(cpu);
 	kstat.irqs[cpu][irq]++;
 
-	action = *(irq + irq_action);
+	action = irq_action[irq];
         if (action) {
                 if (!(action->flags & SA_INTERRUPT))
                         __sti();
-                action = *(irq + irq_action);
+                action = irq_action[irq];
                 do_random = 0;
                 do {
                         do_random |= action->flags;
@@ -396,7 +396,7 @@
 		save_flags(flags);
 		cli();
 		*p = action->next;
-		if (!irq[irq_action]) {
+		if (!irq_action[irq]) {
 			mask_irq(irq);
 			set_int_vector(irq, bad_interrupt[irq], 0);
 		}
@@ -419,8 +419,8 @@
 */
 
 void system_call(void);  /* from entry.S */
-void gdb_handle_breakpoint(void); /* from traps.c */
-void do_sigtrap(void); /* also from traps.c */
+void do_sigtrap(void); /* from entry.S */
+void gdb_handle_breakpoint(void); /* from entry.S */
 
 void init_IRQ(void)
 {
@@ -475,10 +475,10 @@
 
         /* setup a breakpoint handler for debugging used for both user and
            kernel mode debugging  (which is why it is not inside an ifdef
-           CONFIG_KGDB) */
+           CONFIG_ETRAX_KGDB) */
         set_break_vector(8, gdb_handle_breakpoint);
 
-#ifdef CONFIG_KGDB
+#ifdef CONFIG_ETRAX_KGDB
 	/* setup kgdb if its enabled, and break into the debugger */
 	kgdb_init();
 	breakpoint();
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/kgdb.c linux/arch/cris/kernel/kgdb.c
--- v2.4.4/linux/arch/cris/kernel/kgdb.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/kgdb.c	Tue May  1 16:04:56 2001
@@ -18,6 +18,9 @@
 *! Jul 21 1999  Bjorn Wesen     eLinux port
 *!
 *! $Log: kgdb.c,v $
+*! Revision 1.5  2001/04/17 13:58:39  orjanf
+*! * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
+*!
 *! Revision 1.4  2001/02/23 13:45:19  bjornw
 *! config.h check
 *!
@@ -49,7 +52,7 @@
 *!
 *!---------------------------------------------------------------------------
 *!
-*! $Id: kgdb.c,v 1.4 2001/02/23 13:45:19 bjornw Exp $
+*! $Id: kgdb.c,v 1.5 2001/04/17 13:58:39 orjanf Exp $
 *!
 *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
 *!
@@ -60,8 +63,8 @@
  *  kgdb usage notes:
  *  -----------------
  *
- * If you select CONFIG_KGDB in the configuration, the kernel will be built
- * with different gcc flags: "-g" is added to get debug infos, and
+ * If you select CONFIG_ETRAX_KGDB in the configuration, the kernel will be 
+ * built with different gcc flags: "-g" is added to get debug infos, and
  * "-fomit-frame-pointer" is omitted to make debugging easier. Since the
  * resulting kernel will be quite big (approx. > 7 MB), it will be stripped
  * before compresion. Such a kernel will behave just as usually, except if
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/process.c linux/arch/cris/kernel/process.c
--- v2.4.4/linux/arch/cris/kernel/process.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/process.c	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.12 2001/02/27 13:52:52 bjornw Exp $
+/* $Id: process.c,v 1.13 2001/03/20 19:44:06 bjornw Exp $
  * 
  *  linux/arch/cris/kernel/process.c
  *
@@ -7,6 +7,10 @@
  *
  *  Authors:   Bjorn Wesen (bjornw@axis.com)
  *
+ *  $Log: process.c,v $
+ *  Revision 1.13  2001/03/20 19:44:06  bjornw
+ *  Use the 7th syscall argument for regs instead of current_regs
+ *
  */
 
 /*
@@ -33,6 +37,8 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/processor.h>
+
 #include <linux/smp.h>
 
 //#define DEBUG
@@ -64,13 +70,6 @@
 
 static int hlt_counter=0;
 
-/* in a system call, set_esp0 is called to remember the stack frame, therefore
-   in the implementation of syscalls we can use that value to access the stack
-   frame and saved registers.
-*/
-
-#define currentregs ((struct pt_regs *)current->thread.esp0)
-
 void disable_hlt(void)
 {
 	hlt_counter++;
@@ -178,7 +177,7 @@
 	 * remember that the task_struct doubles as the kernel stack for the task
 	 */
 
-	childregs = ((struct pt_regs *) ((unsigned long)p + THREAD_SIZE)) - 1;
+	childregs = user_regs(p);
 
 	*childregs = *regs;  /* struct copy of pt_regs */
 
@@ -202,14 +201,11 @@
 
 	p->thread.ksp = (unsigned long) swstack;
 
-	/* esp0 keeps the pt_regs stacked structure pointer */
-
-	p->thread.esp0 = (unsigned long) childregs;
-
 #ifdef DEBUG
-	printk("kern_stack_page 0x%x, used stack %d, thread.usp 0x%x, usp 0x%x\n", 
-	       current->kernel_stack_page, usedstack, p->thread.usp, usp);
+	printk("copy_thread: new regs at 0x%p, as shown below:\n", childregs);
+	show_registers(childregs);
 #endif
+
 	return 0;
 }
 
@@ -240,33 +236,53 @@
 #endif 
 }
 
-asmlinkage int sys_fork(void)
+/* 
+ * Be aware of the "magic" 7th argument in the four system-calls below.
+ * They need the latest stackframe, which is put as the 7th argument by
+ * entry.S. The previous arguments are dummies or actually used, but need
+ * to be defined to reach the 7th argument.
+ *
+ * N.B.: Another method to get the stackframe is to use current_regs(). But
+ * it returns the latest stack-frame stacked when going from _user mode_ and
+ * some of these (at least sys_clone) are called from kernel-mode sometimes
+ * (for example during kernel_thread, above) and thus cannot use it. Thus,
+ * to be sure not to get any surprises, we use the method for the other calls
+ * as well.
+ */
+
+asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
+			struct pt_regs *regs)
 {
-	return do_fork(SIGCHLD, rdusp(), currentregs, 0);
+	return do_fork(SIGCHLD, rdusp(), regs, 0);
 }
 
 /* if newusp is 0, we just grab the old usp */
 
-asmlinkage int sys_clone(unsigned long newusp, unsigned long flags)
+asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
+			 long r12, long r13, long mof, long srp,
+			 struct pt_regs *regs)
 {
 	if (!newusp)
 		newusp = rdusp();
-	return do_fork(flags, newusp, currentregs, 0);
+	return do_fork(flags, newusp, regs, 0);
 }
 
 /* vfork is a system call in i386 because of register-pressure - maybe
  * we can remove it and handle it in libc but we put it here until then.
  */
 
-asmlinkage int sys_vfork(void)
+asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
+			 struct pt_regs *regs)
 {
-        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), currentregs, 0);
+        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
 }
 
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(const char *fname, char **argv, char **envp)
+asmlinkage int sys_execve(const char *fname, char **argv, char **envp,
+			  long r13, long mof, long srp, 
+			  struct pt_regs *regs)
 {
 	int error;
 	char *filename;
@@ -276,7 +292,7 @@
 
 	if (IS_ERR(filename))
 	        goto out;
-	error = do_execve(filename, argv, envp, currentregs);
+	error = do_execve(filename, argv, envp, regs);
 	putname(filename);
  out:
 	return error;
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/ptrace.c linux/arch/cris/kernel/ptrace.c
--- v2.4.4/linux/arch/cris/kernel/ptrace.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/ptrace.c	Tue May  1 16:04:56 2001
@@ -3,11 +3,18 @@
  *
  * Parts taken from the m68k port.
  * 
- * Copyright (c) 2000 Axis Communications AB
+ * Copyright (c) 2000, 2001 Axis Communications AB
  *
  * Authors:   Bjorn Wesen
  *
  * $Log: ptrace.c,v $
+ * Revision 1.5  2001/03/26 14:24:28  orjanf
+ * * Changed loop condition.
+ * * Added comment documenting non-standard ptrace behaviour.
+ *
+ * Revision 1.4  2001/03/20 19:44:41  bjornw
+ * Use the user_regs macro instead of thread.esp0
+ *
  * Revision 1.3  2000/12/18 23:45:25  bjornw
  * Linux/CRIS first version
  *
@@ -49,8 +56,8 @@
 
 	if (regno == PT_USP)
 		return task->thread.usp;
-	else if (regno <= PT_MAX)
-		return ((unsigned long *)(task->thread.esp0))[regno];
+	else if (regno < PT_MAX)
+		return ((unsigned long *)user_regs(task))[regno];
 	else
 		return 0;
 }
@@ -65,12 +72,20 @@
 
 	if (regno == PT_USP)
 		task->thread.usp = data;
-	else if (regno <= PT_MAX)
-		((unsigned long *)(task->thread.esp0))[regno] = data;
+	else if (regno < PT_MAX)
+		((unsigned long *)user_regs(task))[regno] = data;
 	else
 		return -1;
 	return 0;
 }
+
+/* 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
+ * ignored.  Instead, the data variable is expected to point at a location
+ * (in user space) where the result of the ptrace call is written (instead of
+ * being returned).
+ */
 
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/setup.c linux/arch/cris/kernel/setup.c
--- v2.4.4/linux/arch/cris/kernel/setup.c	Fri Apr 27 14:10:31 2001
+++ linux/arch/cris/kernel/setup.c	Tue May  1 16:04:56 2001
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.11 2001/03/02 15:52:03 bjornw Exp $
+/* $Id: setup.c,v 1.14 2001/04/03 12:54:12 starvik Exp $
  *
  *  linux/arch/cris/kernel/setup.c
  *
@@ -60,7 +60,7 @@
  * given by the macro __pa().
  *
  * In this DRAM, the kernel code and data is loaded, in the beginning.
- * It really starts at c00a0000 to make room for some special pages - 
+ * It really starts at c0004000 to make room for some special pages - 
  * the start address is text_start. The kernel data ends at _end. After
  * this the ROM filesystem is appended (if there is any).
  * 
@@ -77,11 +77,6 @@
 	unsigned long memory_start;
 	extern void console_print_etrax(const char *b);
 
-#if (defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH))
-	/* TODO: move this into flash_init I think */
-	flash_probe();
-#endif
-
  	/* register an initial console printing routine for printk's */
 
 	init_etrax_debug();
@@ -167,8 +162,9 @@
 
 	paging_init();
 
-	/* we dont use a command line yet, so just let it be an empty string */
-
+	/* we dont use a command line yet, so just let it be an empty string 
+	   to start with */
+        
 	*cmdline_p = command_line;
 	strcpy(command_line, "root=/dev/rom"); /* use the appended romdisk as root */
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/shadows.c linux/arch/cris/kernel/shadows.c
--- v2.4.4/linux/arch/cris/kernel/shadows.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/shadows.c	Tue May  1 16:04:56 2001
@@ -1,20 +1,36 @@
-/* $Id: shadows.c,v 1.1 2000/07/10 16:25:21 bjornw Exp $
+/* $Id: shadows.c,v 1.2 2001/03/15 14:25:16 bjornw Exp $
  * 
- * Various Etrax shadow registers. Defines for these are in include/asm-etrax100/io.h
+ * Various shadow registers. Defines for these are in include/asm-etrax100/io.h
  */
 
-#include <linux/config.h>
+/* Shadows for internal Etrax-registers */
+
+unsigned long genconfig_shadow;
+unsigned long port_g_data_shadow;
+unsigned char port_pa_dir_shadow;
+unsigned char port_pa_data_shadow;
+unsigned char port_pb_i2c_shadow;
+unsigned char port_pb_config_shadow;
+unsigned char port_pb_dir_shadow;
+unsigned char port_pb_data_shadow;
+unsigned long r_timer_ctrl_shadow;
+
+/* Shadows for external I/O port registers.
+ * These are only usable if there actually IS a latch connected
+ * to the corresponding external chip-select pin.
+ *
+ * A common usage is that CSP0 controls LED's and CSP4 video chips.
+ */
+
+unsigned long port_cse1_shadow;
+unsigned long port_csp0_shadow;
+unsigned long port_csp4_shadow;
+
+/* Corresponding addresses for the ports.
+ * These are initialized in arch/cris/mm/init.c using ioremap.
+ */
+
+volatile unsigned long *port_cse1_addr;
+volatile unsigned long *port_csp0_addr;
+volatile unsigned long *port_csp4_addr;
 
-unsigned long genconfig_shadow = 42;
-unsigned long port_g_data_shadow = 42;
-unsigned char port_pa_dir_shadow = 42;
-unsigned char port_pa_data_shadow = 42;
-unsigned char port_pb_i2c_shadow = 42;
-unsigned char port_pb_config_shadow = 42;
-unsigned char port_pb_dir_shadow = 42;
-unsigned char port_pb_data_shadow = 42;
-unsigned long r_timer_ctrl_shadow = 42;
-
-#ifdef CONFIG_ETRAX_90000000_LEDS
-unsigned long port_90000000_shadow = 42;
-#endif
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/signal.c linux/arch/cris/kernel/signal.c
--- v2.4.4/linux/arch/cris/kernel/signal.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/signal.c	Tue May  1 16:04:56 2001
@@ -36,6 +36,9 @@
 /* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */
 /* manipulate regs so that upon return, it will be re-executed */
 
+/* We rely on that pc points to the instruction after "break 13", so the
+ * library must never do strange things like putting it in a delay slot.
+ */
 #define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2;
 
 int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
@@ -76,12 +79,14 @@
 }
 
 /*
- * Atomically swap in the new signal mask, and wait for a signal.
+ * Atomically swap in the new signal mask, and wait for a signal.  Define 
+ * dummy arguments to be able to reach the regs argument.  (Note that this
+ * arrangement relies on old_sigset_t occupying one register.)
  */
 int
-sys_sigsuspend(old_sigset_t mask)
+sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, 
+               long srp, struct pt_regs *regs)
 {
-	struct pt_regs * regs = (struct pt_regs *)current_regs();
 	sigset_t saveset;
 
 	mask &= _BLOCKABLE;
@@ -100,10 +105,13 @@
 	}
 }
 
+/* Define dummy arguments to be able to reach the regs argument.  (Note that
+ * this arrangement relies on size_t occupying one register.)
+ */
 int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13, 
+                  long mof, long srp, struct pt_regs *regs)
 {
-	struct pt_regs * regs = (struct pt_regs *)current_regs();
 	sigset_t saveset, newset;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
@@ -225,9 +233,11 @@
 	return 1;
 }
 
-asmlinkage int sys_sigreturn(void)
+/* Define dummy arguments to be able to reach the regs argument.  */
+
+asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, 
+                             long srp, struct pt_regs *regs)
 {
-	struct pt_regs *regs = (struct pt_regs *)current_regs();
 	struct sigframe *frame = (struct sigframe *)rdusp();
 	sigset_t set;
 
@@ -265,9 +275,11 @@
 	return 0;
 }	
 
-asmlinkage int sys_rt_sigreturn(void)
+/* Define dummy arguments to be able to reach the regs argument.  */
+
+asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, 
+                                long mof, long srp, struct pt_regs *regs)
 {
-	struct pt_regs *regs = (struct pt_regs *)current_regs();
 	struct rt_sigframe *frame = (struct rt_sigframe *)rdusp();
 	sigset_t set;
 	stack_t st;
@@ -389,7 +401,6 @@
 		/* trampoline - the desired return ip is the retcode itself */
 		return_ip = (unsigned long)&frame->retcode;
 		/* This is movu.w __NR_sigreturn, r9; break 13; */
-		/* TODO: check byteorder */
 		err |= __put_user(0x9c5f,         (short *)(frame->retcode+0));
 		err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
 		err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
@@ -535,7 +546,14 @@
  * Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
+ *
+ * Also note that the regs structure given here as an argument, is the latest
+ * pushed pt_regs. It may or may not be the same as the first pushed registers
+ * when the initial usermode->kernelmode transition took place. Therefore
+ * we can use user_mode(regs) to see if we came directly from kernel or user
+ * mode below.
  */
+
 int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
 {
 	siginfo_t info;
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/sys_cris.c linux/arch/cris/kernel/sys_cris.c
--- v2.4.4/linux/arch/cris/kernel/sys_cris.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/sys_cris.c	Tue May  1 16:04:56 2001
@@ -1,6 +1,6 @@
-/* $Id: sys_cris.c,v 1.4 2001/01/31 14:55:58 perf Exp $
+/* $Id: sys_cris.c,v 1.7 2001/04/17 11:52:15 orjanf Exp $
  *
- * linux/arch/cris/kernel/sys_etrax.c
+ * linux/arch/cris/kernel/sys_cris.c
  *
  * This file contains various random system calls that
  * have a non-standard calling sequence on some platforms.
@@ -177,20 +177,13 @@
 	case MSGCTL:
 		return sys_msgctl (first, second, (struct msqid_ds *) ptr);
 
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = sys_shmat (first, (char *) ptr, second, &raddr);
-			if (ret)
-				return ret;
-			return put_user (raddr, (ulong *) third);
-		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			return sys_shmat (first, (char *) ptr, second, (ulong *) third);
-		}
+	case SHMAT: {
+                ulong raddr;
+                ret = sys_shmat (first, (char *) ptr, second, &raddr);
+                if (ret)
+                        return ret;
+                return put_user (raddr, (ulong *) third);
+        }
 	case SHMDT: 
 		return sys_shmdt ((char *)ptr);
 	case SHMGET:
diff -u --recursive --new-file v2.4.4/linux/arch/cris/kernel/traps.c linux/arch/cris/kernel/traps.c
--- v2.4.4/linux/arch/cris/kernel/traps.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/kernel/traps.c	Sun May 20 12:11:38 2001
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.8 2001/02/23 13:45:20 bjornw Exp $
+/* $Id: traps.c,v 1.11 2001/04/04 09:43:31 orjanf Exp $
  *
  *  linux/arch/cris/traps.c
  *
@@ -9,11 +9,9 @@
  *  Copyright (C) 2000,2001 Axis Communications AB
  *
  *  Authors:   Bjorn Wesen
- *             Orjan Friberg
  *
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -45,8 +43,10 @@
         int i;
 	extern char _stext, _etext;
 
-        // debugging aid: "show_stack(NULL);" prints the
-        // back trace for this cpu.
+        /*
+         * debugging aid: "show_stack(NULL);" prints the
+         * back trace for this cpu.
+         */
 
         if(sp == NULL)
                 sp = (unsigned long*)rdsp();
@@ -107,8 +107,8 @@
 {
 	unsigned long usp = rdusp();
 
-	printk("IRP: %08lx SRP: %08lx CCR: %08lx USP: %08lx\n",
-	       regs->irp, regs->srp, regs->dccr, usp );
+	printk("IRP: %08lx SRP: %08lx CCR: %08lx USP: %08lx MOF: %08lx\n",
+	       regs->irp, regs->srp, regs->dccr, usp, regs->mof );
 	printk(" r0: %08lx  r1: %08lx  r2: %08lx  r3: %08lx\n",
 	       regs->r0, regs->r1, regs->r2, regs->r3);
 	printk(" r4: %08lx  r5: %08lx  r6: %08lx  r7: %08lx\n",
@@ -120,7 +120,7 @@
 	printk("Process %s (pid: %d, stackpage=%08lx)\n",
 	       current->comm, current->pid, (unsigned long)current);
 
-	// TODO, fix in_kernel detection
+	/* TODO, fix in_kernel detection */
 
 #if 0
 	/*
@@ -168,65 +168,5 @@
 void __init 
 trap_init(void)
 {
-
+  /* Nothing needs to be done */
 }
-
-/* Use static variables instead of the stack for temporary storage.  */
-static int saved_r0 = 0;
-static int saved_dccr = 0;
-
-asm ("
-  .global _gdb_handle_breakpoint
-  .global _do_sigtrap
-_gdb_handle_breakpoint:
-;;
-;; This handles a break instruction for entering a debug session.
-;;
-  move     dccr,[_saved_dccr]       ; Save dccr.
-  move.d   r0,[_saved_r0]           ; Save r0. "
-#ifdef CONFIG_KGDB
-" 
-  move     ccr,r0                   
-  btstq    8,r0                     ; Test the U-flag.
-  bmi      _ugdb_handle_breakpoint  ; Go to user mode debugging.
-  nop                               ; Delay slot.
-  move.d   [_saved_r0],r0           ; Restore r0.
-  move     [_saved_dccr],dccr       ; Restore dccr.
-  ba       _kgdb_handle_breakpoint  ; Go to kernel debugging.
-  nop                               ; Delay slot. "
-#endif
-" 
-_ugdb_handle_breakpoint:
-;;
-;; Yes, we could do a 'push brp' here and let gdb adjust the pc once it
-;; starts talking to the target again, but this way we avoid a 'P' packet.
-;;
-  move     brp,r0               ; Use r0 temporarily for calculation.
-  subq     2,r0                 ; Set to address of previous instruction.
-  move     r0,brp               ; Restore new brp.
-  move.d   [_saved_r0],r0       ; Restore r0.
-  move     [_saved_dccr],dccr   ; Restore dccr.
-
-_do_sigtrap:
-;; 
-;; SIGTRAP the process that executed the break instruction.
-;; Make a frame that Rexit in entry.S expects.
-;;
-  push     brp                  ; Push breakpoint return pointer.
-  push     srp                  ; Push subroutine return pointer.
-  push     dccr                 ; Push condition codes.
-  push     mof                  ; Push multiply overflow reg.
-  di                            ; Need to disable irq's at this point.
-  subq     14*4,sp              ; Make room for r0-r13.
-  movem    r13,[sp]             ; Push the r0-r13 registers.
-  push     r10                  ; Push orig_r10.
-  clear.d  [sp=sp-4]            ; Frametype - this is a normal stackframe.
-
-  movs.w   -8192,r9             ; THREAD_SIZE == 8192
-  and.d    sp,r9
-  move.d   [r9+LTASK_PID],r10   ; current->pid as arg1.
-  moveq    5,r11                ; SIGTRAP as arg2.
-  jsr      _sys_kill       
-
-  jump     _ret_from_intr       ; Use the return routine for interrupts.
-");
diff -u --recursive --new-file v2.4.4/linux/arch/cris/lib/dram_init.S linux/arch/cris/lib/dram_init.S
--- v2.4.4/linux/arch/cris/lib/dram_init.S	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/lib/dram_init.S	Tue May  1 16:04:56 2001
@@ -1,63 +1,97 @@
-	;; $Id: dram_init.S,v 1.2 2001/02/08 15:20:00 starvik Exp $
-	;; 
-	;; DRAM/SDRAM initialization - alter with care
-	;; This file is intended to be included from other assembler files
-	;;
-	;; Copyright (C) 2000 Axis Communications AB
-	;;
-	;; Authors:  Mikael Starvik (starvik@axis.com)	
-	;;           Bjorn Wesen (bjornw@axis.com)
-	;; 
-	;; $Log: dram_init.S,v $
-	;; Revision 1.2  2001/02/08 15:20:00  starvik
-	;; Corrected SDRAM initialization
-	;; Should now be included as inline
-	;;
-	;; Revision 1.1  2001/01/29 13:08:02  starvik
-	;; Initial version
-	;; This file should be included from all assembler files that needs to
-	;; initialize DRAM/SDRAM.
-	;;
-	;;
-	;;
+/* $Id: dram_init.S,v 1.7 2001/04/18 12:05:39 bjornw Exp $
+ * 
+ * DRAM/SDRAM initialization - alter with care
+ * This file is intended to be included from other assembler files
+ *
+ * Note: This file may not modify r9 because r9 is used to carry
+ *       information from the decompresser to the kernel
+ *
+ * Copyright (C) 2000, 2001 Axis Communications AB
+ *
+ * Authors:  Mikael Starvik (starvik@axis.com)	
+ * 
+ * $Log: dram_init.S,v $
+ * Revision 1.7  2001/04/18 12:05:39  bjornw
+ * Fixed comments, and explicitely include config.h to be sure its there
+ *
+ * Revision 1.6  2001/04/10 06:20:16  starvik
+ * Delay should be 200us, not 200ns
+ *
+ * Revision 1.5  2001/04/09 06:01:13  starvik
+ * Added support for 100 MHz SDRAMs
+ *
+ * Revision 1.4  2001/03/26 14:24:01  bjornw
+ * Namechange of some config options
+ *
+ * Revision 1.3  2001/03/23 08:29:41  starvik
+ * Corrected calculation of mrs_data
+ *
+ * Revision 1.2  2001/02/08 15:20:00  starvik
+ * Corrected SDRAM initialization
+ * Should now be included as inline
+ *
+ * Revision 1.1  2001/01/29 13:08:02  starvik
+ * Initial version
+ * This file should be included from all assembler files that needs to
+ * initialize DRAM/SDRAM.
+ *
+ */
+
+/* Just to be certain the config file is included, we include it here
+ * explicitely instead of depending on it being included in the file that
+ * uses this code.
+ */
 
 #include <linux/config.h>
 
+
 #ifndef CONFIG_SVINTO_SIM	
-	move.d   DEF_R_WAITSTATES, r0
+	move.d   CONFIG_ETRAX_DEF_R_WAITSTATES, r0
 	move.d   r0, [R_WAITSTATES]
 
-	move.d   DEF_R_BUS_CONFIG, r0
+	move.d   CONFIG_ETRAX_DEF_R_BUS_CONFIG, r0
 	move.d   r0, [R_BUS_CONFIG]
 	
-#ifndef CONFIG_SDRAM
-	move.d   DEF_R_DRAM_CONFIG, r0
+#ifndef CONFIG_ETRAX_SDRAM
+	move.d   CONFIG_ETRAX_DEF_R_DRAM_CONFIG, r0
 	move.d   r0, [R_DRAM_CONFIG]
 
-	move.d   DEF_R_DRAM_TIMING, r0
+	move.d   CONFIG_ETRAX_DEF_R_DRAM_TIMING, r0
 	move.d   r0, [R_DRAM_TIMING]
 #else	
 	; Refer to ETRAX 100LX Designers Reference for a description of SDRAM initialization
 	
 	; Bank configuration
-        move.d   DEF_R_SDRAM_CONFIG, r0
+	move.d   CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, r0
 	move.d   r0, [R_SDRAM_CONFIG]
 
 	; Calculate value of mrs_data 
-	; cas_delay = 2 && bus_width = 32 => 0x40
-	; cas_delay = 3 && bus_width = 32 => 0x60
-	; cas_delay = 2 && bus_width = 16 => 0x20
-	; cas_delay = 3 && bus_width = 16 => 0x30
+	; CAS latency = 2 && bus_width = 32 => 0x40
+	; CAS latency = 3 && bus_width = 32 => 0x60
+	; CAS latency = 2 && bus_width = 16 => 0x20
+	; CAS latency = 3 && bus_width = 16 => 0x30
 	
-	move.d   0x40, r2       ; Assume 32 bits and cas_delay = 2
-	move.d   DEF_R_SDRAM_TIMING, r1
-	and.d    0x0c, r1	; Get cas delay
-	cmp.d    0x08, r1	; cas_delay = 2?
-        beq      bw_check
+	move.d   0x40, r2       ; Assume 32 bits and CAS latency = 2
+	move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, r1
+	move.d   r1, r3
+ 	and.d    0x03, r1       ; Get CAS latency
+	and.d    0x1000, r3     ; 50 or 100 MHz?
+	beq      speed_50
+	nop
+speed_100:		
+	cmp.d    0x00, r1	; CAS latency = 2?
+	beq      bw_check
+	nop
+	or.d     0x20, r2	; CAS latency = 3 
+	ba       bw_check
+	nop
+speed_50:			
+	cmp.d    0x01, r1	; CAS latency = 2?
+	beq      bw_check
 	nop
-	or.d     0x20, r2       ; cas_delay = 3
+	or.d     0x20, r2       ; CAS latency = 3
 bw_check:
-	move.d   DEF_R_SDRAM_CONFIG, r1
+	move.d   CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, r1
 	and.d    0x800000, r1	; DRAM width is bit 23
 	bne      set_timing
 	nop
@@ -65,14 +99,17 @@
 
 	; Set timing parameters. Starts master clock
 set_timing:
-	move.d   DEF_R_SDRAM_TIMING, r1
+	move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, r1
+	and.d    0x8000f9ff, r1 ; Make sure mrs data and command is 0 
 	or.d     0x80000000, r1	; Make sure sdram enable bit is set
+	move.d   r1, r5
+	or.d     0x0000c000, r1 ; ref = disable
 	lslq     16, r2		; mrs data starts at bit 16
 	or.d     r2, r1 
 	move.d   r1, [R_SDRAM_TIMING]	
 		
-	; Wait 200ns
-	move.d   10, r2
+	; Wait 200us
+	move.d   10000, r2
 sdram_loop:
 	bne      sdram_loop
 	subq     1, r2
@@ -83,10 +120,10 @@
 command_loop:
 	clear.d  r4
 	move.b   [r2+], r4
-	lslq     9, r4		; Command starts at bit 9
+	lslq     9, r4	; Command starts at bit 9
 	or.d     r1, r4
 	move.d   r4, [R_SDRAM_TIMING]
-	nop			; Wait five nop cycles between each command
+	nop		; Wait five nop cycles between each command
 	nop
 	nop
 	nop
@@ -94,6 +131,7 @@
 	cmp.d    r2, r3
 	bne      command_loop
 	nop
+	move.d   r5, [R_SDRAM_TIMING]
 	ba       sdram_commands_end
 	nop
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/lib/hw_settings.S linux/arch/cris/lib/hw_settings.S
--- v2.4.4/linux/arch/cris/lib/hw_settings.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/hw_settings.S	Sun May 20 12:11:38 2001
@@ -0,0 +1,61 @@
+	;; $Id: hw_settings.S,v 1.2 2001/04/03 11:11:09 starvik Exp $
+	;; 
+	;; This table is used by some tools to extract hardware parameters.
+	;; The table should be included in the kernel and the decompressor.
+	;; Don't forget to update the tools if you change this table.
+	;;
+	;; Copyright (C) 2001 Axis Communications AB
+	;;
+	;; Authors:  Mikael Starvik (starvik@axis.com)	
+
+	
+#define PA_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PA_DIR << 8) | \
+		(CONFIG_ETRAX_DEF_R_PORT_PA_DATA))
+#define PB_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG << 16) | \
+		(CONFIG_ETRAX_DEF_R_PORT_PB_DIR << 8) | \
+		(CONFIG_ETRAX_DEF_R_PORT_PB_DATA))
+	
+	.ascii "HW_PARAM_MAGIC" ; Magic number
+	.dword 0xc0004000	; Kernel start address
+
+	; Debug port
+#ifdef CONFIG_ETRAX_DEBUG_PORT0
+	.dword 0		
+#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
+	.dword 1
+#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
+	.dword 2
+#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
+	.dword 3
+#else
+	.dword 4 ; No debug
+#endif			
+
+	; SDRAM or EDO DRAM?
+#ifdef CONFIG_ETRAX_SDRAM
+	.dword 1
+#else
+	.dword 0
+#endif
+
+	; Register values 
+	.dword R_WAITSTATES
+	.dword CONFIG_ETRAX_DEF_R_WAITSTATES
+	.dword R_BUS_CONFIG
+	.dword CONFIG_ETRAX_DEF_R_BUS_CONFIG
+#ifdef CONFIG_ETRAX_SDRAM
+	.dword R_SDRAM_CONFIG
+	.dword CONFIG_ETRAX_DEF_R_SDRAM_CONFIG
+	.dword R_SDRAM_TIMING
+	.dword CONFIG_ETRAX_DEF_R_SDRAM_TIMING
+#else
+	.dword R_DRAM_CONFIG
+	.dword CONFIG_ETRAX_DEF_R_DRAM_CONFIG
+	.dword R_DRAM_TIMING
+	.dword CONFIG_ETRAX_DEF_R_DRAM_TIMING
+#endif
+	.dword R_PORT_PA_SET
+	.dword PA_SET_VALUE 
+	.dword R_PORT_PB_SET
+	.dword PB_SET_VALUE
+	.dword 0 ; No more register values
diff -u --recursive --new-file v2.4.4/linux/arch/cris/lib/memset.c linux/arch/cris/lib/memset.c
--- v2.4.4/linux/arch/cris/lib/memset.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/lib/memset.c	Tue May  1 16:04:56 2001
@@ -27,6 +27,8 @@
 /*#                                                                         */
 /*#-------------------------------------------------------------------------*/
 
+#include <linux/types.h>
+
 /* No, there's no macro saying 12*4, since it is "hard" to get it into
    the asm in a good way.  Thus better to expose the problem everywhere.
    */
@@ -39,7 +41,7 @@
 
 void *memset(void *pdst,
              int c,
-             unsigned int plen)
+             size_t plen)
 {
   /* Ok.  Now we want the parameters put in special registers.
      Make sure the compiler is able to make something useful of this. */
@@ -54,7 +56,12 @@
 
   /* Ugh.  This is fragile at best.  Check with newer GCC releases, if
      they compile cascaded "x |= x << 8" sanely! */
-  __asm__("movu.b %0,r13\n\tlslq 8,r13\n\tmove.b %0,r13\n\tmove.d r13,%0\n\tlslq 16,r13\n\tor.d r13,%0"
+  __asm__("movu.b %0,r13\n\t"
+          "lslq 8,r13\n\t"
+	  "move.b %0,r13\n\t"
+	  "move.d r13,%0\n\t"
+	  "lslq 16,r13\n\t"
+	  "or.d r13,%0"
           : "=r" (lc) : "0" (lc) : "r13");
 
   {
diff -u --recursive --new-file v2.4.4/linux/arch/cris/lib/string.c linux/arch/cris/lib/string.c
--- v2.4.4/linux/arch/cris/lib/string.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/lib/string.c	Tue May  1 16:04:56 2001
@@ -31,9 +31,11 @@
 /*#                                                                         */
 /*#-------------------------------------------------------------------------*/
 
+#include <linux/types.h>
+
 void *memcpy(void *pdst,
              const void *psrc,
-             unsigned int pn)
+             size_t pn)
 {
   /* Ok.  Now we want the parameters put in special registers.
      Make sure the compiler is able to make something useful of this.
diff -u --recursive --new-file v2.4.4/linux/arch/cris/mm/extable.c linux/arch/cris/mm/extable.c
--- v2.4.4/linux/arch/cris/mm/extable.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/mm/extable.c	Tue May  1 16:04:56 2001
@@ -37,8 +37,7 @@
 
 #ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
-	ret = search_one_table(_start___ex_table, _stop___ex_table-1, addr);
-	if (ret) return ret;
+	return search_one_table(_start___ex_table, _stop___ex_table-1, addr);
 #else
 	/* The kernel is the last "module" -- no need to treat it special.  */
 	struct module *mp;
diff -u --recursive --new-file v2.4.4/linux/arch/cris/mm/fault.c linux/arch/cris/mm/fault.c
--- v2.4.4/linux/arch/cris/mm/fault.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/mm/fault.c	Tue May  1 16:04:56 2001
@@ -1,11 +1,20 @@
 /*
  *  linux/arch/cris/mm/fault.c
  *
- *  Copyright (C) 2000  Axis Communications AB
+ *  Copyright (C) 2000, 2001  Axis Communications AB
  *
  *  Authors:  Bjorn Wesen 
  * 
  *  $Log: fault.c,v $
+ *  Revision 1.12  2001/04/04 10:51:14  bjornw
+ *  mmap_sem is grabbed for reading
+ *
+ *  Revision 1.11  2001/03/23 07:36:07  starvik
+ *  Corrected according to review remarks
+ *
+ *  Revision 1.10  2001/03/21 16:10:11  bjornw
+ *  CRIS_FRAME_FIXUP not needed anymore, use FRAME_NORMAL
+ *
  *  Revision 1.9  2001/03/05 13:22:20  bjornw
  *  Spell-fix and fix in vmalloc_fault handling
  *
@@ -70,12 +79,12 @@
 
 	address = cause & PAGE_MASK; /* get faulting address */
 	
-	page_id = IO_EXTRACT(R_MMU_CAUSE,  page_id,   cause);
+	D(page_id = IO_EXTRACT(R_MMU_CAUSE,  page_id,   cause));
+	D(acc     = IO_EXTRACT(R_MMU_CAUSE,  acc_excp,  cause));
+	D(inv     = IO_EXTRACT(R_MMU_CAUSE,  inv_excp,  cause));  
+	D(index  =  IO_EXTRACT(R_TLB_SELECT, index,     select));
 	miss    = IO_EXTRACT(R_MMU_CAUSE,  miss_excp, cause);
 	we      = IO_EXTRACT(R_MMU_CAUSE,  we_excp,   cause);
-	acc     = IO_EXTRACT(R_MMU_CAUSE,  acc_excp,  cause);
-	inv     = IO_EXTRACT(R_MMU_CAUSE,  inv_excp,  cause);  
-	index  =  IO_EXTRACT(R_TLB_SELECT, index,     select);
 	
 	D(printk("bus_fault from IRP 0x%x: addr 0x%x, miss %d, inv %d, we %d, acc %d, "
 		 "idx %d pid %d\n",
@@ -304,23 +313,32 @@
 	/* Are we prepared to handle this kernel fault?
 	 *
 	 * (The kernel has valid exception-points in the source 
-	 *  when it accesses user-memory. When it fails in one
+	 *  when it acesses user-memory. When it fails in one
 	 *  of those points, we find it in a table and do a jump
 	 *  to some fixup code that loads an appropriate error
 	 *  code)
 	 */
 
         if ((fixup = search_exception_table(regs->irp)) != 0) {
+		/* Adjust the instruction pointer in the stackframe */
+
                 regs->irp = fixup;
-		regs->frametype = CRIS_FRAME_FIXUP;
+
+		/* We do not want to return by restoring the CPU-state
+		 * anymore, so switch frame-types (see ptrace.h)
+		 */
+
+		regs->frametype = CRIS_FRAME_NORMAL;
+
 		D(printk("doing fixup to 0x%x\n", fixup));
                 return;
         }
 
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
+	/*
+	 * Oops. The kernel tried to access some bad page. We'll have to
+	 * terminate things with extreme prejudice.
+	 */
+
 	if ((unsigned long) (address) < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 	else
diff -u --recursive --new-file v2.4.4/linux/arch/cris/mm/init.c linux/arch/cris/mm/init.c
--- v2.4.4/linux/arch/cris/mm/init.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/mm/init.c	Tue May  1 16:04:56 2001
@@ -7,6 +7,22 @@
  *  Authors:  Bjorn Wesen (bjornw@axis.com)
  *
  *  $Log: init.c,v $
+ *  Revision 1.23  2001/04/04 14:35:40  bjornw
+ *  * Removed get_pte_slow and friends (2.4.3 change)
+ *  * Removed bad_pmd handling (2.4.3 change)
+ *
+ *  Revision 1.22  2001/04/04 13:38:04  matsfg
+ *  Moved ioremap to a separate function instead
+ *
+ *  Revision 1.21  2001/03/27 09:28:33  bjornw
+ *  ioremap used too early - lets try it in mem_init instead
+ *
+ *  Revision 1.20  2001/03/23 07:39:21  starvik
+ *  Corrected according to review remarks
+ *
+ *  Revision 1.19  2001/03/15 14:25:17  bjornw
+ *  More general shadow registers and ioremaped addresses for external I/O
+ *
  *  Revision 1.18  2001/02/23 12:46:44  bjornw
  *  * 0xc was not CSE1; 0x8 is, same as uncached flash, so we move the uncached
  *    flash during CRIS_LOW_MAP from 0xe to 0x8 so both the flash and the I/O
@@ -68,6 +84,7 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/svinto.h>
+#include <asm/io.h>
 
 static unsigned long totalram_pages;
 
@@ -79,128 +96,13 @@
 extern void show_net_buffers(void);
 extern void tlb_init(void);
 
-/*
- * empty_bad_page is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
- * unused etc..
- *
- * the main point is that when a page table error occurs, we want to get
- * out of the kernel safely before killing the process, so we need something
- * to feed the MMU with when the fault occurs even if we don't have any
- * real PTE's or page tables.
- *
- * empty_bad_page_table is the accompanying page-table: it is initialized
- * to point to empty_bad_page writable-shared entries.
- *
- * empty_zero_page is a special page that is used for zero-initialized
- * data and COW.
- */
 
-unsigned long empty_bad_page_table;
-unsigned long empty_bad_page;
 unsigned long empty_zero_page;
 
-pte_t * __bad_pagetable(void)
-{
-	/* somehow it is enough to just clear it and not fill it with
-	 * bad page PTE's...
-	 */
-	memset((void *)empty_bad_page_table, 0, PAGE_SIZE);
-
-	return (pte_t *) empty_bad_page_table;
-}
-
-pte_t __bad_page(void)
-{
-
-	/* clear the empty_bad_page page. this should perhaps be
-	 * a more simple inlined loop like it is on the other 
-	 * architectures.
-	 */
-
-	memset((void *)empty_bad_page, 0, PAGE_SIZE);
-
-	return pte_mkdirty(__mk_pte((void *)empty_bad_page, PAGE_SHARED));
-}
-
-static pte_t * get_bad_pte_table(void)
-{
-	pte_t *empty_bad_pte_table = (pte_t *)empty_bad_page_table;
-	pte_t v;
-	int i;
-
-	v = __bad_page();
-
-	for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
-		empty_bad_pte_table[i] = v;
-
-	return empty_bad_pte_table;
-}
-
-void __handle_bad_pmd(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-	pmd_set(pmd, get_bad_pte_table());
-}
-
-void __handle_bad_pmd_kernel(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-	pmd_set_kernel(pmd, get_bad_pte_table());
-}
-
-pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
-{
-        pte_t *pte;
-
-        pte = (pte_t *) __get_free_page(GFP_KERNEL);
-        if (pmd_none(*pmd)) {
-                if (pte) {
-                        clear_page(pte);
-			pmd_set_kernel(pmd, pte);
-                        return pte + offset;
-                }
-		pmd_set_kernel(pmd, get_bad_pte_table());
-                return NULL;
-        }
-        free_page((unsigned long)pte);
-        if (pmd_bad(*pmd)) {
-                __handle_bad_pmd_kernel(pmd);
-                return NULL;
-        }
-        return (pte_t *) pmd_page(*pmd) + offset;
-}
-
-pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-        pte = (pte_t *) __get_free_page(GFP_KERNEL);
-        if (pmd_none(*pmd)) {
-                if (pte) {
-                        clear_page(pte);
-			pmd_set(pmd, pte);
-                        return pte + offset;
-                }
-		pmd_set(pmd, get_bad_pte_table());
-                return NULL;
-        }
-        free_page((unsigned long)pte);
-        if (pmd_bad(*pmd)) {
-                __handle_bad_pmd(pmd);
-                return NULL;
-        }
-        return (pte_t *) pmd_page(*pmd) + offset;
-}
-
-#ifndef CONFIG_NO_PGT_CACHE
-struct pgtable_cache_struct quicklists;
-
 /* trim the page-table cache if necessary */
 
-int do_check_pgt_cache(int low, int high)
+int 
+do_check_pgt_cache(int low, int high)
 {
         int freed = 0;
 
@@ -211,25 +113,20 @@
                                 freed++;
                         }
                         if(pmd_quicklist) {
-                                free_pmd_slow(get_pmd_fast());
+                                pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
                                 freed++;
                         }
                         if(pte_quicklist) {
-                                free_pte_slow(get_pte_fast());
-                                 freed++;
+                                pte_free_slow(pte_alloc_one_fast(NULL, 0));
+				freed++;
                         }
                 } while(pgtable_cache_size > low);
         }
         return freed;
 }
-#else
-int do_check_pgt_cache(int low, int high)
-{
-        return 0;
-}
-#endif
 
-void show_mem(void)
+void 
+show_mem(void)
 {
 	int i,free = 0,total = 0,cached = 0, reserved = 0, nonshared = 0;
 	int shared = 0;
@@ -287,15 +184,51 @@
 
 	/* see README.mm for details on the KSEG setup */
 
-#ifdef CONFIG_CRIS_LOW_MAP
+#ifndef CONFIG_CRIS_LOW_MAP
+	/* This code is for the corrected Etrax-100 LX version 2... */
 
+	*R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg  ) | /* cached flash */
+			IO_STATE(R_MMU_KSEG, seg_e, seg  ) | /* uncached flash */
+			IO_STATE(R_MMU_KSEG, seg_d, page ) | /* vmalloc area */
+			IO_STATE(R_MMU_KSEG, seg_c, seg  ) | /* kernel area */
+			IO_STATE(R_MMU_KSEG, seg_b, seg  ) | /* kernel reg area */
+			IO_STATE(R_MMU_KSEG, seg_a, page ) | /* user area */
+			IO_STATE(R_MMU_KSEG, seg_9, page ) |
+			IO_STATE(R_MMU_KSEG, seg_8, page ) |
+			IO_STATE(R_MMU_KSEG, seg_7, page ) |
+			IO_STATE(R_MMU_KSEG, seg_6, page ) |
+			IO_STATE(R_MMU_KSEG, seg_5, page ) |
+			IO_STATE(R_MMU_KSEG, seg_4, page ) |
+			IO_STATE(R_MMU_KSEG, seg_3, page ) |
+			IO_STATE(R_MMU_KSEG, seg_2, page ) |
+			IO_STATE(R_MMU_KSEG, seg_1, page ) |
+			IO_STATE(R_MMU_KSEG, seg_0, page ) );
+
+	*R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_c, 0x4 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
+	
+	*R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_6, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
+#else
 	/* Etrax-100 LX version 1 has a bug so that we cannot map anything
 	 * across the 0x80000000 boundary, so we need to shrink the user-virtual
 	 * area to 0x50000000 instead of 0xb0000000 and map things slightly
 	 * different. The unused areas are marked as paged so that we can catch
 	 * freak kernel accesses there.
 	 *
-	 * The Juliette chip is mapped at 0xa so we pass that segment straight
+	 * The ARTPEC chip is mapped at 0xa so we pass that segment straight
 	 * through. We cannot vremap it because the vmalloc area is below 0x8
 	 * and Juliette needs an uncached area above 0x8.
 	 *
@@ -308,7 +241,7 @@
 			IO_STATE(R_MMU_KSEG, seg_d, page ) | 
 			IO_STATE(R_MMU_KSEG, seg_c, page ) |   
 			IO_STATE(R_MMU_KSEG, seg_b, seg  ) |  /* kernel reg area */
-			IO_STATE(R_MMU_KSEG, seg_a, seg  ) |  /* Juliette etc. */
+			IO_STATE(R_MMU_KSEG, seg_a, seg  ) |  /* ARTPEC etc. */
 			IO_STATE(R_MMU_KSEG, seg_9, seg  ) |  /* LED's on some boards */
 			IO_STATE(R_MMU_KSEG, seg_8, seg  ) |  /* CSE0/1, flash and I/O */
 			IO_STATE(R_MMU_KSEG, seg_7, page ) |  /* kernel vmalloc area */
@@ -337,44 +270,7 @@
 			    IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
 			    IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
 			    IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
-#else
-	/* This code is for the hopefully corrected Etrax-100 LX version 2... */
-
-	*R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg  ) | /* cached flash */
-			IO_STATE(R_MMU_KSEG, seg_e, seg  ) | /* uncached flash */
-			IO_STATE(R_MMU_KSEG, seg_d, page ) | /* vmalloc area */
-			IO_STATE(R_MMU_KSEG, seg_c, seg  ) | /* kernel area */
-			IO_STATE(R_MMU_KSEG, seg_b, seg  ) | /* kernel reg area */
-			IO_STATE(R_MMU_KSEG, seg_a, page ) | /* user area */
-			IO_STATE(R_MMU_KSEG, seg_9, page ) |
-			IO_STATE(R_MMU_KSEG, seg_8, page ) |
-			IO_STATE(R_MMU_KSEG, seg_7, page ) |
-			IO_STATE(R_MMU_KSEG, seg_6, page ) |
-			IO_STATE(R_MMU_KSEG, seg_5, page ) |
-			IO_STATE(R_MMU_KSEG, seg_4, page ) |
-			IO_STATE(R_MMU_KSEG, seg_3, page ) |
-			IO_STATE(R_MMU_KSEG, seg_2, page ) |
-			IO_STATE(R_MMU_KSEG, seg_1, page ) |
-			IO_STATE(R_MMU_KSEG, seg_0, page ) );
-
-	*R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_c, 0x4 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
-	
-	*R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_6, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
-			    IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
-#endif	
+#endif
 
 	*R_MMU_CONTEXT = ( IO_FIELD(R_MMU_CONTEXT, page_id, 0 ) );
 	
@@ -393,8 +289,6 @@
 	 * to a couple of allocated pages
 	 */
 
-	empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
 	empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
 	memset((void *)empty_zero_page, 0, PAGE_SIZE);
 
@@ -412,6 +306,7 @@
 	 */
 
 	free_area_init_node(0, 0, 0, zones_size, PAGE_OFFSET, 0);
+
 }
 
 extern unsigned long loops_per_jiffy; /* init/main.c */
@@ -462,7 +357,7 @@
 	       datasize >> 10,
 	       initsize >> 10
                );
-	
+
 	/* HACK alert - calculate a loops_per_usec for asm/delay.h here
 	 * since this is called just after calibrate_delay in init/main.c
 	 * but before places which use udelay. cannot be in time.c since
@@ -474,9 +369,52 @@
 	return;
 }
 
+/* Initialize remaps of some I/O-ports. This is designed to be callable
+ * multiple times from the drivers init-sections, because we don't know
+ * beforehand which driver will get initialized first.
+ */
+
+void 
+init_ioremap(void)
+{
+  
+	/* Give the external I/O-port addresses their values */
+
+        static int initialized = 0;
+  
+        if( !initialized ) {
+                initialized++;
+            
+#ifdef CONFIG_CRIS_LOW_MAP
+               /* Simply a linear map (see the KSEG map above in paging_init) */
+               port_cse1_addr = (volatile unsigned long *)(MEM_CSE1_START | 
+                                                           MEM_NON_CACHEABLE);
+               port_csp0_addr = (volatile unsigned long *)(MEM_CSP0_START |
+                                                           MEM_NON_CACHEABLE);
+               port_csp4_addr = (volatile unsigned long *)(MEM_CSP4_START |
+                                                           MEM_NON_CACHEABLE);
+#else
+               /* Note that nothing blows up just because we do this remapping 
+                * it's ok even if the ports are not used or connected 
+                * to anything (or connected to a non-I/O thing) */        
+               port_cse1_addr = (volatile unsigned long *)
+                 ioremap((unsigned long)(MEM_CSE1_START | 
+                                         MEM_NON_CACHEABLE), 16);
+               port_csp0_addr = (volatile unsigned long *)
+                 ioremap((unsigned long)(MEM_CSP0_START |
+                                         MEM_NON_CACHEABLE), 16);
+               port_csp4_addr = (volatile unsigned long *)
+                 ioremap((unsigned long)(MEM_CSP4_START |
+                                         MEM_NON_CACHEABLE), 16);
+#endif	
+        }
+}
+
+
 /* free the pages occupied by initialization code */
 
-void free_initmem(void)
+void 
+free_initmem(void)
 {
 #if 0
 	/* currently this is a bad idea since the cramfs image is catted onto
@@ -497,7 +435,8 @@
 #endif
 }
 
-void si_meminfo(struct sysinfo *val)
+void 
+si_meminfo(struct sysinfo *val)
 {
 	int i;
 
diff -u --recursive --new-file v2.4.4/linux/arch/cris/mm/ioremap.c linux/arch/cris/mm/ioremap.c
--- v2.4.4/linux/arch/cris/mm/ioremap.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/mm/ioremap.c	Tue May  1 16:04:56 2001
@@ -51,7 +51,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		pte_t * pte = pte_alloc_kernel(pmd, address);
+		pte_t * pte = pte_alloc(&init_mm, pmd, address);
 		if (!pte)
 			return -ENOMEM;
 		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
@@ -64,6 +64,7 @@
 static int remap_area_pages(unsigned long address, unsigned long phys_addr,
 				 unsigned long size, unsigned long flags)
 {
+	int error;
 	pgd_t * dir;
 	unsigned long end = address + size;
 
@@ -72,19 +73,23 @@
 	flush_cache_all();
 	if (address >= end)
 		BUG();
+	spin_lock(&init_mm.page_table_lock);
 	do {
 		pmd_t *pmd;
-		pmd = pmd_alloc_kernel(dir, address);
+		pmd = pmd_alloc(&init_mm, dir, address);
+		error = -ENOMEM;
 		if (!pmd)
-			return -ENOMEM;
+			break;
 		if (remap_area_pmd(pmd, address, end - address,
-					 phys_addr + address, flags))
-			return -ENOMEM;
+				   phys_addr + address, flags))
+			break;
+		error = 0;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
+	spin_unlock(&init_mm.page_table_lock);
 	flush_tlb_all();
-	return 0;
+	return error;
 }
 
 /*
diff -u --recursive --new-file v2.4.4/linux/arch/cris/mm/tlb.c linux/arch/cris/mm/tlb.c
--- v2.4.4/linux/arch/cris/mm/tlb.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/mm/tlb.c	Tue May  1 16:04:56 2001
@@ -288,7 +288,7 @@
 
 	/* clear the page_id map */
 
-	for(i = 0; i < 64; i++)
+	for(i = 0; i < NUM_PAGEID; i++)
 		page_id_map[i] = NULL;
 	
 	/* invalidate the entire TLB */
diff -u --recursive --new-file v2.4.4/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- v2.4.4/linux/arch/i386/boot/setup.S	Wed Apr 11 18:50:25 2001
+++ linux/arch/i386/boot/setup.S	Tue May  1 16:04:56 2001
@@ -32,6 +32,16 @@
  *
  * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
  * <stiker@northlink.com>
+ *
+ * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * and/or report extended memory in CX/DX for e801h memory size detection 
+ * call.  As a result the kernel got wrong figures.  The int15/e801h docs
+ * from Ralf Brown interrupt list seem to indicate AX/BX should be used
+ * anyway.  So to avoid breaking many machines (presumably there was a reason
+ * to orginally use CX/DX instead of AX/BX), we do a kludge to see
+ * if CX/DX have been changed in the e801 call and if so use AX/BX .
+ * Michael Miller, April 2001 <michaelm@mjmm.org>
+ *
  */
 
 #define __ASSEMBLY__
@@ -336,10 +346,24 @@
 # to write everything into the same place.)
 
 meme801:
+	stc					# fix to work around buggy
+	xorw	%cx,%cx				# BIOSes which dont clear/set
+	xorw	%dx,%dx				# carry on pass/error of
+						# e801h memory size call
+						# or merely pass cx,dx though
+						# without changing them.
 	movw	$0xe801, %ax
 	int	$0x15
 	jc	mem88
 
+	cmpw	$0x0, %cx			# Kludge to handle BIOSes
+	jne	e801usecxdx			# which report their extended
+	cmpw	$0x0, %dx			# memory in AX/BX rather than
+	jne	e801usecxdx			# CX/DX.  The spec I have read
+	movw	%ax, %cx			# seems to indicate AX/BX 
+	movw	%bx, %dx			# are more reasonable anyway...
+
+e801usecxdx:
 	andl	$0xffff, %edx			# clear sign extend
 	shll	$6, %edx			# and go from 64k to 1k chunks
 	movl	%edx, (0x1e0)			# store extended memory size
diff -u --recursive --new-file v2.4.4/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.4.4/linux/arch/i386/config.in	Fri Apr 20 18:26:15 2001
+++ linux/arch/i386/config.in	Thu May 24 15:14:08 2001
@@ -27,21 +27,21 @@
 mainmenu_option next_comment
 comment 'Processor type and features'
 choice 'Processor family' \
-	"386				CONFIG_M386 \
-	 486				CONFIG_M486 \
-	 586/K5/5x86/6x86/6x86MX	CONFIG_M586 \
-	 Pentium-Classic		CONFIG_M586TSC \
-	 Pentium-MMX			CONFIG_M586MMX \
-	 Pentium-Pro/Celeron/Pentium-II	CONFIG_M686 \
-	 Pentium-III			CONFIG_MPENTIUMIII \
-	 Pentium-4			CONFIG_MPENTIUM4 \
-	 K6/K6-II/K6-III		CONFIG_MK6 \
-	 Athlon/Duron/K7		CONFIG_MK7 \
-	 Crusoe				CONFIG_MCRUSOE \
-	 Winchip-C6			CONFIG_MWINCHIPC6 \
-	 Winchip-2			CONFIG_MWINCHIP2 \
-	 Winchip-2A/Winchip-3		CONFIG_MWINCHIP3D \
-	 CyrixIII/C3			CONFIG_MCYRIXIII" Pentium-Pro
+	"386					CONFIG_M386 \
+	 486					CONFIG_M486 \
+	 586/K5/5x86/6x86/6x86MX		CONFIG_M586 \
+	 Pentium-Classic			CONFIG_M586TSC \
+	 Pentium-MMX				CONFIG_M586MMX \
+	 Pentium-Pro/Celeron/Pentium-II		CONFIG_M686 \
+	 Pentium-III/Celeron(Coppermine)	CONFIG_MPENTIUMIII \
+	 Pentium-4				CONFIG_MPENTIUM4 \
+	 K6/K6-II/K6-III			CONFIG_MK6 \
+	 Athlon/Duron/K7			CONFIG_MK7 \
+	 Crusoe					CONFIG_MCRUSOE \
+	 Winchip-C6				CONFIG_MWINCHIPC6 \
+	 Winchip-2				CONFIG_MWINCHIP2 \
+	 Winchip-2A/Winchip-3			CONFIG_MWINCHIP3D \
+	 CyrixIII/C3				CONFIG_MCYRIXIII" Pentium-Pro
 #
 # Define implied options from the CPU selection here
 #
diff -u --recursive --new-file v2.4.4/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.4/linux/arch/i386/defconfig	Fri Apr 27 14:41:16 2001
+++ linux/arch/i386/defconfig	Tue May 22 10:53:06 2001
@@ -382,6 +382,7 @@
 CONFIG_EEPRO100=y
 # CONFIG_EEPRO100_PM is not set
 # CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
@@ -441,7 +442,6 @@
 # CONFIG_PCMCIA_XIRTULIP is not set
 CONFIG_NET_PCMCIA_RADIO=y
 CONFIG_PCMCIA_RAYCS=y
-# CONFIG_PCMCIA_HERMES is not set
 # CONFIG_PCMCIA_NETWAVE is not set
 # CONFIG_PCMCIA_WAVELAN is not set
 # CONFIG_AIRONET4500_CS is not set
@@ -573,6 +573,7 @@
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
@@ -676,6 +677,7 @@
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -700,6 +702,7 @@
 #
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_OV511 is not set
+# CONFIG_USB_PWC is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
 
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- v2.4.4/linux/arch/i386/kernel/bluesmoke.c	Wed Apr 11 19:02:27 2001
+++ linux/arch/i386/kernel/bluesmoke.c	Mon May 21 12:34:50 2001
@@ -1,16 +1,18 @@
-/*
- *	Machine Check Handler For PII/PIII
- */
 
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 
+/*
+ *	Machine Check Handler For PII/PIII
+ */
+
 static int banks;
 
-void do_machine_check(struct pt_regs * regs, long error_code)
+static void intel_machine_check(struct pt_regs * regs, long error_code)
 {
 	int recover=1;
 	u32 alow, ahigh, high, low;
@@ -62,28 +64,101 @@
 	wrmsr(0x17a,mcgstl, mcgsth);
 }
 
+/*
+ *	Machine check handler for Pentium class Intel
+ */
+ 
+static void pentium_machine_check(struct pt_regs * regs, long error_code)
+{
+	u32 loaddr, hi, lotype;
+	rdmsr(0x0, loaddr, hi);
+	rdmsr(0x1, 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());
+}
 
 /*
- *	This has to be run for each processor
+ *	Machine check handler for WinChip C6
+ */
+ 
+static void winchip_machine_check(struct pt_regs * regs, long error_code)
+{
+	printk(KERN_EMERG "CPU#%d: Machine Check Exception.\n", smp_processor_id());
+}
+
+/*
+ *	Handle unconfigured int18 (should never happen)
  */
+
+static void unexpected_machine_check(struct pt_regs * regs, long error_code)
+{	
+	printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
+}
+
+/*
+ *	Call the installed machine check handler for this CPU setup.
+ */ 
  
-void mcheck_init(struct cpuinfo_x86 *c)
+static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
+
+void do_machine_check(struct pt_regs * regs, long error_code)
+{
+	machine_check_vector(regs, error_code);
+}
+
+/*
+ *	Set up machine check reporting for Intel processors
+ */
+
+void __init intel_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
 	static int done;
-
-	if( c->x86_vendor != X86_VENDOR_INTEL )
-		return;
 	
+	/*
+	 *	Check for MCE support
+	 */
+
 	if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
+		return;	
+	
+	/*
+	 *	Pentium machine check
+	 */
+	
+	if(c->x86 == 5)
+	{
+		machine_check_vector = pentium_machine_check;
+		wmb();
+		/* Read registers before enabling */
+		rdmsr(0x0, l, h);
+		rdmsr(0x1, l, h);
+		if(done==0)
+			printk(KERN_INFO "Intel old style machine check architecture supported.\n");
+		/* Enable MCE */		
+		__asm__ __volatile__ (
+			"movl %%cr4, %%eax\n\t"
+			"orl $0x40, %%eax\n\t"
+			"movl %%eax, %%cr4\n\t" : : : "eax");
+		printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
 		return;
-		
+	}
+	
+
+	/*
+	 *	Check for PPro style MCA
+	 */
+	 		
 	if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
 		return;
 		
 	/* Ok machine check is available */
 	
+	machine_check_vector = intel_machine_check;
+	wmb();
+	
 	if(done==0)
 		printk(KERN_INFO "Intel machine check architecture supported.\n");
 	rdmsr(0x179, l, h);
@@ -98,10 +173,56 @@
 	{
 		wrmsr(0x401+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());
+	done=1;
+}
+
+/*
+ *	Set up machine check reporting on the Winchip C6 series
+ */
+ 
+static void winchip_mcheck_init(struct cpuinfo_x86 *c)
+{
+	u32 lo, hi;
+	/* Not supported on C3 */
+	if(c->x86 != 5)
+		return;
+	/* Winchip C6 */
+	machine_check_vector = winchip_machine_check;
+	wmb();
+	rdmsr(0x107, lo, hi);
+	lo|= (1<<2);	/* Enable EIERRINT (int 18 MCE) */
+	lo&= ~(1<<4);	/* Enable MCE */
+	wrmsr(0x107, lo, hi);
 	__asm__ __volatile__ (
 		"movl %%cr4, %%eax\n\t"
 		"orl $0x40, %%eax\n\t"
 		"movl %%eax, %%cr4\n\t" : : : "eax");
-	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
-	done=1;
+	printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+}
+
+
+/*
+ *	This has to be run for each processor
+ */
+
+void __init mcheck_init(struct cpuinfo_x86 *c)
+{
+	switch(c->x86_vendor)
+	{
+		case X86_VENDOR_AMD:
+			/*
+			 *	AMD K7 machine check is Intel like
+			 */
+			if(c->x86 == 6)
+				intel_mcheck_init(c);
+			break;
+		case X86_VENDOR_INTEL:
+			intel_mcheck_init(c);
+			break;
+		case X86_VENDOR_CENTAUR:
+			winchip_mcheck_init(c);
+			break;
+	}
 }
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.4.4/linux/arch/i386/kernel/i386_ksyms.c	Wed Apr 25 13:31:03 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Tue May 15 08:46:20 2001
@@ -112,6 +112,7 @@
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(pcibios_penalize_isa_irq);
+EXPORT_SYMBOL(pci_mem_start);
 #endif
 
 #ifdef CONFIG_X86_USE_3DNOW
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.4.4/linux/arch/i386/kernel/mtrr.c	Wed Apr 11 19:02:27 2001
+++ linux/arch/i386/kernel/mtrr.c	Thu May 24 15:14:08 2001
@@ -646,12 +646,32 @@
     unsigned long low;
 } centaur_mcr[8];
 
+static u8 centaur_mcr_reserved;
+static u8 centaur_mcr_type;		/* 0 for winchip, 1 for winchip2 */
+
+/*
+ *	Report boot time MCR setups 
+ */
+ 
+void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
+{
+	centaur_mcr[mcr].low = lo;
+	centaur_mcr[mcr].high = hi;
+}
+
 static void centaur_get_mcr (unsigned int reg, unsigned long *base,
 			     unsigned long *size, mtrr_type *type)
 {
     *base = centaur_mcr[reg].high >> PAGE_SHIFT;
     *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
     *type = MTRR_TYPE_WRCOMB;	/*  If it is there, it is write-combining  */
+    if(centaur_mcr_type==1 && ((centaur_mcr[reg].low&31)&2))
+    	*type = MTRR_TYPE_UNCACHABLE;
+    if(centaur_mcr_type==1 && (centaur_mcr[reg].low&31)==25)
+    	*type = MTRR_TYPE_WRBACK;
+    if(centaur_mcr_type==0 && (centaur_mcr[reg].low&31)==31)
+    	*type = MTRR_TYPE_WRBACK;
+    
 }   /*  End Function centaur_get_mcr  */
 
 static void (*get_mtrr) (unsigned int reg, unsigned long *base,
@@ -794,7 +814,15 @@
     else
     {
 	high = base << PAGE_SHIFT;
-	low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
+	if(centaur_mcr_type == 0)
+		low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
+	else
+	{
+		if(type == MTRR_TYPE_UNCACHABLE)
+			low = -size << PAGE_SHIFT | 0x02;	/* NC */
+		else
+			low = -size << PAGE_SHIFT | 0x09;	/* WWO,WC */
+	}
     }
     centaur_mcr[reg].high = high;
     centaur_mcr[reg].low = low;
@@ -1104,6 +1132,28 @@
     return -ENOSPC;
 }   /*  End Function generic_get_free_region  */
 
+static int centaur_get_free_region (unsigned long base, unsigned long size)
+/*  [SUMMARY] Get a free MTRR.
+    <base> The starting (base) address of the region.
+    <size> The size (in bytes) of the region.
+    [RETURNS] The index of the region on success, else -1 on error.
+*/
+{
+    int i, max;
+    mtrr_type ltype;
+    unsigned long lbase, lsize;
+
+    max = get_num_var_ranges ();
+    for (i = 0; i < max; ++i)
+    {
+    	if(centaur_mcr_reserved & (1<<i))
+    		continue;
+	(*get_mtrr) (i, &lbase, &lsize, &ltype);
+	if (lsize == 0) return i;
+    }
+    return -ENOSPC;
+}   /*  End Function generic_get_free_region  */
+
 static int cyrix_get_free_region (unsigned long base, unsigned long size)
 /*  [SUMMARY] Get a free ARR.
     <base> The starting (base) address of the region.
@@ -1164,9 +1214,9 @@
  *
  *	The available types are
  *
- *	%MTRR_TYPE_UNCACHEABLE	-	No caching
+ *	%MTRR_TYPE_UNCACHABLE	-	No caching
  *
- *	%MTRR_TYPE_WRITEBACK	-	Write data back in bursts whenever
+ *	%MTRR_TYPE_WRBACK	-	Write data back in bursts whenever
  *
  *	%MTRR_TYPE_WRCOMB	-	Write data back soon but allow bursts
  *
@@ -1229,9 +1279,13 @@
     case MTRR_IF_CENTAUR_MCR:
         if ( mtrr_if == MTRR_IF_CENTAUR_MCR )
 	{
-	    if (type != MTRR_TYPE_WRCOMB)
+	    /*
+	     *	FIXME: Winchip2 supports uncached
+	     */
+	    if (type != MTRR_TYPE_WRCOMB && (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE))
 	    {
-		printk (KERN_WARNING "mtrr: only write-combining is supported\n");
+		printk (KERN_WARNING "mtrr: only write-combining%s supported\n",
+			centaur_mcr_type?" and uncacheable are":" is");
 		return -EINVAL;
 	    }
 	}
@@ -1348,9 +1402,9 @@
  *
  *	The available types are
  *
- *	%MTRR_TYPE_UNCACHEABLE	-	No caching
+ *	%MTRR_TYPE_UNCACHABLE	-	No caching
  *
- *	%MTRR_TYPE_WRITEBACK	-	Write data back in bursts whenever
+ *	%MTRR_TYPE_WRBACK	-	Write data back in bursts whenever
  *
  *	%MTRR_TYPE_WRCOMB	-	Write data back soon but allow bursts
  *
@@ -1943,27 +1997,101 @@
     if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n");
 }   /*  End Function cyrix_arr_init  */
 
-static void __init centaur_mcr_init(void)
+/*
+ *	Initialise the later (saner) Winchip MCR variant. In this version
+ *	the BIOS can pass us the registers it has used (but not their values)
+ *	and the control register is read/write
+ */
+ 
+static void __init centaur_mcr1_init(void)
+{
+    unsigned i;
+    u32 lo, hi;
+
+    /* Unfortunately, MCR's are read-only, so there is no way to
+     * find out what the bios might have done.
+     */
+     
+    rdmsr(0x120, 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 */
+    }    
+    
+    centaur_mcr_type = 1;
+    
+    /*
+     *	Clear any unconfigured MCR's.
+     */
+
+    for (i = 0; i < 8; ++i)
+    {
+    	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
+    	{
+    		if(!(lo & (1<<(9+i))))
+			wrmsr (0x110 + i , 0, 0);
+		else
+			/*
+			 *	If the BIOS set up an MCR we cannot see it
+			 *	but we don't wish to obliterate it
+			 */
+			centaur_mcr_reserved |= (1<<i);
+	}
+    }
+    /*  
+     *	Throw the main write-combining switch... 
+     *	However if OOSTORE is enabled then people have already done far
+     *  cleverer things and we should behave. 
+     */
+
+    lo |= 15;			/* Write combine enables */
+    wrmsr(0x120, lo, hi);
+}   /*  End Function centaur_mcr1_init  */
+
+/*
+ *	Initialise the original winchip with read only MCR registers
+ *	no used bitmask for the BIOS to pass on and write only control
+ */
+ 
+static void __init centaur_mcr0_init(void)
 {
     unsigned i;
-    struct set_mtrr_context ctxt;
 
-    set_mtrr_prepare (&ctxt);
     /* Unfortunately, MCR's are read-only, so there is no way to
      * find out what the bios might have done.
      */
-    /* Clear all MCR's.
+     
+    /* Clear any unconfigured MCR's.
      * This way we are sure that the centaur_mcr array contains the actual
      * values. The disadvantage is that any BIOS tweaks are thus undone.
+     *
      */
     for (i = 0; i < 8; ++i)
     {
-        centaur_mcr[i].high = 0;
-	centaur_mcr[i].low = 0;
-	wrmsr (0x110 + i , 0, 0);
+    	if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
+		wrmsr (0x110 + i , 0, 0);
     }
-    /*  Throw the main write-combining switch...  */
-    wrmsr (0x120, 0x01f0001f, 0);
+
+    wrmsr(0x120, 0x01F0001F, 0);	/* Write only */
+}   /*  End Function centaur_mcr0_init  */
+
+/*
+ *	Initialise Winchip series MCR registers
+ */
+ 
+static void __init centaur_mcr_init(void)
+{
+    struct set_mtrr_context ctxt;
+
+    set_mtrr_prepare (&ctxt);
+
+    if(boot_cpu_data.x86_model==4)
+    	centaur_mcr0_init();
+    else if(boot_cpu_data.x86_model==8 || boot_cpu_data.x86_model == 9)
+    	centaur_mcr1_init();
+
     set_mtrr_done (&ctxt);
 }   /*  End Function centaur_mcr_init  */
 
@@ -2036,6 +2164,7 @@
 	mtrr_if = MTRR_IF_CENTAUR_MCR;
 	get_mtrr = centaur_get_mcr;
 	set_mtrr_up = centaur_set_mcr_up;
+	get_free_region = centaur_get_free_region;
 	centaur_mcr_init();
 	size_or_mask  = 0xfff00000; /* 32 bits */
 	size_and_mask = 0;
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c
--- v2.4.4/linux/arch/i386/kernel/pci-i386.c	Mon Aug  7 14:31:40 2000
+++ linux/arch/i386/kernel/pci-i386.c	Sat May 19 18:07:04 2001
@@ -350,3 +350,35 @@
 	printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	unsigned long prot;
+
+	/* I/O space cannot be accessed via normal processor loads and
+	 * stores on this platform.
+	 */
+	if (mmap_state == pci_mmap_io)
+		return -EINVAL;
+
+	/* Leave vm_pgoff as-is, the PCI space address is the physical
+	 * address on this platform.
+	 */
+	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
+
+	prot = pgprot_val(vma->vm_page_prot);
+	if (boot_cpu_data.x86 > 3)
+		prot |= _PAGE_PCD | _PAGE_PWT;
+	vma->vm_page_prot = __pgprot(prot);
+
+	/* Write-combine setting is ignored, it is changed via the mtrr
+	 * interfaces on this platform.
+	 */
+	if (remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
+			     vma->vm_end - vma->vm_start,
+			     vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- v2.4.4/linux/arch/i386/kernel/pci-irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/i386/kernel/pci-irq.c	Wed May 16 10:25:39 2001
@@ -105,7 +105,7 @@
 		 *  known (ascending bus order) and therefore pci_scan_bus returns immediately.
 		 */
 		if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
-			printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
+			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
 	pcibios_last_bus = -1;
 }
 
@@ -295,10 +295,10 @@
 		case 0x61:
 		case 0x6a:
 		case 0x7e:
-			printk("SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n");
+			printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n");
 			return 0;
 		default:			
-			printk("SiS router pirq escape (%d)\n", pirq);
+			printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
 			return 0;
 	}
 	return (x & 0x80) ? 0 : (x & 0x0f);
@@ -329,10 +329,10 @@
 		case 0x61:
 		case 0x6a:
 		case 0x7e:
-			printk("advanced SiS pirq mapping not yet implemented\n");
+			printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n");
 			return 0;
 		default:			
-			printk("SiS router pirq escape (%d)\n", pirq);
+			printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
 			return 0;
 	}
 	pci_write_config_byte(router, reg, x);
@@ -351,7 +351,7 @@
 static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
 	if (pirq > 8) {
-		printk("VLSI router pirq escape (%d)\n", pirq);
+		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
 		return 0;
 	}
 	return read_config_nybble(router, 0x74, pirq-1);
@@ -360,7 +360,7 @@
 static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
 	if (pirq > 8) {
-		printk("VLSI router pirq escape (%d)\n", pirq);
+		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
 		return 0;
 	}
 	write_config_nybble(router, 0x74, pirq-1, irq);
@@ -411,6 +411,7 @@
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX,   pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82820FW_0, pirq_piix_get, pirq_piix_set },
 
 	{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
 
@@ -439,13 +440,17 @@
 
 #ifdef CONFIG_PCI_BIOS
 	if (!rt->signature) {
-		printk("PCI: Using BIOS for IRQ routing\n");
+		printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
 		pirq_router = &pirq_bios_router;
 		return;
 	}
 #endif
+
+	DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
+	    rt->rtr_vendor, rt->rtr_device);
+
 	/* fall back to default router if nothing else found */
-	pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1;
+	pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1];
 
 	pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
 	if (!pirq_router_dev) {
@@ -464,7 +469,7 @@
 			pirq_router = r;
 		}
 	}
-	printk("PCI: Using IRQ router %s [%04x/%04x] at %s\n",
+	printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
 		pirq_router->name,
 		pirq_router_dev->vendor,
 		pirq_router_dev->device,
@@ -568,7 +573,7 @@
 		} else
 			return 0;
 	}
-	printk("PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name);
+	printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name);
 
 	/* Update IRQ for all devices with the same pirq value */
 	pci_for_each_dev(dev2) {
@@ -582,13 +587,13 @@
 		if (info->irq[pin].link == pirq) {
 			/* We refuse to override the dev->irq information. Give a warning! */
 		    	if (dev2->irq && dev2->irq != irq) {
-		    		printk("IRQ routing conflict in pirq table for device %s\n", dev2->slot_name);
+		    		printk(KERN_INFO "IRQ routing conflict in pirq table for device %s\n", dev2->slot_name);
 		    		continue;
 		    	}
 			dev2->irq = irq;
 			pirq_penalty[irq]++;
 			if (dev != dev2)
-				printk("PCI: The same IRQ used for device %s\n", dev2->slot_name);
+				printk(KERN_INFO "PCI: The same IRQ used for device %s\n", dev2->slot_name);
 		}
 	}
 	return 1;
@@ -667,7 +672,7 @@
 				}
 #endif
 				if (irq >= 0) {
-					printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
+					printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
 						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
 					dev->irq = irq;
 				}
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.4.4/linux/arch/i386/kernel/setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/i386/kernel/setup.c	Tue May 22 10:23:16 2001
@@ -127,6 +127,9 @@
 unsigned int BIOS_revision;
 unsigned int mca_pentium_flag;
 
+/* For PCI or other memory-mapped resources */
+unsigned long pci_mem_start = 0x10000000;
+
 /*
  * Setup options
  */
@@ -1009,6 +1012,9 @@
 	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
 		request_resource(&ioport_resource, standard_io_resources+i);
 
+	/* Tell the PCI layer not to allocate too close to the RAM area.. */
+	pci_mem_start = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;
+
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -1657,7 +1663,7 @@
 
 	/* Unhide possibly hidden capability flags
 	   The mp6 iDragon family don't have MSRs.
-	   We switch on extra features with this cpuid wierdness: */
+	   We switch on extra features with this cpuid weirdness: */
 	__asm__ (
 		"movl $0x6363452a, %%eax\n\t"
 		"movl $0x3231206c, %%ecx\n\t"
@@ -2268,7 +2274,7 @@
 
 	/* Now the feature flags better reflect actual CPU features! */
 
-	printk(KERN_DEBUG "CPU: After generic, caps: %08x %08x %08x %08x\n",
+	printk(KERN_DEBUG "CPU:     After generic, caps: %08x %08x %08x %08x\n",
 	       c->x86_capability[0],
 	       c->x86_capability[1],
 	       c->x86_capability[2],
@@ -2286,7 +2292,7 @@
 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
 	}
 
-	printk(KERN_DEBUG "CPU: Common caps: %08x %08x %08x %08x\n",
+	printk(KERN_DEBUG "CPU:             Common caps: %08x %08x %08x %08x\n",
 	       boot_cpu_data.x86_capability[0],
 	       boot_cpu_data.x86_capability[1],
 	       boot_cpu_data.x86_capability[2],
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.4.4/linux/arch/i386/kernel/traps.c	Mon Mar 19 18:23:40 2001
+++ linux/arch/i386/kernel/traps.c	Mon May  7 14:15:21 2001
@@ -973,7 +973,7 @@
 	set_trap_gate(11,&segment_not_present);
 	set_trap_gate(12,&stack_segment);
 	set_trap_gate(13,&general_protection);
-	set_trap_gate(14,&page_fault);
+	set_intr_gate(14,&page_fault);
 	set_trap_gate(15,&spurious_interrupt_bug);
 	set_trap_gate(16,&coprocessor_error);
 	set_trap_gate(17,&alignment_check);
diff -u --recursive --new-file v2.4.4/linux/arch/i386/lib/mmx.c linux/arch/i386/lib/mmx.c
--- v2.4.4/linux/arch/i386/lib/mmx.c	Wed Apr 11 19:02:27 2001
+++ linux/arch/i386/lib/mmx.c	Tue May 22 10:23:16 2001
@@ -163,7 +163,7 @@
 		".previous"
 		: : "r" (from) );
 
-	for(i=0; i<4096/64; i++)
+	for(i=0; i<(4096-320)/64; i++)
 	{
 		__asm__ __volatile__ (
 		"1: prefetch 320(%0)\n"
@@ -195,6 +195,29 @@
 		from+=64;
 		to+=64;
 	}
+	for(i=(4096-320)/64; i<4096/64; i++)
+	{
+		__asm__ __volatile__ (
+		"2: movq (%0), %%mm0\n"
+		"   movntq %%mm0, (%1)\n"
+		"   movq 8(%0), %%mm1\n"
+		"   movntq %%mm1, 8(%1)\n"
+		"   movq 16(%0), %%mm2\n"
+		"   movntq %%mm2, 16(%1)\n"
+		"   movq 24(%0), %%mm3\n"
+		"   movntq %%mm3, 24(%1)\n"
+		"   movq 32(%0), %%mm4\n"
+		"   movntq %%mm4, 32(%1)\n"
+		"   movq 40(%0), %%mm5\n"
+		"   movntq %%mm5, 40(%1)\n"
+		"   movq 48(%0), %%mm6\n"
+		"   movntq %%mm6, 48(%1)\n"
+		"   movq 56(%0), %%mm7\n"
+		"   movntq %%mm7, 56(%1)\n"
+		: : "r" (from), "r" (to) : "memory");
+		from+=64;
+		to+=64;
+	}
 	/* since movntq is weakly-ordered, a "sfence" is needed to become
 	 * ordered again.
 	 */
@@ -213,13 +236,8 @@
 static void fast_clear_page(void *page)
 {
 	int i;
-	if (!(current->flags & PF_USEDFPU))
-		clts();
-	else
-	{
-		__asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
-		current->flags &= ~PF_USEDFPU;
-	}
+	
+	kernel_fpu_begin();
 	
 	__asm__ __volatile__ (
 		"  pxor %%mm0, %%mm0\n" : :
@@ -247,19 +265,16 @@
 		: : "r" (page) : "memory");
 		page+=128;
 	}
-	stts();
+
+	kernel_fpu_end();
 }
 
 static void fast_copy_page(void *to, void *from)
 {
 	int i;
-	if (!(current->flags & PF_USEDFPU))
-		clts();
-	else
-	{
-		__asm__ __volatile__ ( " fnsave %0; fwait\n"::"m"(current->thread.i387));
-		current->flags &= ~PF_USEDFPU;
-	}
+	
+	
+	kernel_fpu_begin();
 
 	__asm__ __volatile__ (
 		"1: prefetch (%0)\n"
@@ -310,7 +325,7 @@
 		from+=64;
 		to+=64;
 	}
-	stts();
+	kernel_fpu_end();
 }
 
 
diff -u --recursive --new-file v2.4.4/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.4.4/linux/arch/i386/mm/fault.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/i386/mm/fault.c	Tue May 15 00:16:51 2001
@@ -117,6 +117,10 @@
 	/* get the address */
 	__asm__("movl %%cr2,%0":"=r" (address));
 
+	/* It's safe to allow irq's after cr2 has been saved */
+	if (regs->eflags & X86_EFLAGS_IF)
+		local_irq_enable();
+
 	tsk = current;
 
 	/*
@@ -127,8 +131,12 @@
 	 * be in an interrupt or a critical region, and should
 	 * only copy the information from the master page table,
 	 * nothing more.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * (error_code & 4) == 0, and that the fault was not a
+	 * protection error (error_code & 1) == 0.
 	 */
-	if (address >= TASK_SIZE)
+	if (address >= TASK_SIZE && !(error_code & 5))
 		goto vmalloc_fault;
 
 	mm = tsk->mm;
@@ -224,7 +232,6 @@
 bad_area:
 	up_read(&mm->mmap_sem);
 
-bad_area_nosemaphore:
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
 		tsk->thread.cr2 = address;
@@ -322,27 +329,32 @@
 		/*
 		 * Synchronize this task's top level page-table
 		 * with the 'reference' page table.
+		 *
+		 * Do _not_ use "tsk" here. We might be inside
+		 * an interrupt in the middle of a task switch..
 		 */
 		int offset = __pgd_offset(address);
 		pgd_t *pgd, *pgd_k;
 		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
 
-		pgd = tsk->active_mm->pgd + offset;
+		asm("movl %%cr3,%0":"=r" (pgd));
+		pgd = offset + (pgd_t *)__va(pgd);
 		pgd_k = init_mm.pgd + offset;
 
-		if (!pgd_present(*pgd)) {
-			if (!pgd_present(*pgd_k))
-				goto bad_area_nosemaphore;
-			set_pgd(pgd, *pgd_k);
-			return;
-		}
-
+		if (!pgd_present(*pgd_k))
+			goto no_context;
+		set_pgd(pgd, *pgd_k);
+		
 		pmd = pmd_offset(pgd, address);
 		pmd_k = pmd_offset(pgd_k, address);
-
-		if (pmd_present(*pmd) || !pmd_present(*pmd_k))
-			goto bad_area_nosemaphore;
+		if (!pmd_present(*pmd_k))
+			goto no_context;
 		set_pmd(pmd, *pmd_k);
+
+		pte_k = pte_offset(pmd_k, address);
+		if (!pte_present(*pte_k))
+			goto no_context;
 		return;
 	}
 }
diff -u --recursive --new-file v2.4.4/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.4.4/linux/arch/m68k/config.in	Tue Apr 17 17:19:25 2001
+++ linux/arch/m68k/config.in	Mon May 21 18:12:09 2001
@@ -192,7 +192,7 @@
       int  'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
    fi
    dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-   if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+   if [ "$CONFIG_CHR_DEV_ST" != "n" ]; then
       int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
    fi
    dep_tristate '  SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
diff -u --recursive --new-file v2.4.4/linux/arch/m68k/lib/semaphore.S linux/arch/m68k/lib/semaphore.S
--- v2.4.4/linux/arch/m68k/lib/semaphore.S	Wed Jan 26 12:44:20 2000
+++ linux/arch/m68k/lib/semaphore.S	Sat May 19 17:43:05 2001
@@ -51,49 +51,3 @@
 	moveml (%sp)+,%a0/%d0/%d1
 	rts
 
-ENTRY(__down_read_failed)
-	moveml %a0/%d0/%d1,-(%sp)
-	jcc 3f
-1:	movel %a1,-(%sp)
-	jbsr SYMBOL_NAME(down_read_failed_biased)
-	movel (%sp)+,%a1
-2:	moveml (%sp)+,%a0/%d0/%d1
-	rts
-
-3:	movel %a1,-(%sp)
-	jbsr SYMBOL_NAME(down_read_failed)
-	movel (%sp)+,%a1
-	subql #1,%a1@
-	jpl 2b
-	jcc 3b
-	jra 1b
-
-ENTRY(__down_write_failed)
-	moveml %a0/%d0/%d1,-(%sp)
-	jcc 3f
-1:	movel %a1,-(%sp)
-	jbsr SYMBOL_NAME(down_write_failed_biased)
-	movel (%sp)+,%a1
-2:	moveml (%sp)+,%a0/%d0/%d1
-	rts
-
-3:	movel %a1,-(%sp)
-	jbsr SYMBOL_NAME(down_write_failed)
-	movel (%sp)+,%a1
-	subl #RW_LOCK_BIAS,%a1@
-	jpl 2b
-	jcc 3b
-	jra 1b
-
-ENTRY(__rwsem_wake)
-	moveml %a0/%d0/%d1,-(%sp)
-	jeq 1f
-	movel %a1,-(%sp)
-	jbsr SYMBOL_NAME(rwsem_wake_readers)
-	jra 2f
-1:	movel %a1,-(%sp)
-	jbsr rwsem_wake_writer
-2:	movel (%sp)+,%a1
-	moveml (%sp)+,%a0/%d0/%d1
-	rts
-
diff -u --recursive --new-file v2.4.4/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.4.4/linux/arch/m68k/mm/memory.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/m68k/mm/memory.c	Sat May 19 17:43:05 2001
@@ -246,6 +246,10 @@
 		voff -= m68k_memory[i].size;
 	} while (++i < m68k_num_memory);
 
+	/* As a special case allow `__pa(high_memory)'.  */
+	if (voff == 0)
+		return m68k_memory[i-1].addr + m68k_memory[i-1].size;
+
 	return mm_vtop_fallback(vaddr);
 }
 #endif
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8260_io/Makefile linux/arch/ppc/8260_io/Makefile
--- v2.4.4/linux/arch/ppc/8260_io/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/8260_io/Makefile	Mon May 21 17:04:46 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:19 cort
+#
 #
 # Makefile for the linux MPC8xx ppc-specific parts of comm processor
 #
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8260_io/commproc.c linux/arch/ppc/8260_io/commproc.c
--- v2.4.4/linux/arch/ppc/8260_io/commproc.c	Sun Sep 17 09:48:05 2000
+++ linux/arch/ppc/8260_io/commproc.c	Mon May 21 17:04:46 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.commproc.c 1.5 05/17/01 18:14:19 cort
+ */
 
 /*
  * General Purpose functions for the global management of the
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8260_io/enet.c linux/arch/ppc/8260_io/enet.c
--- v2.4.4/linux/arch/ppc/8260_io/enet.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/8260_io/enet.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.enet.c 1.6 05/17/01 18:14:19 cort
+ */
+/*
  * Ethernet driver for Motorola MPC8260.
  * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
  * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8260_io/fcc_enet.c linux/arch/ppc/8260_io/fcc_enet.c
--- v2.4.4/linux/arch/ppc/8260_io/fcc_enet.c	Fri Feb 16 16:02:34 2001
+++ linux/arch/ppc/8260_io/fcc_enet.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.fcc_enet.c 1.7 05/17/01 18:14:20 cort
+ */
+/*
  * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
  * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8260_io/uart.c linux/arch/ppc/8260_io/uart.c
--- v2.4.4/linux/arch/ppc/8260_io/uart.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/8260_io/uart.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.uart.c 1.6 05/17/01 18:14:20 cort
+ */
+/*
  *  UART driver for MPC8260 CPM SCC or SMC
  *  Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
  *  Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/Config.in linux/arch/ppc/8xx_io/Config.in
--- v2.4.4/linux/arch/ppc/8xx_io/Config.in	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/Config.in	Wed May 16 09:57:20 2001
@@ -18,12 +18,12 @@
   fi
   bool 'Use Big CPM Ethernet Buffers' CONFIG_ENET_BIG_BUFFERS
 fi
-bool 'Use SMC2 for UART' CONFIG_8xxSMC2
-if [ "$CONFIG_8xxSMC2" = "y" ]; then
-  bool 'Use Alternate SMC2 I/O (823/850)' CONFIG_8xx_ALTSMC2
-  bool 'Use SMC2 for Console' CONFIG_8xx_CONS_SMC2
+bool 'Use SMC2 for UART' CONFIG_SMC2_UART
+if [ "$CONFIG_SMC2_UART" = "y" ]; then
+  bool 'Use Alternate SMC2 I/O (823/850)' CONFIG_ALTSMC2
+  bool 'Use SMC2 for Console' CONFIG_CONS_SMC2
 fi
-bool 'Enable SCC2 and SCC3 for UART' CONFIG_8xxSCC
+bool 'Enable SCC2 and SCC3 for UART' CONFIG_USE_SCC_IO
 
 # This doesn't really belong here, but it is convenient to ask
 # 8xx specific questions.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/Makefile linux/arch/ppc/8xx_io/Makefile
--- v2.4.4/linux/arch/ppc/8xx_io/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/8xx_io/Makefile	Mon May 21 17:04:46 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:20 cort
+#
 #
 # Makefile for the linux MPC8xx ppc-specific parts of comm processor
 #
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- v2.4.4/linux/arch/ppc/8xx_io/commproc.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/commproc.c	Mon May 21 17:04:46 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.commproc.c 1.8 05/18/01 07:54:04 patch
+ */
 
 /*
  * General Purpose functions for the global management of the
@@ -218,7 +221,7 @@
  * The internal baud rate clock is the system clock divided by 16.
  * This assumes the baudrate is 16x oversampled by the uart.
  */
-#define BRG_INT_CLK		(((bd_t *)__res)->bi_intfreq * 1000000)
+#define BRG_INT_CLK		(((bd_t *)__res)->bi_intfreq)
 #define BRG_UART_CLK		(BRG_INT_CLK/16)
 #define BRG_UART_CLK_DIV16	(BRG_UART_CLK/16)
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h
--- v2.4.4/linux/arch/ppc/8xx_io/commproc.h	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/commproc.h	Mon May 21 17:04:46 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.commproc.h 1.8 05/17/01 18:14:20 cort
+ */
 
 /*
  * MPC8xx Communication Processor Module.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.4.4/linux/arch/ppc/8xx_io/enet.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/enet.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.enet.c 1.10 05/17/01 18:14:20 cort
+ */
+/*
  * Ethernet driver for Motorola MPC8xx.
  * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- v2.4.4/linux/arch/ppc/8xx_io/fec.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/fec.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.fec.c 1.12 05/18/01 07:54:04 patch
+ */
+/*
  * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
  * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
  *
@@ -1686,10 +1689,7 @@
 	/* Set MII speed to 2.5 MHz
 	*/
 	fecp->fec_mii_speed = fep->phy_speed =
-		(
-		  ( ((bd->bi_intfreq * 1000000) + 500000) / 2500000 / 2 )
-		  & 0x3F
-		) << 1;
+		(( (bd->bi_intfreq + 500000) / 2500000 / 2 ) & 0x3F ) << 1;
 #else
 	fecp->fec_mii_speed = 0;	/* turn off MDIO */
 #endif	/* CONFIG_USE_MDIO */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.4.4/linux/arch/ppc/8xx_io/uart.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/uart.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.uart.c 1.10 05/17/01 18:14:20 cort
+ */
+/*
  *  UART driver for MPC860 CPM SCC or SMC
  *  Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
  *
@@ -55,17 +58,17 @@
 */
 # ifndef CONFIG_SERIAL_CONSOLE_PORT
 #  ifdef CONFIG_SCC3_ENET
-#   ifdef CONFIG_8xx_CONS_SMC2
+#   ifdef CONFIG_CONS_SMC2
 #    define CONFIG_SERIAL_CONSOLE_PORT	0	/* Console on SMC2 is 1st port */
 #   else
 #    error "Can't use SMC1 for console with Ethernet on SCC3"
 #   endif
 #  else	/* ! CONFIG_SCC3_ENET */
-#   ifdef CONFIG_8xx_CONS_SMC2			/* Console on SMC2 */
+#   ifdef CONFIG_CONS_SMC2			/* Console on SMC2 */
 #    define CONFIG_SERIAL_CONSOLE_PORT	1
 #   else					/* Console on SMC1 */
 #    define CONFIG_SERIAL_CONSOLE_PORT	0
-#   endif /* CONFIG_8xx_CONS_SMC2 */
+#   endif /* CONFIG_CONS_SMC2 */
 #  endif  /* CONFIG_SCC3_ENET */
 # endif	  /* CONFIG_SERIAL_CONSOLE_PORT */
 #endif	  /* CONFIG_SERIAL_CONSOLE */
@@ -134,15 +137,15 @@
   	{ 0,     0, PROFF_SMC1, CPMVEC_SMC1,   0,    0 },    /* SMC1 ttyS0 */
 #endif
 #if !defined(CONFIG_USB_MPC8xx) && !defined(CONFIG_USB_CLIENT_MPC8xx)
-# ifdef CONFIG_8xxSMC2
+# ifdef CONFIG_SMC2_UART
   	{ 0,     0, PROFF_SMC2, CPMVEC_SMC2,   0,    1 },    /* SMC2 ttyS1 */
 # endif
-# ifdef CONFIG_8xxSCC
+# ifdef CONFIG_USE_SCC_IO
   	{ 0,     0, PROFF_SCC2, CPMVEC_SCC2,   0,    (NUM_IS_SCC | 1) },    /* SCC2 ttyS2 */
   	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    (NUM_IS_SCC | 2) },    /* SCC3 ttyS3 */
 # endif
   #else /* CONFIG_USB_xxx */
-# ifdef CONFIG_8xxSCC
+# ifdef CONFIG_USE_SCC_IO
   	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    (NUM_IS_SCC | 2) },    /* SCC3 ttyS3 */
 # endif
 #endif	/* CONFIG_USB_xxx */
@@ -2533,7 +2536,7 @@
 
 	/* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O.
 	 */
-#ifdef CONFIG_8xxSCC
+#ifdef CONFIG_USE_SCC_IO
 #ifndef CONFIG_MBX
 	/* The "standard" configuration through the 860.
 	*/
@@ -2747,7 +2750,7 @@
 				 * parallel I/O.  On 823/850 these are on
 				 * port A for SMC2.
 				 */
-#ifndef CONFIG_8xx_ALTSMC2
+#ifndef CONFIG_ALTSMC2
 				iobits = 0xc0 << (idx * 4);
 				cp->cp_pbpar |= iobits;
 				cp->cp_pbdir &= ~iobits;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.4.4/linux/arch/ppc/Makefile	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/Makefile	Thu May 24 15:02:06 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.13 05/21/01 00:48:24 cort
+#
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
 # for "archclean" and "archdep" for cleaning up and making dependencies for
@@ -31,7 +33,7 @@
 endif
 
 ifdef CONFIG_8xx
-CFLAGS := $(CFLAGS) -mcpu=860 -I../8xx_io
+CFLAGS := $(CFLAGS) -mcpu=860
 endif
 
 ifdef CONFIG_PPC64BRIDGE
@@ -65,10 +67,6 @@
 endif
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-MAKECOFFBOOT = $(MAKE) -C arch/$(ARCH)/coffboot
-MAKECHRPBOOT = $(MAKE) -C arch/$(ARCH)/chrpboot
-MAKEMBXBOOT = $(MAKE) -C arch/$(ARCH)/mbxboot
-MAKETREEBOOT = $(MAKE) -C arch/$(ARCH)/treeboot
 
 ifdef CONFIG_8xx
 SUBDIRS += arch/ppc/8xx_io
@@ -89,108 +87,20 @@
 checks:
 	@$(MAKE) -C arch/$(ARCH)/kernel checks
 
-BOOT_TARGETS = zImage znetboot.initrd zImage.initrd
-
-ifdef CONFIG_4xx
-$(BOOT_TARGETS): $(CHECKS) vmlinux
-	@$(MAKETREEBOOT) $@
-endif
-
-ifdef CONFIG_8xx
-$(BOOT_TARGETS): $(CHECKS) vmlinux
-	@$(MAKECOFFBOOT) $@
-	@$(MAKEMBXBOOT) $@
-endif
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
 
-ifdef CONFIG_6xx
-ifndef CONFIG_8260
 $(BOOT_TARGETS): $(CHECKS) vmlinux
-	@$(MAKECOFFBOOT) $@
 	@$(MAKEBOOT) $@
-	@$(MAKECHRPBOOT) $@
 
-znetboot: $(CHECKS) vmlinux
-ifdef CONFIG_ALL_PPC
-ifdef CONFIG_SMP
-	cp -f vmlinux /tftpboot/vmlinux.smp
-else
-	cp -f vmlinux /tftpboot/vmlinux
-endif
-endif
-	@$(MAKECOFFBOOT) $@
-	@$(MAKEBOOT) $@
-	@$(MAKECHRPBOOT) $@
-else
-# 8260 is custom 6xx
-$(BOOT_TARGETS): $(CHECKS) vmlinux
-	@$(MAKECOFFBOOT) $@
-	@$(MAKEMBXBOOT) $@
-endif
-endif
-
-ifdef CONFIG_PPC64BRIDGE
-$(BOOT_TARGETS): $(CHECKS) vmlinux
-	@$(MAKECOFFBOOT) $@
-	@$(MAKEBOOT) $@
-	@$(MAKECHRPBOOT) $@
-
-znetboot: $(CHECKS) vmlinux
-	cp -f vmlinux /tftpboot/vmlinux.64
-	@$(MAKECOFFBOOT) $@
-	@$(MAKEBOOT) $@
-	@$(MAKECHRPBOOT) $@
-endif
-
-.PHONY: clean_config
-clean_config:
+%_config: arch/ppc/configs/%_defconfig
 	rm -f .config arch/ppc/defconfig
-
-pmac_config: clean_config
-	cp -f arch/ppc/configs/pmac_defconfig arch/ppc/defconfig
-
-prep_config: clean_config
-	cp -f arch/ppc/configs/prep_defconfig arch/ppc/defconfig
-
-chrp_config: clean_config
-	cp -f arch/ppc/configs/chrp_defconfig arch/ppc/defconfig
-
-common_config: clean_config
-	cp -f arch/ppc/configs/common_defconfig arch/ppc/defconfig
-
-mbx_config: clean_config
-	cp -f arch/ppc/configs/mbx_defconfig arch/ppc/defconfig
-
-apus_config: clean_config
-	cp -f arch/ppc/configs/apus_defconfig arch/ppc/defconfig
-
-oak_config: clean_config
-	cp -f arch/ppc/configs/oak_defconfig arch/ppc/defconfig
-
-walnut_config: clean_config
-	cp -f arch/ppc/configs/walnut_defconfig arch/ppc/defconfig
-
-rpxlite_config: clean_config
-	cp -f arch/ppc/configs/rpxlite_defconfig arch/ppc/defconfig
-
-rpxcllf_config: clean_config
-	cp -f arch/ppc/configs/rpxcllf_defconfig arch/ppc/defconfig
-
-bseip_config: clean_config
-	cp -f arch/ppc/configs/bseip_defconfig arch/ppc/defconfig
-
-est8260_config: clean_config
-	cp -f arch/ppc/configs/est8260_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/$(@:config=defconfig) arch/ppc/defconfig
 
 archclean:
 	rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks}
-	@$(MAKECOFFBOOT) clean
 	@$(MAKEBOOT) clean
-	@$(MAKECHRPBOOT) clean
-	@$(MAKEMBXBOOT) clean
-	@$(MAKETREEBOOT) clean
 
 archmrproper:
 
 archdep:
-	$(MAKEBOOT) fastdep
-	$(MAKECHRPBOOT) fastdep
+	$(MAKEBOOT) dep
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/Makefile linux/arch/ppc/amiga/Makefile
--- v2.4.4/linux/arch/ppc/amiga/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/amiga/Makefile	Mon May 21 17:04:46 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.5 05/21/01 00:48:24 cort
+#
 #
 # Makefile for Linux arch/m68k/amiga source directory
 #
@@ -14,6 +16,6 @@
 obj-y		:= config.o amiints.o cia.o time.o bootinfo.o amisound.o \
 			chipram.o amiga_ksyms.o
 
-obj-$(CONFIG_AMIGA_PCMCIA) += pcmia.o
+obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/amiga_ksyms.c linux/arch/ppc/amiga/amiga_ksyms.c
--- v2.4.4/linux/arch/ppc/amiga/amiga_ksyms.c	Tue Aug  4 16:06:36 1998
+++ linux/arch/ppc/amiga/amiga_ksyms.c	Mon May 21 17:04:46 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.amiga_ksyms.c 1.5 05/17/01 18:14:20 cort
+ */
 #include "../../m68k/amiga/amiga_ksyms.c"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.4.4/linux/arch/ppc/amiga/amiints.c	Fri Feb 16 16:02:34 2001
+++ linux/arch/ppc/amiga/amiints.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.amiints.c 1.8 05/21/01 00:48:24 cort
+ */
+/*
  * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -255,9 +258,10 @@
 		return;
 	}
 
-	if (irq >= IRQ_AMIGA_AUTO)
+	if (irq >= IRQ_AMIGA_AUTO) {
 		sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
-
+		return;
+	}
 	if (irq >= IRQ_AMIGA_CIAA) {
 		cia_free_irq(irq, dev_id);
 		return;
@@ -295,7 +299,10 @@
 		return;
 	}
 
-	if (--ami_ablecount[irq])
+	ami_ablecount[irq]--;
+	if (ami_ablecount[irq]<0)
+		ami_ablecount[irq]=0;
+	else if (ami_ablecount[irq])
 		return;
 
 	/* No action for auto-vector interrupts */
@@ -347,64 +354,16 @@
 	ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
 }
 
-void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
+void amiga_do_irq_list(int irq, struct pt_regs *fp)
 {
-	irq_node_t *node, *slow_nodes;
-	unsigned short intena;
-	unsigned long flags;
+	irq_node_t *node;
 
 	kstat.irqs[0][SYS_IRQS + irq]++;
-	if (server->count++)
-		server->reentrance = 1;
-
-	intena = ami_intena_vals[irq];
-	custom.intreq = intena;
 
-	/* serve first fast handlers - there can only be one of these */
-	node = ami_irq_list[irq];
-
-	/*
-	 * Timer interrupts show up like this
-	 */
-	if (!node) {
-		server->count--;
-		return;
-	}
+	custom.intreq = ami_intena_vals[irq];
 
-	if (node && (node->flags & SA_INTERRUPT)) {
-		save_flags(flags);
-		cli();
+	for (node = ami_irq_list[irq]; node; node = node->next)
 		node->handler(irq, node->dev_id, fp);
-		restore_flags(flags);
-
-		server->count--;
-		return;
-	}
-
-	/*
-	 * Disable the interrupt source in question and reenable all
-	 * other interrupts. No interrupt handler should ever touch
-	 * the intena flags directly!
-	 */
-	custom.intena = intena;
-	save_flags(flags);
-	sti();
-
-	slow_nodes = node;
-	for (;;) {
-		for (; node; node = node->next)
-			node->handler(irq, node->dev_id, fp);
-
-		if (!server->reentrance) {
-			server->count--;
-			restore_flags(flags);
-			custom.intena = IF_SETCLR | intena;
-			return;
-		}
-
-		server->reentrance = 0;
-		node = slow_nodes;
-	}
 }
 
 /*
@@ -437,7 +396,6 @@
 static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
 {
 	unsigned short ints = custom.intreqr & custom.intenar;
-	static struct irq_server server = {0, 0};
 
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
@@ -453,7 +411,7 @@
 
 	/* if a vertical blank interrupt */
 	if (ints & IF_VERTB)
-		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
 }
 
 static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
@@ -512,7 +470,7 @@
    and executes them in a loop. Having ami_badint at the end of the chain
    is a bad idea. */
 void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	NULL, ami_int1, NULL, NULL /* FB expects to replace ami_int3*/,
+	NULL, ami_int1, NULL, ami_int3,
 	ami_int4, ami_int5, NULL, ami_int7
 };
 #else
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/amisound.c linux/arch/ppc/amiga/amisound.c
--- v2.4.4/linux/arch/ppc/amiga/amisound.c	Tue Aug  4 16:06:36 1998
+++ linux/arch/ppc/amiga/amisound.c	Mon May 21 17:04:46 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.amisound.c 1.5 05/17/01 18:14:20 cort
+ */
 #include "../../m68k/amiga/amisound.c"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/bootinfo.c linux/arch/ppc/amiga/bootinfo.c
--- v2.4.4/linux/arch/ppc/amiga/bootinfo.c	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/amiga/bootinfo.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.bootinfo.c 1.5 05/17/01 18:14:20 cort
+ */
+/*
  *  linux/arch/ppc/amiga/bootinfo.c
  *
  *  Extracted from arch/m68k/kernel/setup.c.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/chipram.c linux/arch/ppc/amiga/chipram.c
--- v2.4.4/linux/arch/ppc/amiga/chipram.c	Tue Jul 11 11:18:53 2000
+++ linux/arch/ppc/amiga/chipram.c	Mon May 21 17:04:46 2001
@@ -1,183 +1,4 @@
 /*
-**  linux/amiga/chipram.c
-**
-**      Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
-**          - 64-bit aligned allocations for full AGA compatibility
-*/
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/zorro.h>
-#include <asm/amigahw.h>
-
-struct chip_desc {
-	unsigned first   :  1;
-	unsigned last    :  1;
-	unsigned alloced :  1;
-	unsigned length  : 24;
-	long pad;					/* We suppose this makes this struct 64 bits long!! */
-};
-
-#define DP(ptr) ((struct chip_desc *)(ptr))
-
-u_long amiga_chip_size;
-static unsigned long chipavail;
-
-static struct resource chipram = { "Chip RAM", 0 };
-
-unsigned long amiga_chip_avail( void )
-{
-#ifdef DEBUG
-	printk("chip_avail : %ld bytes\n",chipavail);
-#endif
-	return chipavail;
-}
-
-
-void __init amiga_chip_init (void)
-{
-  struct chip_desc *dp;
-
-  if (!AMIGAHW_PRESENT(CHIP_RAM))
-    return;
-
-#ifndef CONFIG_APUS_FAST_EXCEPT
-  /*
-   * Remove the first 4 pages where PPC exception handlers will
-   * be located.
-   */
-  amiga_chip_size -= 0x4000;
-#endif
-  chipram.end = amiga_chip_size-1;
-  request_resource(&iomem_resource, &chipram);
-
-  /* initialize start boundary */
-
-  dp = DP(chipaddr);
-  dp->first = 1;
-
-  dp->alloced = 0;
-  dp->length = amiga_chip_size - 2*sizeof(*dp);
-
-  /* initialize end boundary */
-  dp = DP(chipaddr + amiga_chip_size) - 1;
-  dp->last = 1;
-  
-  dp->alloced = 0;
-  dp->length = amiga_chip_size - 2*sizeof(*dp);
-  chipavail = dp->length;  /*MILAN*/
-
-#ifdef DEBUG
-  printk ("chipram end boundary is %p, length is %d\n", dp,
-	  dp->length);
-#endif
-}
-
-void *amiga_chip_alloc(long size, const char *name)
-{
-	/* last chunk */
-	struct chip_desc *dp;
-	void *ptr;
-
-	/* round off */
-	size = (size + 7) & ~7;
-
-#ifdef DEBUG
-   printk("amiga_chip_alloc: allocate %ld bytes\n", size);
-#endif
-
-	/*
-	 * get pointer to descriptor for last chunk by 
-	 * going backwards from end chunk
-	 */
-	dp = DP(chipaddr + amiga_chip_size) - 1;
-	dp = DP((unsigned long)dp - dp->length) - 1;
-	
-	while ((dp->alloced || dp->length < size)
-	       && !dp->first)
-		dp = DP ((unsigned long)dp - dp[-1].length) - 2;
-
-	if (dp->alloced || dp->length < size) {
-		printk ("no chipmem available for %ld allocation\n", size);
-		return NULL;
-	}
-
-	if (dp->length < (size + 2*sizeof(*dp))) {
-		/* length too small to split; allocate the whole thing */
-		dp->alloced = 1;
-		ptr = (void *)(dp+1);
-		dp = DP((unsigned long)ptr + dp->length);
-		dp->alloced = 1;
-#ifdef DEBUG
-		printk ("amiga_chip_alloc: no split\n");
-#endif
-	} else {
-		/* split the extent; use the end part */
-		long newsize = dp->length - (2*sizeof(*dp) + size);
-
-#ifdef DEBUG
-		printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length,
-			newsize);
-#endif
-		dp->length = newsize;
-		dp = DP((unsigned long)(dp+1) + newsize);
-		dp->first = dp->last = 0;
-		dp->alloced = 0;
-		dp->length = newsize;
-		dp++;
-		dp->first = dp->last = 0;
-		dp->alloced = 1;
-		dp->length = size;
-		ptr = (void *)(dp+1);
-		dp = DP((unsigned long)ptr + size);
-		dp->alloced = 1;
-		dp->length = size;
-	}
-
-#ifdef DEBUG
-	printk ("amiga_chip_alloc: returning %p\n", ptr);
-#endif
-
-	if ((unsigned long)ptr & 7)
-		panic("amiga_chip_alloc: alignment violation\n");
-
-    chipavail -= size + (2*sizeof(*dp)); /*MILAN*/
-
-    if (!request_mem_region(ZTWO_PADDR(ptr), size, name))
-	printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx "
-	       "is busy\n", size, ZTWO_PADDR(ptr));
-
-    return ptr;
-}
-
-void amiga_chip_free (void *ptr)
-{
-	struct chip_desc *sdp = DP(ptr) - 1, *dp2;
-	struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
-
-    chipavail += sdp->length + (2* sizeof(sdp)); /*MILAN*/
-#ifdef DEBUG
-   printk("chip_free: free %ld bytes at %p\n",sdp->length,ptr);
-#endif
-	/* deallocate the chunk */
-	sdp->alloced = edp->alloced = 0;
-	release_mem_region(ZTWO_PADDR(ptr), sdp->length);
-
-	/* check if we should merge with the previous chunk */
-	if (!sdp->first && !sdp[-1].alloced) {
-		dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
-		dp2->length += sdp->length + 2*sizeof(*sdp);
-		edp->length = dp2->length;
-		sdp = dp2;
-	}
-
-	/* check if we should merge with the following chunk */
-	if (!edp->last && !edp[1].alloced) {
-		dp2 = DP((unsigned long)edp + edp[1].length) + 2;
-		dp2->length += edp->length + 2*sizeof(*sdp);
-		sdp->length = dp2->length;
-		edp = dp2;
-	}
-}
+ * BK Id: SCCS/s.chipram.c 1.7 05/21/01 00:49:49 cort
+ */
+#include "../../m68k/amiga/chipram.c"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/cia.c linux/arch/ppc/amiga/cia.c
--- v2.4.4/linux/arch/ppc/amiga/cia.c	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/amiga/cia.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.cia.c 1.7 05/21/01 00:48:24 cort
+ */
+/*
  *  linux/arch/m68k/amiga/cia.c - CIA support
  *
  *  Copyright (C) 1996 Roman Zippel
@@ -27,18 +30,17 @@
 	u_short int_mask;
 	int handler_irq, cia_irq, server_irq;
 	char *name;
-	struct irq_server server;
 	irq_handler_t irq_list[CIA_IRQS];
 } ciaa_base = {
 	&ciaa, 0, 0, IF_PORTS,
 	IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
 	IRQ_AMIGA_PORTS,
-	"CIAA handler", {0, 0}
+	"CIAA handler"
 }, ciab_base = {
 	&ciab, 0, 0, IF_EXTER,
 	IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
 	IRQ_AMIGA_EXTER,
-	"CIAB handler", {0, 0}
+	"CIAB handler"
 };
 
 #define CIA_SET_BASE_ADJUST_IRQ(base, irq)	\
@@ -197,7 +199,7 @@
 		}
 		ints >>= 1;
 	}
-	amiga_do_irq_list(base->server_irq, fp, &base->server);
+	amiga_do_irq_list(base->server_irq, fp);
 }
 
 void __init cia_init_IRQ(struct ciabase *base)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c
--- v2.4.4/linux/arch/ppc/amiga/config.c	Mon Nov 27 17:57:34 2000
+++ linux/arch/ppc/amiga/config.c	Mon May 21 17:04:46 2001
@@ -1,12 +1,8 @@
+/*
+ * BK Id: SCCS/s.config.c 1.7 05/21/01 00:48:24 cort
+ */
 #define m68k_debug_device debug_device
 
-#include <linux/init.h>
-
-/* machine dependent "kbd-reset" setup function */
-void (*mach_kbd_reset_setup) (char *, int) __initdata = 0;
-
-#include <asm/io.h>
-
 /*
  *  linux/arch/m68k/amiga/config.c
  *
@@ -28,6 +24,10 @@
 #include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/init.h>
+#ifdef CONFIG_ZORRO
+#include <linux/zorro.h>
+#endif
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
@@ -36,10 +36,12 @@
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/irq.h>
+#include <asm/keyboard.h>
 #include <asm/machdep.h>
-#include <linux/zorro.h>
+#include <asm/io.h>
 
 unsigned long powerup_PCI_present;
+unsigned long powerup_BPPCPLUS_present;
 unsigned long amiga_model;
 unsigned long amiga_eclock;
 unsigned long amiga_masterclock;
@@ -121,7 +123,7 @@
 };
 
 #ifdef CONFIG_MAGIC_SYSRQ
-static char amiga_sysrq_xlate[128] =
+char amiga_sysrq_xlate[128] =
 	"\0001234567890-=\\\000\000"					/* 0x00 - 0x0f */
 	"qwertyuiop[]\000123"							/* 0x10 - 0x1f */
 	"asdfghjkl;'\000\000456"						/* 0x20 - 0x2f */
@@ -139,16 +141,18 @@
      *  Motherboard Resources present in all Amiga models
      */
 
-static struct resource mb_res[] = {
-    { "Ranger Memory", 0x00c00000, 0x00c7ffff },
-    { "CIA B", 0x00bfd000, 0x00bfdfff },
-    { "CIA A", 0x00bfe000, 0x00bfefff },
-    { "Custom I/O", 0x00dff000, 0x00dfffff },
-    { "Kickstart ROM", 0x00f80000, 0x00ffffff }
+static struct {
+    struct resource _ciab, _ciaa, _custom, _kickstart;
+} mb_resources = {
+//    { "Ranger Memory", 0x00c00000, 0x00c7ffff },
+    _ciab:	{ "CIA B", 0x00bfd000, 0x00bfdfff },
+    _ciaa:	{ "CIA A", 0x00bfe000, 0x00bfefff },
+    _custom:	{ "Custom I/O", 0x00dff000, 0x00dfffff },
+    _kickstart:	{ "Kickstart ROM", 0x00f80000, 0x00ffffff }
 };
 
 static struct resource rtc_resource = {
-    "A2000 RTC", 0x00dc0000, 0x00dcffff
+    NULL, 0x00dc0000, 0x00dcffff
 };
 
 static struct resource ram_resource[NUM_MEMINFO];
@@ -194,6 +198,7 @@
 	    break;
 
 	case BI_AMIGA_AUTOCON:
+#ifdef CONFIG_ZORRO
 	    if (zorro_num_autocon < ZORRO_NUM_AUTO) {
 		const struct ConfigDev *cd = (struct ConfigDev *)data;
 		struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
@@ -204,12 +209,21 @@
 		dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
 	    } else
 		printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+#endif /* CONFIG_ZORRO */
 	    break;
 
 	case BI_AMIGA_SERPER:
 	    /* serial port period: ignored here */
 	    break;
 
+	case BI_AMIGA_PUP_BRIDGE:
+	    powerup_PCI_present = *(const unsigned short *)data;
+	    break;
+
+	case BI_AMIGA_BPPC_SCSI:
+	    powerup_BPPCPLUS_present = *(const unsigned short *)data;
+	    break;
+
 	default:
 	    unknown = 1;
     }
@@ -392,11 +406,8 @@
 
   /* Some APUS boxes may have PCI memory, but ... */
   iomem_resource.name = "Memory";
-  request_resource(&iomem_resource, &ranger_resource);
-  request_resource(&iomem_resource, &ciab_resource);
-  request_resource(&iomem_resource, &ciaa_resource);
-  request_resource(&iomem_resource, &custom_chips_resource);
-  request_resource(&iomem_resource, &kickstart_resource);
+  for (i = 0; i < 4; i++)
+    request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
 
   mach_sched_init      = amiga_sched_init;
   mach_keyb_init       = amiga_keyb_init;
@@ -415,11 +426,12 @@
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
     mach_gettod  = a3000_gettod;
-    rtc_resource.name[1] = '3';
+    rtc_resource.name = "A3000 RTC";
     request_resource(&iomem_resource, &rtc_resource);
   }
   else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
     mach_gettod  = a2000_gettod;
+    rtc_resource.name = "A2000 RTC";
     request_resource(&iomem_resource, &rtc_resource);
   }
 
@@ -439,14 +451,10 @@
   mach_floppy_setup    = amiga_floppy_setup;
 #endif
   mach_reset           = amiga_reset;
+#ifdef CONFIG_DUMMY_CONSOLE
   conswitchp           = &dummy_con;
-  kd_mksound           = amiga_mksound;
-#ifdef CONFIG_MAGIC_SYSRQ
-  mach_sysrq_key = 0x5f;	     /* HELP */
-  mach_sysrq_shift_state = 0x03; /* SHIFT+ALTGR */
-  mach_sysrq_shift_mask = 0xff;  /* all modifiers except CapsLock */
-  mach_sysrq_xlate = amiga_sysrq_xlate;
 #endif
+  kd_mksound           = amiga_mksound;
 #ifdef CONFIG_HEARTBEAT
   mach_heartbeat = amiga_heartbeat;
 #endif
@@ -500,11 +508,14 @@
 static unsigned short jiffy_ticks;
 
 static void __init amiga_sched_init(void (*timer_routine)(int, void *,
-					struct pt_regs *))
+							  struct pt_regs *))
 {
+	static struct resource sched_res = {
+	    "timer", 0x00bfd400, 0x00bfd5ff,
+	};
 	jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
 
-	if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer"))
+	if (request_resource(&mb_resources._ciab, &sched_res))
 	    printk("Cannot allocate ciab.ta{lo,hi}\n");
 	ciab.cra &= 0xC0;   /* turn off timer A, continuous mode, from Eclk */
 	ciab.talo = jiffy_ticks % 256;
@@ -612,6 +623,8 @@
 			t->wday = tod->weekday;
 			t->mon  = tod->month1  * 10 + tod->month2 - 1;
 			t->year = tod->year1   * 10 + tod->year2;
+			if (t->year <= 69)
+				t->year += 100;
 		} else {
 			tod->second1 = t->sec / 10;
 			tod->second2 = t->sec % 10;
@@ -625,6 +638,8 @@
 				tod->weekday = t->wday;
 			tod->month1  = (t->mon + 1) / 10;
 			tod->month2  = (t->mon + 1) % 10;
+			if (t->year >= 100)
+				t->year -= 100;
 			tod->year1   = t->year / 10;
 			tod->year2   = t->year % 10;
 		}
@@ -646,6 +661,8 @@
 			t->wday = tod->weekday;
 			t->mon  = tod->month1      * 10 + tod->month2 - 1;
 			t->year = tod->year1       * 10 + tod->year2;
+			if (t->year <= 69)
+				t->year += 100;
 
 			if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
 				if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12)
@@ -672,6 +689,8 @@
 				tod->weekday = t->wday;
 			tod->month1  = (t->mon + 1) / 10;
 			tod->month2  = (t->mon + 1) % 10;
+			if (t->year >= 100)
+				t->year -= 100;
 			tod->year1   = t->year / 10;
 			tod->year2   = t->year % 10;
 		}
@@ -796,7 +815,9 @@
 
 static void amiga_savekmsg_init(void)
 {
-    savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug");
+    static struct resource debug_res = { "Debug" };
+
+    savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
     savekmsg->magic1 = SAVEKMSG_MAGIC1;
     savekmsg->magic2 = SAVEKMSG_MAGIC2;
     savekmsg->magicptr = virt_to_phys(savekmsg);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/ints.c linux/arch/ppc/amiga/ints.c
--- v2.4.4/linux/arch/ppc/amiga/ints.c	Fri Nov 12 04:29:47 1999
+++ linux/arch/ppc/amiga/ints.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ints.c 1.5 05/17/01 18:14:20 cort
+ */
+/*
  *  linux/arch/ppc/amiga/ints.c
  *
  *  Linux/m68k general interrupt handling code from arch/m68k/kernel/ints.c
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/pcmcia.c linux/arch/ppc/amiga/pcmcia.c
--- v2.4.4/linux/arch/ppc/amiga/pcmcia.c	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/amiga/pcmcia.c	Mon May 21 17:04:46 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.pcmcia.c 1.5 05/17/01 18:14:20 cort
+ */
 #include "../../m68k/amiga/pcmcia.c"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/amiga/time.c linux/arch/ppc/amiga/time.c
--- v2.4.4/linux/arch/ppc/amiga/time.c	Mon Sep 11 08:39:48 2000
+++ linux/arch/ppc/amiga/time.c	Mon May 21 17:04:46 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.time.c 1.5 05/17/01 18:14:20 cort
+ */
 #include <linux/config.h> /* CONFIG_HEARTBEAT */
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.4.4/linux/arch/ppc/boot/Makefile	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/boot/Makefile	Thu May 24 15:02:06 2001
@@ -9,127 +9,88 @@
 # Adapted for PowerPC by Gary Thomas
 # modified by Cort (cort@cs.nmt.edu)
 #
+
 .c.s:
 	$(CC) $(CFLAGS) -S -o $*.s $<
 .s.o:
 	$(AS) -o $*.o $<
 .c.o:
-	$(CC) $(CFLAGS)  -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -D__BOOTER__ -c -o $*.o $<
+	$(CC) $(CFLAGS) -c -o $*.o $<
 .S.s:
 	$(CPP) $(AFLAGS) -traditional -o $*.o $<
 .S.o:
 	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
 
-ZOFF = 0
-ZSZ = 0
-IOFF = 0
-ISZ = 0
+GZIP_FLAGS = -v9f
 
-ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.prep.smp$(MSIZE)
-else
-TFTPIMAGE=/tftpboot/zImage.prep$(MSIZE)
-endif
+CFLAGS	:= $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -D__BOOTER__ \
+		-I$(TOPDIR)/arch/$(ARCH)/boot/include
+AFLAGS	+= -D__BOOTER__
+OBJCOPY_ARGS = -O elf32-powerpc
 
-ifeq ($(CONFIG_PPC64BRIDGE),y)
-MSIZE=.64
+ifeq ($(CONFIG_SMP),y)
+TFTPSIMAGE=/tftpboot/sImage.smp
 else
-MSIZE=
+TFTPSIMAGE=/tftpboot/sImage
 endif
 
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000
 
-GZIP_FLAGS = -v9f
+lib/zlib.a:
+	$(MAKE) -C lib
 
-OBJECTS := head.o misc.o ../coffboot/zlib.o
-CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin
-OBJCOPY_ARGS = -O elf32-powerpc
+images/vmlinux.gz: $(TOPDIR)/vmlinux
+	$(MAKE) -C images vmlinux.gz
 
-OBJECTS += vreset.o kbd.o of1275.o
-ifeq ($(CONFIG_SERIAL_CONSOLE),y)
-OBJECTS += ns16550.o
-endif
-
-all:	zImage
-
-zvmlinux.initrd: zvmlinux
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
-		--add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.initrd.tmp zvmlinux.initrd
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
-		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
-		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
-		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
-		-D__BOOTER__ \
-		-c -o misc.o misc.c
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
-		--add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.initrd.tmp $@
-	rm zvmlinux.initrd.tmp
+# Since gemini doesn't need/have it's own directory, we do znetboot* here
+ifdef CONFIG_GEMINI
+BOOT_TARGETS = zImage zImage.initrd
+else
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
+endif
 
-zImage: zvmlinux mkprep
+# We go into the utils dir by hand to ensure HOSTCC builds
+$(BOOT_TARGETS): sImage vmapus lib/zlib.a images/vmlinux.gz
+ifneq ("xx$(CONFIG_8260)$(CONFIG_8xx)","xx")
+	$(MAKE) -C mbx $@
+endif
 ifdef CONFIG_ALL_PPC
-	./mkprep -pbp zvmlinux zImage
+	$(MAKE) -C utils addnote piggyback mknote hack-coff mkprep
+	$(MAKE) -C chrp $@
+	$(MAKE) -C pmac $@
+	$(MAKE) -C prep $@
 endif
-ifdef CONFIG_APUS
-	$(STRIP) ../../../vmlinux -o vmapus
-	gzip $(GZIP_FLAGS) vmapus
+ifdef CONFIG_4xx
+	$(MAKE) -C tree $@
 endif
 
-zImage.initrd: zvmlinux.initrd mkprep
-ifdef CONFIG_ALL_PPC
-	./mkprep -pbp zvmlinux.initrd zImage.initrd
+sImage: $(TOPDIR)/vmlinux
+ifdef CONFIG_GEMINI
+	$(OBJCOPY) -I elf32-powerpc -O binary $(TOPDIR)/vmlinux images/sImage
 endif
 
-zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
-#
-# build the boot loader image and then compute the offset into it
-# for the kernel image
-#
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.tmp $@
-#
-# then with the offset rebuild the bootloader so we know where the kernel is
-#
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
-		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
-		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
-		-D__BOOTER__ \
-		-c -o misc.o misc.c
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.tmp $@
-	rm zvmlinux.tmp
-
-floppy: $(TOPDIR)/vmlinux zImage
-	dd if=zImage of=/dev/fd0H1440 bs=64b
-
-mkprep : mkprep.c
-	$(HOSTCC) -o mkprep mkprep.c
+vmapus: $(TOPDIR)/vmlinux
+ifdef CONFIG_APUS
+	$(STRIP) $(TOPDIR)/vmlinux -o images/vmapus
+	gzip $(GZIP_FLAGS) images/vmapus
+endif
 
+ifdef CONFIG_GEMINI
 znetboot : zImage
-ifdef CONFIG_ALL_PPC
-	cp zImage $(TFTPIMAGE)
+	cp images/sImage $(TFTPSIMAGE)
 endif
 
-znetboot.initrd : zImage.initrd
-	cp zImage.initrd $(TFTPIMAGE)
-
+# Do the dirs
 clean:
-	rm -f vmlinux* zvmlinux* mkprep zImage*
-
-fastdep:
-	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+	$(MAKE) -C images clean
+	$(MAKE) -C tree clean
+	$(MAKE) -C utils clean
 
 dep:
-	$(CPP) $(CPPFLAGS) -M *.S *.c > .depend
-
-# just here to match coffboot/Makefile
-vmlinux.coff:
+	$(MAKE) -C mbx fastdep
+	$(MAKE) -C chrp fastdep
+	$(MAKE) -C common fastdep
+	$(MAKE) -C pmac fastdep
+	$(MAKE) -C prep fastdep
+	$(MAKE) -C common fastdep
 
-vmlinux.coff.initrd:
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/chrp/Makefile linux/arch/ppc/boot/chrp/Makefile
--- v2.4.4/linux/arch/ppc/boot/chrp/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/chrp/Makefile	Thu May 24 15:02:06 2001
@@ -0,0 +1,73 @@
+# BK Id: SCCS/s.Makefile 1.8 05/18/01 06:20:29 patch
+#
+# Makefile for making ELF bootable images for booting on CHRP
+# using Open Firmware.
+#
+# Geert Uytterhoeven	September 1997
+#
+# Based on coffboot by Paul Mackerras
+
+ifeq ($(CONFIG_PPC64BRIDGE),y)
+MSIZE=.64
+AFLAGS += -Wa,-mppc64bridge
+else
+MSIZE=
+endif
+
+.c.o:
+	$(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
+.S.o:
+	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
+
+LD_ARGS = -Ttext 0x00400000
+
+OBJS = ../common/crt0.o start.o main.o misc.o ../common/string.o image.o
+LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a
+ADDNOTE = ../utils/addnote
+PIGGYBACK = ../utils/piggyback
+
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE)
+else
+TFTPIMAGE=/tftpboot/zImage.chrp$(MSIZE)
+endif
+
+all: zImage
+
+znetboot: zImage
+ifdef CONFIG_SMP
+	cp -f $(TOPDIR)/vmlinux /tftpboot/vmlinux.smp
+else
+	cp -f $(TOPDIR)/vmlinux /tftpboot/vmlinux
+endif
+ifdef CONFIG_PPC64BRIDGE
+	cp -f $(TOPDIR)/vmlinux /tftpboot/vmlinux.64
+endif
+	cp ../images/zImage.chrp $(TFTPIMAGE)
+
+znetboot.initrd: zImage.initrd
+	cp ../images/zImage.initrd.chrp $(TFTPIMAGE)
+
+floppy: zImage
+	mcopy zImage a:zImage
+
+image.o: $(PIGGYBACK) ../images/vmlinux.gz
+	$(PIGGYBACK) image < ../images/vmlinux.gz | $(AS) -o $@
+
+sysmap.o: $(PIGGYBACK) $(TOPDIR)/System.map
+	$(PIGGYBACK) sysmap < $(TOPDIR)/System.map | $(AS) -o $@
+
+initrd.o: ../images/ramdisk.image.gz $(PIGGYBACK)
+	$(PIGGYBACK) initrd < ../images/ramdisk.image.gz | $(AS) -o $@
+
+zImage: $(OBJS) $(LIBS) ../common/no_initrd.o $(ADDNOTE) ../images/vmlinux.gz
+	$(LD) $(LD_ARGS) -o ../images/$@.chrp $(OBJS) ../common/no_initrd.o $(LIBS)
+	cp ../images/$@.chrp ../images/$@.chrp-rs6k
+	$(ADDNOTE) ../images/$@.chrp-rs6k
+
+zImage.initrd: $(OBJS) $(LIBS) initrd.o $(ADDNOTE) ../images/vmlinux.gz
+	$(LD) $(LD_ARGS) -o ../images/$@.chrp $(OBJS) initrd.o $(LIBS)
+	cp ../images/$@.chrp ../images/$@.chrp-rs6k
+	$(ADDNOTE) ../images/$@.chrp-rs6k
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/chrp/main.c linux/arch/ppc/boot/chrp/main.c
--- v2.4.4/linux/arch/ppc/boot/chrp/main.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/chrp/main.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,198 @@
+/*
+ * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 "nonstdio.h"
+#include "zlib.h"
+#include <asm/bootinfo.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+extern void *finddevice(const char *);
+extern int getprop(void *, const char *, void *, int);
+void gunzip(void *, int, unsigned char *, int *);
+
+#define RAM_START	0x00000000
+#define RAM_END		(64<<20)
+
+#define BOOT_START	((unsigned long)_start)
+#define BOOT_END	((unsigned long)(_end + 0xFFF) & ~0xFFF)
+
+#define RAM_FREE	((unsigned long)(_end+0x1000)&~0xFFF)
+#define PROG_START	0x00010000
+
+char *avail_ram;
+char *end_avail;
+
+extern char _end[];
+extern char image_data[];
+extern int image_len;
+extern char initrd_data[];
+extern int initrd_len;
+extern char sysmap_data[];
+extern int sysmap_len;
+
+static char scratch[1024<<10];	/* 1MB of scratch space for gunzip */
+
+chrpboot(int a1, int a2, void *prom)
+{
+    int ns, oh, i;
+    unsigned sa, len;
+    void *dst;
+    unsigned char *im;
+    unsigned initrd_start, initrd_size;
+    extern char _start;
+    
+    printf("chrpboot starting: loaded at 0x%x\n\r", &_start);
+
+    if (initrd_len) {
+	initrd_size = initrd_len;
+	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+	a1 = initrd_start;
+	a2 = initrd_size;
+	claim(initrd_start, RAM_END - initrd_start, 0);
+	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r",
+	       initrd_start, initrd_data, initrd_size);
+	memcpy((char *)initrd_start, initrd_data, initrd_size);
+    }
+
+    im = image_data;
+    len = image_len;
+    /* claim 4MB starting at PROG_START */
+    claim(PROG_START, (4<<20) - PROG_START, 0);
+    dst = (void *) PROG_START;
+    if (im[0] == 0x1f && im[1] == 0x8b) {
+	avail_ram = scratch;
+	end_avail = scratch + sizeof(scratch);
+	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
+	gunzip(dst, 0x400000, im, &len);
+	printf("done %u bytes\n\r", len);
+    } else {
+	memmove(dst, im, len);
+    }
+
+    flush_cache(dst, len);
+    
+    sa = (unsigned long)PROG_START;
+    printf("start address = 0x%x\n\r", sa);
+
+    {
+	    struct bi_record *rec;
+	    
+	    rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20));
+
+	    rec->tag = BI_FIRST;
+	    rec->size = sizeof(struct bi_record);
+	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	    
+	    rec->tag = BI_BOOTLOADER_ID;
+	    sprintf( (char *)rec->data, "chrpboot");
+	    rec->size = sizeof(struct bi_record) + strlen("chrpboot") + 1;
+	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	    
+	    rec->tag = BI_MACHTYPE;
+	    rec->data[0] = _MACH_chrp;
+	    rec->data[1] = 1;
+	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
+#if 0
+	    rec->tag = BI_SYSMAP;
+	    rec->data[0] = (unsigned long)sysmap_data;
+	    rec->data[1] = sysmap_len;
+	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
+#endif
+	    rec->tag = BI_LAST;
+	    rec->size = sizeof(struct bi_record);
+	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
+    }
+    (*(void (*)())sa)(a1, a2, prom);
+
+    printf("returned?\n\r");
+
+    pause();
+}
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+    void *p = avail_ram;
+
+    size *= items;
+    size = (size + 7) & -8;
+    avail_ram += size;
+    if (avail_ram > end_avail) {
+	printf("oops... out of memory\n\r");
+	pause();
+    }
+    return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+    nb = (nb + 7) & -8;
+    if (addr == (avail_ram - nb)) {
+	avail_ram -= nb;
+    }
+}
+
+#define HEAD_CRC	2
+#define EXTRA_FIELD	4
+#define ORIG_NAME	8
+#define COMMENT		0x10
+#define RESERVED	0xe0
+
+#define DEFLATED	8
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+    z_stream s;
+    int r, i, flags;
+
+    /* skip header */
+    i = 10;
+    flags = src[3];
+    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+	printf("bad gzipped data\n\r");
+	exit();
+    }
+    if ((flags & EXTRA_FIELD) != 0)
+	i = 12 + src[10] + (src[11] << 8);
+    if ((flags & ORIG_NAME) != 0)
+	while (src[i++] != 0)
+	    ;
+    if ((flags & COMMENT) != 0)
+	while (src[i++] != 0)
+	    ;
+    if ((flags & HEAD_CRC) != 0)
+	i += 2;
+    if (i >= *lenp) {
+	printf("gunzip: ran out of data in header\n\r");
+	exit();
+    }
+
+    s.zalloc = zalloc;
+    s.zfree = zfree;
+    r = inflateInit2(&s, -MAX_WBITS);
+    if (r != Z_OK) {
+	printf("inflateInit2 returned %d\n\r", r);
+	exit();
+    }
+    s.next_in = src + i;
+    s.avail_in = *lenp - i;
+    s.next_out = dst;
+    s.avail_out = dstlen;
+    r = inflate(&s, Z_FINISH);
+    if (r != Z_OK && r != Z_STREAM_END) {
+	printf("inflate returned %d msg: %s\n\r", r, s.msg);
+	exit();
+    }
+    *lenp = s.next_out - (unsigned char *) dst;
+    inflateEnd(&s);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/chrp/misc.S linux/arch/ppc/boot/chrp/misc.S
--- v2.4.4/linux/arch/ppc/boot/chrp/misc.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/chrp/misc.S	Thu May 24 15:02:06 2001
@@ -0,0 +1,53 @@
+/*
+ * BK Id: SCCS/s.misc.S 1.6 05/18/01 15:16:59 cort
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+	.text
+
+/*
+ * Use the BAT0 registers to map the 1st 8MB of RAM to 0x90000000.
+ */
+	.globl	setup_bats
+setup_bats:
+	mfpvr	3
+	rlwinm	3,3,16,16,31		/* r3 = 1 for 601, 4 for 604 */
+	cmpi	0,3,1
+	lis	4,0x9000
+	bne	4f
+	ori	4,4,4			/* set up BAT registers for 601 */
+	li	5,0x7f
+	b	5f
+4:	ori	4,4,0xff		/* set up BAT registers for 604 */
+	li	5,2
+	mtdbatu	3,4
+	mtdbatl	3,5
+5:	mtibatu	3,4
+	mtibatl	3,5
+	isync
+	blr
+
+/*
+ * Flush the dcache and invalidate the icache for a range of addresses.
+ *
+ * flush_cache(addr, len)
+ */
+	.global	flush_cache
+flush_cache:
+	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
+	rlwinm.	4,4,27,5,31
+	mtctr	4
+	beqlr
+1:	dcbf	0,3
+	icbi	0,3
+	addi	3,3,0x20
+	bdnz	1b
+	sync
+	isync
+	blr
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/chrp/start.c linux/arch/ppc/boot/chrp/start.c
--- v2.4.4/linux/arch/ppc/boot/chrp/start.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/chrp/start.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,308 @@
+/*
+ * BK Id: SCCS/s.start.c 1.6 05/18/01 15:16:59 cort
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stdarg.h>
+
+int (*prom)();
+
+void *chosen_handle;
+void *stdin;
+void *stdout;
+void *stderr;
+
+void exit(void);
+void *finddevice(const char *name);
+int getprop(void *phandle, const char *name, void *buf, int buflen);
+
+void printk(char *fmt, ...);
+
+void
+start(int a1, int a2, void *promptr)
+{
+    prom = (int (*)()) promptr;
+    chosen_handle = finddevice("/chosen");
+    if (chosen_handle == (void *) -1)
+	exit();
+    if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
+	exit();
+    stderr = stdout;
+    if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
+	exit();
+
+    chrpboot(a1, a2, promptr);
+    for (;;)
+	exit();
+}
+
+int
+write(void *handle, void *ptr, int nb)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *ihandle;
+	void *addr;
+	int len;
+	int actual;
+    } args;
+
+    args.service = "write";
+    args.nargs = 3;
+    args.nret = 1;
+    args.ihandle = handle;
+    args.addr = ptr;
+    args.len = nb;
+    args.actual = -1;
+    (*prom)(&args);
+    return args.actual;
+}
+
+int
+read(void *handle, void *ptr, int nb)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *ihandle;
+	void *addr;
+	int len;
+	int actual;
+    } args;
+
+    args.service = "read";
+    args.nargs = 3;
+    args.nret = 1;
+    args.ihandle = handle;
+    args.addr = ptr;
+    args.len = nb;
+    args.actual = -1;
+    (*prom)(&args);
+    return args.actual;
+}
+
+void
+exit()
+{
+    struct prom_args {
+	char *service;
+    } args;
+
+    for (;;) {
+	args.service = "exit";
+	(*prom)(&args);
+    }
+}
+
+void
+pause()
+{
+    struct prom_args {
+	char *service;
+    } args;
+
+    args.service = "enter";
+    (*prom)(&args);
+}
+
+void *
+finddevice(const char *name)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	const char *devspec;
+	void *phandle;
+    } args;
+
+    args.service = "finddevice";
+    args.nargs = 1;
+    args.nret = 1;
+    args.devspec = name;
+    args.phandle = (void *) -1;
+    (*prom)(&args);
+    return args.phandle;
+}
+
+void *
+claim(unsigned int virt, unsigned int size, unsigned int align)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	unsigned int virt;
+	unsigned int size;
+	unsigned int align;
+	void *ret;
+    } args;
+
+    args.service = "claim";
+    args.nargs = 3;
+    args.nret = 1;
+    args.virt = virt;
+    args.size = size;
+    args.align = align;
+    (*prom)(&args);
+    return args.ret;
+}
+
+int
+getprop(void *phandle, const char *name, void *buf, int buflen)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *phandle;
+	const char *name;
+	void *buf;
+	int buflen;
+	int size;
+    } args;
+
+    args.service = "getprop";
+    args.nargs = 4;
+    args.nret = 1;
+    args.phandle = phandle;
+    args.name = name;
+    args.buf = buf;
+    args.buflen = buflen;
+    args.size = -1;
+    (*prom)(&args);
+    return args.size;
+}
+
+int
+putc(int c, void *f)
+{
+    char ch = c;
+
+    if (c == '\n')
+	putc('\r', f);
+    return write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+putchar(int c)
+{
+    return putc(c, stdout);
+}
+
+int
+fputs(char *str, void *f)
+{
+    int n = strlen(str);
+
+    return write(f, str, n) == n? 0: -1;
+}
+
+int
+readchar()
+{
+    char ch;
+
+    for (;;) {
+	switch (read(stdin, &ch, 1)) {
+	case 1:
+	    return ch;
+	case -1:
+	    printk("read(stdin) returned -1\r\n");
+	    return -1;
+	}
+    }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+getchar()
+{
+    int c;
+
+    if (lineleft == 0) {
+	lineptr = line;
+	for (;;) {
+	    c = readchar();
+	    if (c == -1 || c == 4)
+		break;
+	    if (c == '\r' || c == '\n') {
+		*lineptr++ = '\n';
+		putchar('\n');
+		break;
+	    }
+	    switch (c) {
+	    case 0177:
+	    case '\b':
+		if (lineptr > line) {
+		    putchar('\b');
+		    putchar(' ');
+		    putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    case 'U' & 0x1F:
+		while (lineptr > line) {
+		    putchar('\b');
+		    putchar(' ');
+		    putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    default:
+		if (lineptr >= &line[sizeof(line) - 1])
+		    putchar('\a');
+		else {
+		    putchar(c);
+		    *lineptr++ = c;
+		}
+	    }
+	}
+	lineleft = lineptr - line;
+	lineptr = line;
+    }
+    if (lineleft == 0)
+	return -1;
+    --lineleft;
+    return *lineptr++;
+}
+
+extern int vsprintf(char *buf, const char *fmt, va_list args);
+static char sprint_buf[1024];
+
+void
+printk(char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_buf, fmt, args);
+	va_end(args);
+	write(stdout, sprint_buf, n);
+}
+
+int
+printf(char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_buf, fmt, args);
+	va_end(args);
+	write(stdout, sprint_buf, n);
+	return n;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/Makefile linux/arch/ppc/boot/common/Makefile
--- v2.4.4/linux/arch/ppc/boot/common/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/Makefile	Thu May 24 15:02:06 2001
@@ -0,0 +1,27 @@
+#
+# arch/ppc/boot/common/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Tom Rini	January 2001
+#
+
+.c.s:
+	$(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+	$(AS) -o $*.o $<
+.c.o:
+	$(CC) $(CFLAGS) -c -o $*.o $<
+.S.s:
+	$(CPP) $(AFLAGS) -traditional -o $*.o $<
+.S.o:
+	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
+
+OBJCOPY_ARGS = -O elf32-powerpc
+
+coffcrt0.o:
+	$(CC) $(AFLAGS) -DXCOFF -traditional -c -o coffcrt0.o crt0.S
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/crt0.S linux/arch/ppc/boot/common/crt0.S
--- v2.4.4/linux/arch/ppc/boot/common/crt0.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/crt0.S	Thu May 24 15:02:06 2001
@@ -0,0 +1,84 @@
+/*
+ * BK Id: SCCS/s.crt0.S 1.10 05/21/01 00:49:49 cort
+ */
+/*    Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
+ *      Initial Power Macintosh COFF version.
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *      Modifications for IBM PowerPC 400-class processor evaluation
+ *      boards.
+ *
+ *    Module name: crt0.S
+ *
+ *    Description:
+ *      Boot loader execution entry point. Clears out .bss section as per
+ *      ANSI C requirements. Invalidates and flushes the caches over the
+ *      range covered by the boot loader's .text section. Sets up a stack
+ *      below the .text section entry point.
+ *
+ *    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 "../../kernel/ppc_asm.tmpl"
+
+	.text
+
+	.globl	_start
+_start:
+#ifdef XCOFF
+	.long	__start,0,0
+
+	.globl	__start
+__start:
+#endif
+#ifdef CONFIG_4xx
+	## Clear out the BSS as per ANSI C requirements
+
+	lis	r7,_end@ha
+	addi	r7,r7,_end@l		# r7 = &_end
+	lis	r8,__bss_start@ha	# 
+	addi	r8,r8,__bss_start@l	# r8 = &_bss_start
+
+	## Determine how large an area, in number of words, to clear
+	
+	subf	r7,r8,r7		# r7 = &_end - &_bss_start + 1 
+	addi	r7,r7,3			# r7 += 3
+	srwi.	r7,r7,2			# r7 = size in words.
+	beq	2f			# If the size is zero, do not bother
+	addi	r8,r8,-4		# r8 -= 4
+	mtctr	r7			# SPRN_CTR = number of words to clear
+	li	r0,0			# r0 = 0
+1:	stwu	r0,4(r8)		# Clear out a word
+	bdnz	1b			# If we are not done yet, keep clearing
+#endif
+
+	## Flush and invalidate the caches for the range in memory covering
+	## the .text section of the boot loader
+	
+2:	lis	r9,_start@h		# r9 = &_start
+	lis	r8,_etext@ha		# 
+	addi	r8,r8,_etext@l		# r8 = &_etext
+3:	dcbf	r0,r9			# Flush the data cache
+	icbi	r0,r9			# Invalidate the instruction cache
+	addi	r9,r9,0x10		# Increment by one cache line
+	cmplw	cr0,r9,r8		# Are we at the end yet?
+	blt	3b			# No, keep flushing and invalidating
+	sync				# sync ; isync after flushing the icache
+	isync
+
+#ifdef CONFIG_4xx
+	## Set up the stack
+
+	lis	r9,_start@h		# r9 = &_start (text section entry)
+	addi	r9,r9,_start@l
+	subi	r1,r9,64		# Start the stack 64 bytes below _start
+	clrrwi	r1,r1,4			# Make sure it is aligned on 16 bytes.
+	li	r0,0
+	stwu	r0,-16(r1)
+	mtlr	r9
+#endif
+
+	b	start			# All done, start the real work.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/misc-common.c linux/arch/ppc/boot/common/misc-common.c
--- v2.4.4/linux/arch/ppc/boot/common/misc-common.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/misc-common.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,539 @@
+/*
+ * arch/ppc/boot/common/misc-common.c
+ * 
+ * Misc. bootloader code (almost) all platforms can use
+ *
+ * Author: Johnnie Peters <jpeters@mvista.com>
+ * Editor: Tom Rini <trini@mvista.com>
+ *
+ * Derived from arch/ppc/boot/prep/misc.c
+ *
+ * Copyright 2000-2001 MontaVista Software Inc.
+ *
+ * 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 "zlib.h"
+#include <linux/pci.h>
+
+/* If we're on a ALL_PPC, assume we have a keyboard controller
+ * Also note, if we're not ALL_PPC, we assume you are a serial
+ * console - Tom */
+#ifdef CONFIG_ALL_PPC
+extern void cursor(int x, int y);
+extern void scroll(void);
+extern char *vidmem;
+extern int lines, cols;
+extern int orig_x, orig_y;
+extern int keyb_present;
+extern int CRT_tstc(void);
+extern int CRT_getc(void);
+#else
+int cursor(int x, int y) {return 0;}
+void scroll(void) {}
+char vidmem[1];
+#define lines 0
+#define cols 0
+int orig_x = 0;
+int orig_y = 0;
+#define keyb_present 0
+int CRT_tstc(void) {return 0;}
+int CRT_getc(void) {return 0;}
+#endif
+
+extern char *avail_ram;
+extern char *end_avail;
+extern char _end[];
+
+void puts(const char *);
+void putc(const char c);
+void puthex(unsigned long val);
+void _bcopy(char *src, char *dst, int len);
+void gunzip(void *, int, unsigned char *, int *);
+static int _cvt(unsigned long val, char *buf, long radix, char *digits);
+
+void _vprintk(void(*)(const char), const char *, va_list);
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+struct NS16550 *com_port;
+
+int serial_tstc(volatile struct NS16550 *);
+unsigned char serial_getc(volatile struct NS16550 *);
+void serial_putc(volatile struct NS16550 *, unsigned char);
+#endif
+
+void pause(void)
+{
+	puts("pause\n");
+}
+
+void exit(void)
+{
+	puts("exit\n");
+	while(1); 
+}
+
+int tstc(void)
+{
+#if defined(CONFIG_SERIAL_CONSOLE)
+	if(keyb_present)
+		return (CRT_tstc() || serial_tstc(com_port));
+	else
+		return (serial_tstc(com_port));
+#else
+	return CRT_tstc();
+#endif
+}
+
+int getc(void)
+{
+	while (1) {
+#if defined(CONFIG_SERIAL_CONSOLE)
+		if (serial_tstc(com_port))
+			return (serial_getc(com_port));
+#endif /* CONFIG_SERIAL_CONSOLE */
+		if (keyb_present)
+			if(CRT_tstc())
+				return (CRT_getc());
+	}
+}
+
+void 
+putc(const char c)
+{
+	int x,y;
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+	serial_putc(com_port, c);
+	if ( c == '\n' )
+		serial_putc(com_port, '\r');
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+	x = orig_x;
+	y = orig_y;
+
+	if ( c == '\n' ) {
+		x = 0;
+		if ( ++y >= lines ) {
+			scroll();
+			y--;
+		}
+	} else if (c == '\r') {
+		x = 0;
+	} else if (c == '\b') {
+		if (x > 0) {
+			x--;
+		}
+	} else {
+		vidmem [ ( x + cols * y ) * 2 ] = c; 
+		if ( ++x >= cols ) {
+			x = 0;
+			if ( ++y >= lines ) {
+				scroll();
+				y--;
+			}
+		}
+	}
+
+	cursor(x, y);
+
+	orig_x = x;
+	orig_y = y;
+}
+
+void puts(const char *s)
+{
+	int x,y;
+	char c;
+
+	x = orig_x;
+	y = orig_y;
+
+	while ( ( c = *s++ ) != '\0' ) {
+#if defined(CONFIG_SERIAL_CONSOLE)
+	        serial_putc(com_port, c);
+	        if ( c == '\n' ) serial_putc(com_port, '\r');
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+		if ( c == '\n' ) {
+			x = 0;
+			if ( ++y >= lines ) {
+				scroll();
+				y--;
+			}
+		} else if (c == '\b') {
+		  if (x > 0) {
+		    x--;
+		  }
+		} else {
+			vidmem [ ( x + cols * y ) * 2 ] = c; 
+			if ( ++x >= cols ) {
+				x = 0;
+				if ( ++y >= lines ) {
+					scroll();
+					y--;
+				}
+			}
+		}
+	}
+
+	cursor(x, y);
+
+	orig_x = x;
+	orig_y = y;
+}
+
+void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while(1);	/* Halt */
+}
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+	void *p = avail_ram;
+	
+	size *= items;
+	size = (size + 7) & -8;
+	avail_ram += size;
+	if (avail_ram > end_avail) {
+		puts("oops... out of memory\n");
+		pause();
+	}
+	return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+}
+
+#define HEAD_CRC	2
+#define EXTRA_FIELD	4
+#define ORIG_NAME	8
+#define COMMENT		0x10
+#define RESERVED	0xe0
+
+#define DEFLATED	8
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+	z_stream s;
+	int r, i, flags;
+	
+	/* skip header */
+	i = 10;
+	flags = src[3];
+	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+		puts("bad gzipped data\n");
+		exit();
+	}
+	if ((flags & EXTRA_FIELD) != 0)
+		i = 12 + src[10] + (src[11] << 8);
+	if ((flags & ORIG_NAME) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & COMMENT) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & HEAD_CRC) != 0)
+		i += 2;
+	if (i >= *lenp) {
+		puts("gunzip: ran out of data in header\n");
+		exit();
+	}
+	
+	s.zalloc = zalloc;
+	s.zfree = zfree;
+	r = inflateInit2(&s, -MAX_WBITS);
+	if (r != Z_OK) {
+		puts("inflateInit2 returned %d\n");
+		exit();
+	}
+	s.next_in = src + i;
+	s.avail_in = *lenp - i;
+	s.next_out = dst;
+	s.avail_out = dstlen;
+	r = inflate(&s, Z_FINISH);
+	if (r != Z_OK && r != Z_STREAM_END) {
+		puts("inflate returned %d\n");
+		exit();
+	}
+	*lenp = s.next_out - (unsigned char *) dst;
+	inflateEnd(&s);
+}
+
+void
+puthex(unsigned long val)
+{
+
+	unsigned char buf[10];
+	int i;
+	for (i = 7;  i >= 0;  i--)
+	{
+		buf[i] = "0123456789ABCDEF"[val & 0x0F];
+		val >>= 4;
+	}
+	buf[8] = '\0';
+	puts(buf);
+}
+
+#define FALSE 0
+#define TRUE  1
+#include <stdarg.h>
+
+void
+_printk(char const *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	_vprintk(putc, fmt, ap);
+	va_end(ap);
+	return;
+}
+
+#define is_digit(c) ((c >= '0') && (c <= '9'))
+
+void
+_vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
+{
+	char c, sign, *cp = 0;
+	int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
+	char buf[32];
+	long val;
+	while ((c = *fmt0++))
+	{
+		if (c == '%')
+		{
+			c = *fmt0++;
+			left_prec = right_prec = pad_on_right = 0;
+			if (c == '-')
+			{
+				c = *fmt0++;
+				pad_on_right++;
+			}
+			if (c == '0')
+			{
+				zero_fill = TRUE;
+				c = *fmt0++;
+			} else
+			{
+				zero_fill = FALSE;
+			}
+			while (is_digit(c))
+			{
+				left_prec = (left_prec * 10) + (c - '0');
+				c = *fmt0++;
+			}
+			if (c == '.')
+			{
+				c = *fmt0++;
+				zero_fill++;
+				while (is_digit(c))
+				{
+					right_prec = (right_prec * 10) + (c - '0');
+					c = *fmt0++;
+				}
+			} else
+			{
+				right_prec = left_prec;
+			}
+			sign = '\0';
+			switch (c)
+			{
+			case 'd':
+			case 'x':
+			case 'X':
+				val = va_arg(ap, long);
+				switch (c)
+				{
+				case 'd':
+					if (val < 0)
+					{
+						sign = '-';
+						val = -val;
+					}
+					length = _cvt(val, buf, 10, "0123456789");
+					break;
+				case 'x':
+					length = _cvt(val, buf, 16, "0123456789abcdef");
+					break;
+				case 'X':
+					length = _cvt(val, buf, 16, "0123456789ABCDEF");
+					break;
+				}
+				cp = buf;
+				break;
+			case 's':
+				cp = va_arg(ap, char *);
+				length = strlen(cp);
+				break;
+			case 'c':
+				c = va_arg(ap, long /*char*/);
+				(*putc)(c);
+				continue;
+			default:
+				(*putc)('?');
+			}
+			pad = left_prec - length;
+			if (sign != '\0')
+			{
+				pad--;
+			}
+			if (zero_fill)
+			{
+				c = '0';
+				if (sign != '\0')
+				{
+					(*putc)(sign);
+					sign = '\0';
+				}
+			} else
+			{
+				c = ' ';
+			}
+			if (!pad_on_right)
+			{
+				while (pad-- > 0)
+				{
+					(*putc)(c);
+				}
+			}
+			if (sign != '\0')
+			{
+				(*putc)(sign);
+			}
+			while (length-- > 0)
+			{
+				(*putc)(c = *cp++);
+				if (c == '\n')
+				{
+					(*putc)('\r');
+				}
+			}
+			if (pad_on_right)
+			{
+				while (pad-- > 0)
+				{
+					(*putc)(c);
+				}
+			}
+		} else
+		{
+			(*putc)(c);
+			if (c == '\n')
+			{
+				(*putc)('\r');
+			}
+		}
+	}
+}
+
+int
+_cvt(unsigned long val, char *buf, long radix, char *digits)
+{
+	char temp[80];
+	char *cp = temp;
+	int length = 0;
+	if (val == 0)
+	{ /* Special case */
+		*cp++ = '0';
+	} else
+		while (val)
+		{
+			*cp++ = digits[val % radix];
+			val /= radix;
+		}
+	while (cp != temp)
+	{
+		*buf++ = *--cp;
+		length++;
+	}
+	*buf = '\0';
+	return (length);
+}
+
+void
+_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
+{
+	int i, c;
+	if ((unsigned int)s > (unsigned int)p)
+	{
+		s = (unsigned int)s - (unsigned int)p;
+	}
+	while (s > 0)
+	{
+		if (base)
+		{
+			_printk("%06X: ", (int)p - (int)base);
+		} else
+		{
+			_printk("%06X: ", p);
+		}
+		for (i = 0;  i < 16;  i++)
+		{
+			if (i < s)
+			{
+				_printk("%02X", p[i] & 0xFF);
+			} else
+			{
+				_printk("  ");
+			}
+			if ((i % 2) == 1) _printk(" ");
+			if ((i % 8) == 7) _printk(" ");
+		}
+		_printk(" |");
+		for (i = 0;  i < 16;  i++)
+		{
+			if (i < s)
+			{
+				c = p[i] & 0xFF;
+				if ((c < 0x20) || (c >= 0x7F)) c = '.';
+			} else
+			{
+				c = ' ';
+			}
+			_printk("%c", c);
+		}
+		_printk("|\n");
+		s -= 16;
+		p += 16;
+	}
+}
+
+void
+_dump_buf(unsigned char *p, int s)
+{
+	_printk("\n");
+	_dump_buf_with_offset(p, s, 0);
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/misc-simple.c linux/arch/ppc/boot/common/misc-simple.c
--- v2.4.4/linux/arch/ppc/boot/common/misc-simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/misc-simple.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,182 @@
+/*
+ * arch/ppc/common/misc-simple.c
+ *
+ * Misc. bootloader code for many machines.  This assumes you have are using
+ * a 6xx/7xx/74xx CPU in your machine.  This assumes the chunk of memory
+ * below 8MB is free.  Finally, it assumes you have a NS16550-style uart for 
+ * your serial console.  If a machine meets these requirements, it can quite
+ * likely use this code during boot.
+ * 
+ * Author: Matt Porter <mporter@mvista.com>
+ * Derived from arch/ppc/boot/prep/misc.c
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * 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/types.h>
+#include <linux/elf.h>
+#include <linux/config.h>
+
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+
+#include "zlib.h"
+
+unsigned long com_port;
+
+char *avail_ram;
+char *end_avail;
+extern char _end[];
+
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE ""
+#endif
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+unsigned long initrd_start = 0, initrd_end = 0;
+char *zimage_start;
+int zimage_size;
+
+extern void puts(const char *);
+extern void putc(const char c);
+extern void puthex(unsigned long val);
+extern void *memcpy(void * __dest, __const void * __src,
+			    __kernel_size_t __n);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern void udelay(long delay);
+extern int tstc(void);
+extern int getc(void);
+extern volatile unsigned long serial_init(int chan);
+
+void
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
+{
+
+	int timer = 0;
+	extern unsigned long start;
+	char *cp, ch;
+
+	com_port = serial_init(0);
+
+	/* assume the chunk below 8M is free */
+	end_avail = (char *)0x00800000;
+
+	/*
+	 * Reveal where we were loaded at and where we
+	 * were relocated to.
+	 */
+	puts("loaded at:     "); puthex(load_addr);
+	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
+	if ( (unsigned long)load_addr != (unsigned long)&start )
+	{
+		puts("relocated to:  "); puthex((unsigned long)&start);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+		puts("\n");
+	}
+
+	/* we have to subtract 0x10000 here to correct for objdump including
+	   the size of the elf header which we strip -- Cort */
+	zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
+	zimage_size = ZIMAGE_SIZE;
+
+	if ( INITRD_OFFSET )
+		initrd_start = load_addr - 0x10000 + INITRD_OFFSET;
+	else
+		initrd_start = 0;
+	initrd_end = INITRD_SIZE + initrd_start;
+
+	/*
+	 * Find a place to stick the zimage and initrd and 
+	 * relocate them if we have to. -- Cort
+	 */
+	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
+	puts("zimage at:     "); puthex((unsigned long)zimage_start);
+	puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
+	if ( (unsigned long)zimage_start <= 0x00800000 )
+	{
+		memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
+		zimage_start = (char *)avail_ram;
+		puts("relocated to:  "); puthex((unsigned long)zimage_start);
+		puts(" ");
+		puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
+		puts("\n");
+
+		/* relocate initrd */
+		if ( initrd_start )
+		{
+			puts("initrd at:     "); puthex(initrd_start);
+			puts(" "); puthex(initrd_end); puts("\n");
+			avail_ram = (char *)PAGE_ALIGN(
+				(unsigned long)zimage_size+(unsigned long)zimage_start);
+			memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
+			initrd_start = (unsigned long)avail_ram;
+			initrd_end = initrd_start + INITRD_SIZE;
+			puts("relocated to:  "); puthex(initrd_start);
+			puts(" "); puthex(initrd_end); puts("\n");
+		}
+	} else if ( initrd_start ) {
+		puts("initrd at:     "); puthex(initrd_start);
+		puts(" "); puthex(initrd_end); puts("\n");
+	}
+
+	avail_ram = (char *)0x00400000;
+	end_avail = (char *)0x00800000;
+	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
+	puthex((unsigned long)end_avail); puts("\n");
+
+	/* Display standard Linux/PPC boot prompt for kernel args */
+	puts("\nLinux/PPC load: ");
+	cp = cmd_line;
+	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+	while ( *cp ) putc(*cp++);
+	while (timer++ < 5*1000) {
+		if (tstc()) {
+			while ((ch = getc()) != '\n' && ch != '\r') {
+				/* Test for backspace/delete */
+				if (ch == '\b' || ch == '\177') {
+					if (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				/* Test for ^x/^u (and wipe the line) */
+				} else if (ch == '\030' || ch == '\025') {
+					while (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				} else {
+					*cp++ = ch;
+					putc(ch);
+				}
+			}
+			break;  /* Exit 'timer' loop */
+		}
+		udelay(1000);  /* 1 msec */
+	}
+	*cp = 0;
+	puts("\n");
+
+	/* mappings on early boot can only handle 16M */
+	if ( (int)(cmd_line[0]) > (16<<20))
+		puts("cmd_line located > 16M\n");
+	if ( initrd_start > (16<<20))
+		puts("initrd_start located > 16M\n");
+       
+	puts("Uncompressing Linux...");
+
+	gunzip(0, 0x400000, zimage_start, &zimage_size);
+	puts("done.\n");
+
+	puts("Now booting the kernel\n");
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/no_initrd.c linux/arch/ppc/boot/common/no_initrd.c
--- v2.4.4/linux/arch/ppc/boot/common/no_initrd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/no_initrd.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,5 @@
+/*
+ * BK Id: SCCS/s.no_initrd.c 1.7 05/18/01 15:17:23 cort
+ */
+char initrd_data[1];
+int initrd_len = 0;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/ns16550.c linux/arch/ppc/boot/common/ns16550.c
--- v2.4.4/linux/arch/ppc/boot/common/ns16550.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/ns16550.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,80 @@
+/*
+ * BK Id: SCCS/s.ns16550.c 1.7 05/18/01 06:20:29 patch
+ */
+/*
+ * COM1 NS16550 support
+ */
+
+#include <linux/config.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+
+/* Some machines, such as ones with a PReP memory map, initally have
+ * their serial port at an offset of 0x80000000 from where they are
+ * in <asm/serial.h>.  This tries to take that into account. */
+#ifndef IOOFFSET
+#define IOOFFSET 0
+#endif
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
+};
+
+static int shift;
+
+volatile unsigned long serial_init(int chan) {
+	unsigned long com_port;
+
+	/* Get the base, and add any offset we need to deal with. */
+	com_port = rs_table[chan].port + IOOFFSET;
+
+	/* How far apart the registers are. */
+	shift = rs_table[chan].iomem_reg_shift;
+
+	/* See if port is present */
+	*((unsigned char *)com_port + (UART_LCR << shift)) = 0x00;
+	*((unsigned char *)com_port + (UART_IER << shift)) = 0x00;
+	/* Access baud rate */
+	*((unsigned char *)com_port + (UART_LCR << shift)) = 0x00;
+#ifdef CONFIG_SERIAL_CONSOLE_NONSTD
+	/* Input clock. */
+	*((unsigned char *)com_port + (UART_DLL << shift)) = 
+			(BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD);
+	*((unsigned char *)com_port + (UART_DLM << shift)) = 
+		(BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8;
+#endif
+	 /* 8 data, 1 stop, no parity */
+	*((unsigned char *)com_port + (UART_LCR << shift)) = 0x03;
+	/* RTS/DTR */
+	*((unsigned char *)com_port + (UART_MCR << shift)) = 0x03;
+	/* Clear & enable FIFOs */
+	*((unsigned char *)com_port + (UART_FCR << shift)) = 0x07;
+
+	return (com_port);
+}
+
+void
+serial_putc(volatile unsigned long com_port, unsigned char c)
+{
+	while ((*((volatile unsigned char *)com_port + (UART_LSR << shift)) &
+				UART_LSR_THRE) == 0)
+		;
+	*(volatile unsigned char *)com_port = c;
+}
+
+unsigned char
+serial_getc(volatile unsigned long com_port)
+{
+	while ((*((volatile unsigned char *)com_port + (UART_LSR << shift))
+			& UART_LSR_DR) == 0)
+		;
+	return (*(volatile unsigned char *)com_port);
+}
+
+int
+serial_tstc(volatile unsigned long com_port)
+{
+	return ((*((volatile unsigned char *)com_port + (UART_LSR << shift))
+				& UART_LSR_DR) != 0);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/common/string.S linux/arch/ppc/boot/common/string.S
--- v2.4.4/linux/arch/ppc/boot/common/string.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/common/string.S	Thu May 24 15:02:06 2001
@@ -0,0 +1,153 @@
+/*
+ * BK Id: SCCS/s.string.S 1.8 05/18/01 06:20:29 patch
+ */
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * 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.
+ */
+#define r0	0
+#define r3	3
+#define r4	4
+#define r5	5
+#define r6	6
+#define r7	7
+#define r8	8
+
+	.globl	strlen
+strlen:
+	addi	r4,r3,-1
+1:	lbzu	r0,1(r4)
+	cmpwi	0,r0,0
+	bne	1b
+	subf	r3,r3,r4
+	blr
+
+	.globl	memset
+memset:
+	rlwimi	r4,r4,8,16,23
+	rlwimi	r4,r4,16,0,15
+	addi	r6,r3,-4
+	cmplwi	0,r5,4
+	blt	7f
+	stwu	r4,4(r6)
+	beqlr
+	andi.	r0,r6,3
+	add	r5,r0,r5
+	subf	r6,r0,r6
+	rlwinm	r0,r5,32-2,2,31
+	mtctr	r0
+	bdz	6f
+1:	stwu	r4,4(r6)
+	bdnz	1b
+6:	andi.	r5,r5,3
+7:	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+	addi	r6,r6,3
+8:	stbu	r4,1(r6)
+	bdnz	8b
+	blr
+
+	.globl	memmove
+memmove:
+	cmplw	0,r3,r4
+	bgt	backwards_memcpy
+	/* fall through */
+
+	.globl	memcpy
+memcpy:
+	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
+	addi	r6,r3,-4
+	addi	r4,r4,-4
+	beq	2f			/* if less than 8 bytes to do */
+	andi.	r0,r6,3			/* get dest word aligned */
+	mtctr	r7
+	bne	5f
+1:	lwz	r7,4(r4)
+	lwzu	r8,8(r4)
+	stw	r7,4(r6)
+	stwu	r8,8(r6)
+	bdnz	1b
+	andi.	r5,r5,7
+2:	cmplwi	0,r5,4
+	blt	3f
+	lwzu	r0,4(r4)
+	addi	r5,r5,-4
+	stwu	r0,4(r6)
+3:	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+	addi	r4,r4,3
+	addi	r6,r6,3
+4:	lbzu	r0,1(r4)
+	stbu	r0,1(r6)
+	bdnz	4b
+	blr
+5:	subfic	r0,r0,4
+	mtctr	r0
+6:	lbz	r7,4(r4)
+	addi	r4,r4,1
+	stb	r7,4(r6)
+	addi	r6,r6,1
+	bdnz	6b
+	subf	r5,r0,r5
+	rlwinm.	r7,r5,32-3,3,31
+	beq	2b
+	mtctr	r7
+	b	1b
+
+	.globl	backwards_memcpy
+backwards_memcpy:
+	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
+	add	r6,r3,r5
+	add	r4,r4,r5
+	beq	2f
+	andi.	r0,r6,3
+	mtctr	r7
+	bne	5f
+1:	lwz	r7,-4(r4)
+	lwzu	r8,-8(r4)
+	stw	r7,-4(r6)
+	stwu	r8,-8(r6)
+	bdnz	1b
+	andi.	r5,r5,7
+2:	cmplwi	0,r5,4
+	blt	3f
+	lwzu	r0,-4(r4)
+	subi	r5,r5,4
+	stwu	r0,-4(r6)
+3:	cmpwi	0,r5,0
+	beqlr
+	mtctr	r5
+4:	lbzu	r0,-1(r4)
+	stbu	r0,-1(r6)
+	bdnz	4b
+	blr
+5:	mtctr	r0
+6:	lbzu	r7,-1(r4)
+	stbu	r7,-1(r6)
+	bdnz	6b
+	subf	r5,r0,r5
+	rlwinm.	r7,r5,32-3,3,31
+	beq	2b
+	mtctr	r7
+	b	1b
+
+	.globl	memcmp
+memcmp:
+	cmpwi	0,r5,0
+	blelr
+	mtctr	r5
+	addi	r6,r3,-1
+	addi	r4,r4,-1
+1:	lbzu	r3,1(r6)
+	lbzu	r0,1(r4)
+	subf.	r3,r0,r3
+	bdnzt	2,1b
+	blr
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.4.4/linux/arch/ppc/boot/head.S	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/boot/head.S	Wed Dec 31 16:00:00 1969
@@ -1,238 +0,0 @@
-#include "../kernel/ppc_defs.h"
-#include "../kernel/ppc_asm.tmpl"
-#include <asm/processor.h>
-#include <asm/cache.h>
-
-	.text
-
-/*
- * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
- *	
- * Boot loader philosophy:
- *      ROM loads us to some arbitrary location
- *      Move the boot code to the link address (8M)
- *      Call decompress_kernel()
- *         Relocate the initrd, zimage and residual data to 8M
- *         Decompress the kernel to 0
- *      Jump to the kernel entry
- *            -- Cort
- */
-	.globl	start
-start:
-	bl	start_
-start_:
-	mr	r11,r3		/* Save pointer to residual/board data */
-	mr      r25,r5          /* Save OFW pointer */
-	li	r3,MSR_IP	/* Establish default MSR value */
-	mtmsr	r3
-
-/* check if we need to relocate ourselves to the link addr or were we
-   loaded there to begin with -- Cort */
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	mflr	r3
-	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
-	mr	r8,r3
-	cmp	0,r3,r4
-	bne	1010f
-/* compute size of whole image in words.  this should be moved to
- * start_ldr() -- Cort
- */
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	lis	r5,end@h
-	ori	r5,r5,end@l
-	addi	r5,r5,3		/* round up */
-	sub	r5,r5,r4
-	srwi	r5,r5,2
-	mr	r7,r5
-	b	start_ldr
-1010:
-/* 
- * no matter where we're loaded, move ourselves to -Ttext address
- */
-relocate:
-	mflr	r3		/* Compute code bias */
-	subi	r3,r3,4
-	mr	r8,r3
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	lis	r5,end@h
-	ori	r5,r5,end@l
-	addi	r5,r5,3			/* Round up - just in case */
-	sub	r5,r5,r4		/* Compute # longwords to move */
-	srwi	r5,r5,2
-	mtctr	r5
-	mr	r7,r5
-	li	r6,0
-	subi	r3,r3,4			/* Set up for loop */
-	subi	r4,r4,4
-00:	lwzu	r5,4(r3)
-	stwu	r5,4(r4)
-	xor	r6,r6,r5
-	bdnz	00b
-  	lis	r3,start_ldr@h
-	ori	r3,r3,start_ldr@l
-	mtlr	r3			/* Easiest way to do an absolute jump */
-	blr
-start_ldr:
-/* Clear all of BSS */
-	lis	r3,edata@h
-	ori	r3,r3,edata@l
-	lis	r4,end@h
-	ori	r4,r4,end@l
-	subi	r3,r3,4
-	subi	r4,r4,4
-	li	r0,0
-50:	stwu	r0,4(r3)
-	cmp	0,r3,r4
-	bne	50b
-90:	mr	r9,r1			/* Save old stack pointer (in case it matters) */
-	lis	r1,.stack@h
-	ori	r1,r1,.stack@l
-	addi	r1,r1,4096*2
-	subi	r1,r1,256
-	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
-	andc	r1,r1,r2
-/* Run loader */
-	mr	r3,r8			/* Load point */
-	mr	r4,r7			/* Program length */
-	mr	r5,r6			/* Checksum */
-	mr	r6,r11			/* Residual data */
-	mr      r7,r25                  /* OFW interfaces */
-	bl	decompress_kernel
-	
-	/* changed to use r3 (as firmware does) for kernel
-	   as ptr to residual -- Cort*/
-	lis	r6,cmd_line@h
-	ori	r6,r6,cmd_line@l
-	lwz	r6, 0(r6)
-	subi	r7,r6,1
-00:	lbzu	r2,1(r7)
-	cmpi	0,r2,0
-	bne	00b
-
-	/* tell kernel we're prep */
-	/* 
-	 * get start address of kernel code which is stored as a coff
-	 * entry.  see boot/head.S -- Cort 
-	 */
-	li	r9,0x4
-	mtlr	r9
-	lis	r10,0xdeadc0de@h
-	ori	r10,r10,0xdeadc0de@l
-	li	r9,0
-	stw	r10,0(r9)
-/*
- * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
- * so disable BATs before setting this to avoid a clash
- */
-	li      r8,0
-	mtspr   DBAT0U,r8
-	mtspr   DBAT1U,r8
-	mtspr   DBAT2U,r8
-	mtspr   DBAT3U,r8
-	mtspr   IBAT0U,r8
-	mtspr   IBAT1U,r8
-	mtspr   IBAT2U,r8
-	mtspr   IBAT3U,r8
-
-	blr
-hang:
-	b	hang	
-
-/*
- * Delay for a number of microseconds
- * -- Use the BUS timer (assumes 66MHz)
- */
-	.globl	udelay
-udelay:		
-	mfspr	r4,PVR
-	srwi	r4,r4,16
-	cmpi	0,r4,1		/* 601 ? */
-	bne	.udelay_not_601
-00:	li	r0,86	/* Instructions / microsecond? */
-	mtctr	r0
-10:	addi	r0,r0,0 /* NOP */
-	bdnz	10b
-	subic.	r3,r3,1
-	bne	00b
-	blr
-
-.udelay_not_601:		
-	mulli	r4,r3,1000	/* nanoseconds */
-	addi	r4,r4,59
-	li	r5,60
-	divw	r4,r4,r5	/* BUS ticks */
-1:	mftbu	r5
-	mftb	r6
-	mftbu	r7
-	cmp	0,r5,r7
-	bne	1b		/* Get [synced] base time */
-	addc	r9,r6,r4	/* Compute end time */
-	addze	r8,r5
-2:	mftbu	r5
-	cmp	0,r5,r8
-	blt	2b
-	bgt	3f
-	mftb	r6
-	cmp	0,r6,r9
-	blt	2b
-3:	blr		
-
-.globl _get_HID0
-_get_HID0:		
-	mfspr	r3,HID0
-	blr
-
-.globl _put_HID0
-_put_HID0:		
-	mtspr	HID0,r3
-	blr
-		
-.globl _get_MSR
-_get_MSR:		
-	mfmsr	r3
-	blr
-	
-.globl _put_MSR
-_put_MSR:		
-	mtmsr	r3
-	blr
-
-/*
- * Flush instruction cache
- * *** I'm really paranoid here!
- */
-_GLOBAL(flush_instruction_cache)
-	mflr	r5
-	bl	flush_data_cache
-	mfspr	r3,HID0	/* Caches are controlled by this register */
-	li	r4,0
-	ori	r4,r4,(HID0_ICE|HID0_ICFI)
-	or	r3,r3,r4	/* Need to enable+invalidate to clear */
-	mtspr	HID0,r3
-	andc	r3,r3,r4
-	ori	r3,r3,HID0_ICE	/* Enable cache */
-	mtspr	HID0,r3
-	mtlr	r5
-	blr
-	
-#define NUM_CACHE_LINES 128*8
-#define CACHE_LINE_SIZE 32 
-#define cache_flush_buffer 0x1000
-
-/*
- * Flush data cache
- * *** I'm really paranoid here!
- */
-_GLOBAL(flush_data_cache)
-	lis	r3,cache_flush_buffer@h
-	ori	r3,r3,cache_flush_buffer@l
-	li	r4,NUM_CACHE_LINES
-	mtctr	r4
-00:	lwz	r4,0(r3)
-	addi	r3,r3,CACHE_LINE_SIZE	/* Next line, please */
-	bdnz	00b	
-10:	blr
-	.comm	.stack,4096*2,4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/images/Makefile linux/arch/ppc/boot/images/Makefile
--- v2.4.4/linux/arch/ppc/boot/images/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/images/Makefile	Thu May 24 15:02:06 2001
@@ -0,0 +1,12 @@
+#
+# This dir holds all of the images for PPC machines.
+# Tom Rini	January 2001
+
+include $(TOPDIR)/Rules.make
+
+vmlinux.gz: $(TOPDIR)/vmlinux
+	$(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux
+	gzip -vf9 vmlinux
+
+clean:
+	rm -f sImage vmapus vmlinux.* miboot.image* zImage* zvmlinux.*
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/include/nonstdio.h linux/arch/ppc/boot/include/nonstdio.h
--- v2.4.4/linux/arch/ppc/boot/include/nonstdio.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/include/nonstdio.h	Thu May 24 15:02:06 2001
@@ -0,0 +1,21 @@
+/*
+ * BK Id: SCCS/s.nonstdio.h 1.7 05/18/01 15:17:23 cort
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+typedef int	FILE;
+extern FILE *stdin, *stdout;
+#define NULL	((void *)0)
+#define EOF	(-1)
+#define fopen(n, m)	NULL
+#define fflush(f)	0
+#define fclose(f)	0
+extern char *fgets();
+
+#define perror(s)	printf("%s: no files!\n", (s))
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/include/rs6000.h linux/arch/ppc/boot/include/rs6000.h
--- v2.4.4/linux/arch/ppc/boot/include/rs6000.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/include/rs6000.h	Thu May 24 15:02:06 2001
@@ -0,0 +1,246 @@
+/*
+ * BK Id: SCCS/s.rs6000.h 1.7 05/18/01 15:17:23 cort
+ */
+/* IBM RS/6000 "XCOFF" file definitions for BFD.
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+   FIXME: Can someone provide a transliteration of this name into ASCII?
+   Using the following chars caused a compiler warning on HIUX (so I replaced
+   them with octal escapes), and isn't useful without an understanding of what
+   character set it is.
+   Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+   and John Gilmore of Cygnus Support.  */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+	char f_magic[2];	/* magic number			*/
+	char f_nscns[2];	/* number of sections		*/
+	char f_timdat[4];	/* time & date stamp		*/
+	char f_symptr[4];	/* file pointer to symtab	*/
+	char f_nsyms[4];	/* number of symtab entries	*/
+	char f_opthdr[2];	/* sizeof(optional hdr)		*/
+	char f_flags[2];	/* flags			*/
+};
+
+        /* IBM RS/6000 */
+#define U802WRMAGIC     0730    /* writeable text segments **chh**      */
+#define U802ROMAGIC     0735    /* readonly sharable text segments      */
+#define U802TOCMAGIC    0737    /* readonly text segments and TOC       */
+
+#define BADMAG(x)	\
+	((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
+	 (x).f_magic != U802TOCMAGIC)
+
+#define	FILHDR	struct external_filehdr
+#define	FILHSZ	20
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct 
+{
+  unsigned char	magic[2];	/* type of file			*/
+  unsigned char	vstamp[2];	/* version stamp		*/
+  unsigned char	tsize[4];	/* text size in bytes, padded to FW bdry */
+  unsigned char	dsize[4];	/* initialized data "  "	*/
+  unsigned char	bsize[4];	/* uninitialized data "   "	*/
+  unsigned char	entry[4];	/* entry pt.			*/
+  unsigned char	text_start[4];	/* base of text used for this file */
+  unsigned char	data_start[4];	/* base of data used for this file */
+  unsigned char	o_toc[4];	/* address of TOC */
+  unsigned char	o_snentry[2];	/* section number of entry point */
+  unsigned char	o_sntext[2];	/* section number of .text section */
+  unsigned char	o_sndata[2];	/* section number of .data section */
+  unsigned char	o_sntoc[2];	/* section number of TOC */
+  unsigned char	o_snloader[2];	/* section number of .loader section */
+  unsigned char	o_snbss[2];	/* section number of .bss section */
+  unsigned char	o_algntext[2];	/* .text alignment */
+  unsigned char	o_algndata[2];	/* .data alignment */
+  unsigned char	o_modtype[2];	/* module type (??) */
+  unsigned char o_cputype[2];	/* cpu type */
+  unsigned char	o_maxstack[4];	/* max stack size (??) */
+  unsigned char o_maxdata[4];	/* max data size (??) */
+  unsigned char	o_resv2[12];	/* reserved */
+}
+AOUTHDR;
+
+#define AOUTSZ 72
+#define SMALL_AOUTSZ (28)
+#define AOUTHDRSZ 72
+
+#define	RS6K_AOUTHDR_OMAGIC	0x0107	/* old: text & data writeable */
+#define	RS6K_AOUTHDR_NMAGIC	0x0108	/* new: text r/o, data r/w */
+#define	RS6K_AOUTHDR_ZMAGIC	0x010B	/* paged: text r/o, both page-aligned */
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+	char		s_name[8];	/* section name			*/
+	char		s_paddr[4];	/* physical address, aliased s_nlib */
+	char		s_vaddr[4];	/* virtual address		*/
+	char		s_size[4];	/* section size			*/
+	char		s_scnptr[4];	/* file ptr to raw data for section */
+	char		s_relptr[4];	/* file ptr to relocation	*/
+	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
+	char		s_nreloc[2];	/* number of relocation entries	*/
+	char		s_nlnno[2];	/* number of line number entries*/
+	char		s_flags[4];	/* flags			*/
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT	".text"
+#define _DATA	".data"
+#define _BSS	".bss"
+#define _PAD	".pad"
+#define _LOADER	".loader"
+
+#define	SCNHDR	struct external_scnhdr
+#define	SCNHSZ	40
+
+/* XCOFF uses a special .loader section with type STYP_LOADER.  */
+#define STYP_LOADER 0x1000
+
+/* XCOFF uses a special .debug section with type STYP_DEBUG.  */
+#define STYP_DEBUG 0x2000
+
+/* XCOFF handles line number or relocation overflow by creating
+   another section header with STYP_OVRFLO set.  */
+#define STYP_OVRFLO 0x8000
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+	union {
+		char l_symndx[4];	/* function name symbol index, iff l_lnno == 0*/
+		char l_paddr[4];	/* (physical) address of line number	*/
+	} l_addr;
+	char l_lnno[2];	/* line number		*/
+};
+
+
+#define	LINENO	struct external_lineno
+#define	LINESZ	6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
+#define E_FILNMLEN	14	/* # characters in a file name		*/
+#define E_DIMNUM	4	/* # array dimensions in auxiliary entry */
+
+struct external_syment 
+{
+  union {
+    char e_name[E_SYMNMLEN];
+    struct {
+      char e_zeroes[4];
+      char e_offset[4];
+    } e;
+  } e;
+  char e_value[4];
+  char e_scnum[2];
+  char e_type[2];
+  char e_sclass[1];
+  char e_numaux[1];
+};
+
+
+
+#define N_BTMASK	(017)
+#define N_TMASK		(060)
+#define N_BTSHFT	(4)
+#define N_TSHIFT	(2)
+  
+
+union external_auxent {
+	struct {
+		char x_tagndx[4];	/* str, un, or enum tag indx */
+		union {
+			struct {
+			    char  x_lnno[2]; /* declaration line number */
+			    char  x_size[2]; /* str/union/array size */
+			} x_lnsz;
+			char x_fsize[4];	/* size of function */
+		} x_misc;
+		union {
+			struct {		/* if ISFCN, tag, or .bb */
+			    char x_lnnoptr[4];	/* ptr to fcn line # */
+			    char x_endndx[4];	/* entry ndx past block end */
+			} x_fcn;
+			struct {		/* if ISARY, up to 4 dimen. */
+			    char x_dimen[E_DIMNUM][2];
+			} x_ary;
+		} x_fcnary;
+		char x_tvndx[2];		/* tv index */
+	} x_sym;
+
+	union {
+		char x_fname[E_FILNMLEN];
+		struct {
+			char x_zeroes[4];
+			char x_offset[4];
+		} x_n;
+	} x_file;
+
+	struct {
+		char x_scnlen[4];			/* section length */
+		char x_nreloc[2];	/* # relocation entries */
+		char x_nlinno[2];	/* # line numbers */
+	} x_scn;
+
+        struct {
+		char x_tvfill[4];	/* tv fill value */
+		char x_tvlen[2];	/* length of .tv */
+		char x_tvran[2][2];	/* tv range */
+	} x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
+
+	struct {
+		unsigned char x_scnlen[4];
+		unsigned char x_parmhash[4];
+		unsigned char x_snhash[2];
+		unsigned char x_smtyp[1];
+		unsigned char x_smclas[1];
+		unsigned char x_stab[4];
+		unsigned char x_snstab[2];
+	} x_csect;
+
+};
+
+#define	SYMENT	struct external_syment
+#define	SYMESZ	18	
+#define	AUXENT	union external_auxent
+#define	AUXESZ	18
+#define DBXMASK 0x80		/* for dbx storage mask */
+#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+  char r_vaddr[4];
+  char r_symndx[4];
+  char r_size[1];
+  char r_type[1];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/include/zlib.h linux/arch/ppc/boot/include/zlib.h
--- v2.4.4/linux/arch/ppc/boot/include/zlib.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/include/zlib.h	Thu May 24 15:02:06 2001
@@ -0,0 +1,433 @@
+/*
+ * BK Id: SCCS/s.zlib.h 1.8 05/18/01 15:17:23 cort
+ */
+/*
+ * This file is derived from zlib.h and zconf.h from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.
+ */
+
+/*
+ *  ==FILEVERSION 960122==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 0.95, Aug 16th, 1995.
+
+  Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
+ */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+/* #include "zconf.h" */	/* included directly here */
+
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
+
+/*
+     The library does not install any signal handler. It is recommended to
+  add at least a handler for SIGSEGV when decompressing; the library checks
+  the consistency of the input data whenever possible but may go nuts
+  for some forms of corrupted input.
+ */
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
+ * at addresses which are not a multiple of their size.
+ * Under DOS, -DFAR=far or -DFAR=__far may be needed.
+ */
+
+#ifndef STDC
+#  if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
+#    define STDC
+#  endif
+#endif
+
+#ifdef	__MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
+#  include <unix.h>
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            1 << (windowBits+2)   +  1 << (memLevel+9)
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte FAR Bytef;
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+/* end of original zconf.h */
+
+#define ZLIB_VERSION "0.95P"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms may be added later and will have the same
+  stream interface.
+
+     For compression the application must provide the output buffer and
+  may optionally provide the input buffer for optimization. For decompression,
+  the application must provide the input buffer and may optionally provide
+  the output buffer for optimization.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address, uInt nbytes));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidp      opaque;  /* private data object passed to zalloc and zfree */
+
+    Byte     data_type; /* best guess about the data type: ascii or binary */
+
+} z_stream;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_FULL_FLUSH    2
+#define Z_SYNC_FLUSH    3 /* experimental: partial_flush + byte align */
+#define Z_FINISH        4
+#define Z_PACKET_FLUSH	5
+/* See deflate() below for the usage of these constants */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+/* error codes for the compression/decompression functions */
+
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Used to set the data_type field */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+extern char *zlib_version;
+/* The application can compare zlib_version and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+ */
+
+                        /* basic functions */
+
+extern int inflateInit OF((z_stream *strm));
+/* 
+     Initializes the internal stream state for decompression. The fields
+   zalloc and zfree must be initialized before by the caller.  If zalloc and
+   zfree are set to Z_NULL, inflateInit updates them to use default allocation
+   functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory.  msg is set to null if there is no error message.
+   inflateInit does not perform any decompression: this will be done by
+   inflate().
+*/
+
+
+extern int inflate OF((z_stream *strm, int flush));
+/*
+  Performs one or both of the following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() always provides as much output as possible
+    (until there is no more input data or no more space in the output buffer).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate().
+
+    If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
+  inflate flushes as much output as possible to the output buffer. The
+  flushing behavior of inflate is not specified for values of the flush
+  parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+  current implementation actually flushes as much output as possible
+  anyway.  For Z_PACKET_FLUSH, inflate checks that once all the input data
+  has been consumed, it is expecting to see the length field of a stored
+  block; if not, it returns Z_DATA_ERROR.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+    inflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if the end of the
+  compressed data has been reached and all uncompressed output has been
+  produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
+  the stream structure was inconsistent (for example if next_in or next_out
+  was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
+  progress is possible or if there was not enough room in the output buffer
+  when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
+  call inflateSync to look for a good compression block.  */
+
+
+extern int inflateEnd OF((z_stream *strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* advanced functions */
+
+extern int inflateInit2 OF((z_stream *strm,
+                            int  windowBits));
+/*   
+     This is another version of inflateInit with more compression options. The
+   fields next_out, zalloc and zfree must be initialized before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library (the value 16 will be allowed soon). The
+   default value is 15 if inflateInit is used instead. If a compressed stream
+   with a larger window size is given as input, inflate() will return with
+   the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     If next_out is not null, the library will use this buffer for the history
+   buffer; the buffer must either be large enough to hold the entire output
+   data, or have at least 1<<windowBits bytes.  If next_out is null, the
+   library will allocate its own buffer (and leave next_out null). next_in
+   need not be provided here but must be provided by the application for the
+   next call of inflate().
+
+     If the history buffer is provided by the application, next_out must
+   never be changed by the application since the decompressor maintains
+   history information inside this buffer from call to call; the application
+   can only reset next_out to the beginning of the history buffer when
+   avail_out is zero and all output has been consumed.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+   windowBits < 8). msg is set to null if there is no error message.
+   inflateInit2 does not perform any decompression: this will be done by
+   inflate().
+*/
+
+extern int inflateSync OF((z_stream *strm));
+/* 
+    Skips invalid compressed data until the special marker (see deflate()
+  above) can be found, or until all available input is skipped. No output
+  is provided.
+
+    inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no marker has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+extern int inflateReset OF((z_stream *strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+extern int inflateIncomp OF((z_stream *strm));
+/*
+     This function adds the data at next_in (avail_in bytes) to the output
+   history without performing any output.  There must be no pending output,
+   and the decompressor must be expecting to see the start of a block.
+   Calling this function is equivalent to decompressing a stored block
+   containing the data at next_in (except that the data is not output).
+*/
+
+                        /* checksum functions */
+
+/*
+     This function is not related to compression but is exported
+   anyway because it might be useful in applications using the
+   compression library.
+*/
+
+extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+#ifndef _Z_UTIL_H
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+#endif /* _ZLIB_H */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/iso_font.h linux/arch/ppc/boot/iso_font.h
--- v2.4.4/linux/arch/ppc/boot/iso_font.h	Wed Dec 18 00:49:52 1996
+++ linux/arch/ppc/boot/iso_font.h	Wed Dec 31 16:00:00 1969
@@ -1,257 +0,0 @@
-static const unsigned char font[] = {
-/* 0x00 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x01 */ 0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,
-/* 0x02 */ 0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00,
-/* 0x03 */ 0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,
-/* 0x04 */ 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
-/* 0x05 */ 0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x06 */ 0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x07 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x08 */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-/* 0x09 */ 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,
-/* 0x0A */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,
-/* 0x0B */ 0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
-/* 0x0C */ 0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x0D */ 0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,
-/* 0x0E */ 0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,
-/* 0x0F */ 0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x10 */ 0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
-/* 0x11 */ 0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
-/* 0x12 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
-/* 0x13 */ 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
-/* 0x14 */ 0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,
-/* 0x15 */ 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,
-/* 0x16 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,
-/* 0x17 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
-/* 0x18 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x19 */ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,
-/* 0x1A */ 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x1B */ 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x1C */ 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x1D */ 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x1E */ 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,
-/* 0x1F */ 0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
-/* 0x20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x21 */ 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x22 */ 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x23 */ 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,
-/* 0x24 */ 0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,
-/* 0x25 */ 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,
-/* 0x26 */ 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x27 */ 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x28 */ 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,
-/* 0x29 */ 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,
-/* 0x2A */ 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x2B */ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x2C */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
-/* 0x2D */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x2E */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x2F */ 0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,
-/* 0x30 */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
-/* 0x31 */ 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
-/* 0x32 */ 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
-/* 0x33 */ 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x34 */ 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
-/* 0x35 */ 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x36 */ 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x37 */ 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
-/* 0x38 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x39 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
-/* 0x3A */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
-/* 0x3B */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
-/* 0x3C */ 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,
-/* 0x3D */ 0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x3E */ 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
-/* 0x3F */ 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x40 */ 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00,
-/* 0x41 */ 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x42 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,
-/* 0x43 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,
-/* 0x44 */ 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
-/* 0x45 */ 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
-/* 0x46 */ 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
-/* 0x47 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,
-/* 0x48 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x49 */ 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x4A */ 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
-/* 0x4B */ 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
-/* 0x4C */ 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
-/* 0x4D */ 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x4E */ 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x4F */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x50 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
-/* 0x51 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,
-/* 0x52 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
-/* 0x53 */ 0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x54 */ 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x55 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x56 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
-/* 0x57 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,
-/* 0x58 */ 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x59 */ 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x5A */ 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,
-/* 0x5B */ 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
-/* 0x5C */ 0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
-/* 0x5D */ 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,
-/* 0x5E */ 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x5F */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,
-/* 0x60 */ 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x61 */ 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x62 */ 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,
-/* 0x63 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x64 */ 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x65 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x66 */ 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
-/* 0x67 */ 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,
-/* 0x68 */ 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
-/* 0x69 */ 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x6A */ 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,
-/* 0x6B */ 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,
-/* 0x6C */ 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x6D */ 0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x6E */ 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
-/* 0x6F */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x70 */ 0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
-/* 0x71 */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
-/* 0x72 */ 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
-/* 0x73 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x74 */ 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,
-/* 0x75 */ 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x76 */ 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,
-/* 0x77 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,
-/* 0x78 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,
-/* 0x79 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
-/* 0x7A */ 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
-/* 0x7B */ 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,
-/* 0x7C */ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x7D */ 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
-/* 0x7E */ 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0x7F */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,
-/* 0x80 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,
-/* 0x81 */ 0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x82 */ 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x83 */ 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x84 */ 0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x85 */ 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x86 */ 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x87 */ 0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,
-/* 0x88 */ 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x89 */ 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x8A */ 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x8B */ 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x8C */ 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x8D */ 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0x8E */ 0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x8F */ 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0x90 */ 0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00,
-/* 0x91 */ 0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,
-/* 0x92 */ 0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,
-/* 0x93 */ 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x94 */ 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x95 */ 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x96 */ 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x97 */ 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0x98 */ 0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
-/* 0x99 */ 0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x9A */ 0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0x9B */ 0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x9C */ 0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,
-/* 0x9D */ 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0x9E */ 0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,
-/* 0x9F */ 0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,
-/* 0xA0 */ 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0xA1 */ 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
-/* 0xA2 */ 0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0xA3 */ 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
-/* 0xA4 */ 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
-/* 0xA5 */ 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0xA6 */ 0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xA7 */ 0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xA8 */ 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
-/* 0xA9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,
-/* 0xAA */ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
-/* 0xAB */ 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,
-/* 0xAC */ 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00,
-/* 0xAD */ 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,
-/* 0xAE */ 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xAF */ 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xB0 */ 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
-/* 0xB1 */ 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
-/* 0xB2 */ 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,
-/* 0xB3 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xB4 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xB5 */ 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xB6 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xB7 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xB8 */ 0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xB9 */ 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xBA */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xBB */ 0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xBC */ 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xBD */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xBE */ 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xBF */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xC0 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xC1 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xC2 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xC3 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xC4 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xC5 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xC6 */ 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xC7 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xC8 */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xC9 */ 0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xCA */ 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xCB */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xCC */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xCD */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xCE */ 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xCF */ 0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xD0 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xD1 */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xD2 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xD3 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xD4 */ 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xD5 */ 0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xD6 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xD7 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
-/* 0xD8 */ 0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xD9 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xDA */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xDB */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-/* 0xDC */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-/* 0xDD */ 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
-/* 0xDE */ 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
-/* 0xDF */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xE0 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,
-/* 0xE1 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00,
-/* 0xE2 */ 0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,
-/* 0xE3 */ 0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,
-/* 0xE4 */ 0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
-/* 0xE5 */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
-/* 0xE6 */ 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00,
-/* 0xE7 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
-/* 0xE8 */ 0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
-/* 0xE9 */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
-/* 0xEA */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,
-/* 0xEB */ 0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,
-/* 0xEC */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xED */ 0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,
-/* 0xEE */ 0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,
-/* 0xEF */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
-/* 0xF0 */ 0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,
-/* 0xF1 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
-/* 0xF2 */ 0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00,
-/* 0xF3 */ 0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00,
-/* 0xF4 */ 0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
-/* 0xF5 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
-/* 0xF6 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
-/* 0xF7 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xF8 */ 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xF9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xFA */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xFB */ 0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,
-/* 0xFC */ 0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xFD */ 0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-/* 0xFE */ 0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,
-};
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/kbd.c linux/arch/ppc/boot/kbd.c
--- v2.4.4/linux/arch/ppc/boot/kbd.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/boot/kbd.c	Wed Dec 31 16:00:00 1969
@@ -1,210 +0,0 @@
-#include <linux/keyboard.h>
-
-#include <../drivers/char/defkeymap.c>	/* yeah I know it's bad -- Cort */
-
-
-unsigned char shfts, ctls, alts, caps;
-
-#define	KBDATAP		0x60	/* kbd data port */
-#define	KBSTATUSPORT	0x61	/* kbd status */
-#define	KBSTATP		0x64	/* kbd status port */
-#define	KBINRDY		0x01
-#define	KBOUTRDY	0x02
-
-
-static int kbd(int noblock)
-{
-	unsigned char dt, brk, val;
-	unsigned code;
-loop:
-	if (noblock) {
-	    if ((inb(KBSTATP) & KBINRDY) == 0)
-		return (-1);
-	} else while((inb(KBSTATP) & KBINRDY) == 0) ;
-
-	dt = inb(KBDATAP);
-
-	brk = dt & 0x80;	/* brk == 1 on key release */
-	dt = dt & 0x7f;		/* keycode */
-
-	if (shfts)
-	    code = shift_map[dt];
-	else if (ctls)
-	    code = ctrl_map[dt];
-	else
-	    code = plain_map[dt];
-
-	val = KVAL(code);
-	switch (KTYP(code) & 0x0f) {
-	    case KT_LATIN:
-		if (brk)
-		    break;
-		if (alts)
-		    val |= 0x80;
-		if (val == 0x7f)	/* map delete to backspace */
-		    val = '\b';
-		return val;
-
-	    case KT_LETTER:
-		if (brk)
-		    break;
-		if (caps)
-		    val -= 'a'-'A';
-		return val;
-
-	    case KT_SPEC:
-		if (brk)
-		    break;
-		if (val == KVAL(K_CAPS))
-		    caps = !caps;
-		else if (val == KVAL(K_ENTER)) {
-enter:		    /* Wait for key up */
-		    while (1) {
-			while((inb(KBSTATP) & KBINRDY) == 0) ;
-			dt = inb(KBDATAP);
-			if (dt & 0x80) /* key up */ break;
-		    }
-		    return 10;
-		}
-		break;
-
-	    case KT_PAD:
-		if (brk)
-		    break;
-		if (val < 10)
-		    return val;
-		if (val == KVAL(K_PENTER))
-		    goto enter;
-		break;
-
-	    case KT_SHIFT:
-		switch (val) {
-		    case KG_SHIFT:
-		    case KG_SHIFTL:
-		    case KG_SHIFTR:
-			shfts = brk ? 0 : 1;
-			break;
-		    case KG_ALT:
-		    case KG_ALTGR:
-			alts = brk ? 0 : 1;
-			break;
-		    case KG_CTRL:
-		    case KG_CTRLL:
-		    case KG_CTRLR:
-			ctls = brk ? 0 : 1;
-			break;
-		}
-		break;
-
-	    case KT_LOCK:
-		switch (val) {
-		    case KG_SHIFT:
-		    case KG_SHIFTL:
-		    case KG_SHIFTR:
-			if (brk)
-			    shfts = !shfts;
-			break;
-		    case KG_ALT:
-		    case KG_ALTGR:
-			if (brk)
-			    alts = !alts;
-			break;
-		    case KG_CTRL:
-		    case KG_CTRLL:
-		    case KG_CTRLR:
-			if (brk)
-			    ctls = !ctls;
-			break;
-		}
-		break;
-	}
-	if (brk) return (-1);  /* Ignore initial 'key up' codes */
-	goto loop;
-}
-
-static void kbdreset(void)
-{
-	unsigned char c;
-	int i;
-
-	/* flush input queue */
-	while ((inb(KBSTATP) & KBINRDY))
-	{
-		(void)inb(KBDATAP);
-	}
-	/* Send self-test */
-	while (inb(KBSTATP) & KBOUTRDY) ;
-	outb(KBSTATP,0xAA);
-	while ((inb(KBSTATP) & KBINRDY) == 0) ;	/* wait input ready */
-	if ((c = inb(KBDATAP)) != 0x55)
-	{
-		puts("Keyboard self test failed - result:");
-		puthex(c);
-		puts("\n");
-	}
-	/* Enable interrupts and keyboard controller */
-	while (inb(KBSTATP) & KBOUTRDY) ;
-	outb(KBSTATP,0x60);	
-	while (inb(KBSTATP) & KBOUTRDY) ;
-	outb(KBDATAP,0x45);
-	for (i = 0;  i < 10000;  i++) udelay(1);
-	
-	while (inb(KBSTATP) & KBOUTRDY) ;
-	outb(KBSTATP,0x20);
-	while ((inb(KBSTATP) & KBINRDY) == 0) ; /* wait input ready */
-	if (! (inb(KBDATAP) & 0x40)) {
-		/*
-		 * Quote from PS/2 System Reference Manual:
-		 *
-		 * "Address hex 0060 and address hex 0064 should be
-		 * written only when the input-buffer-full bit and
-		 * output-buffer-full bit in the Controller Status
-		 * register are set 0." (KBINRDY and KBOUTRDY)
-		 */
-		
-		while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
-		outb(KBDATAP,0xF0);
-		while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
-		outb(KBDATAP,0x01);
-	}
-	
-	while (inb(KBSTATP) & KBOUTRDY) ;
-	outb(KBSTATP,0xAE);
-}
-
-/* We have to actually read the keyboard when CRT_tstc is called,
- * since the pending data might be a key release code, and therefore
- * not valid data.  In this case, kbd() will return -1, even though there's
- * data to be read.  Of course, we might actually read a valid key press,
- * in which case it gets queued into key_pending for use by CRT_getc.
- */
-
-static int kbd_reset = 0;
-
-static int key_pending = -1;
-
-int CRT_getc(void)
-{
-	int c;
-	if (!kbd_reset) {kbdreset(); kbd_reset++; }
-
-        if (key_pending != -1) {
-                c = key_pending;
-                key_pending = -1;
-                return c;
-        } else {
-	while ((c = kbd(0)) == 0) ;
-                return c;
-        }
-}
-
-int CRT_tstc(void)
-{
-	if (!kbd_reset) {kbdreset(); kbd_reset++; }
-
-        while (key_pending == -1 && ((inb(KBSTATP) & KBINRDY) != 0)) {
-                key_pending = kbd(1);
-        }
-
-        return (key_pending != -1);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/lib/Makefile linux/arch/ppc/boot/lib/Makefile
--- v2.4.4/linux/arch/ppc/boot/lib/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/lib/Makefile	Thu May 24 15:02:06 2001
@@ -0,0 +1,9 @@
+#
+# Makefile for some libs needed by zImage.
+#
+
+L_TARGET := zlib.a
+
+obj-y := zlib.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/lib/zlib.c linux/arch/ppc/boot/lib/zlib.c
--- v2.4.4/linux/arch/ppc/boot/lib/zlib.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/lib/zlib.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,2150 @@
+/*
+ * BK Id: SCCS/s.zlib.c 1.8 05/18/01 15:17:24 cort
+ */
+/*
+ * This file is derived from various .h and .c files from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.  See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - changed functions not used outside this file to "local"
+ * - added minCompression parameter to deflateInit2
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp
+ *
+ */
+
+/*+++++*/
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
+
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#define FAR
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern char *z_errmsg[]; /* indexed by 1-zlib_error */
+
+#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
+/* To be used only when the state is known to be valid */
+
+#ifndef NULL
+#define NULL	((void *) 0)
+#endif
+
+        /* common constants */
+
+#define DEFLATED   8
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+         /* functions */
+
+#include <linux/string.h>
+#define zmemcpy memcpy
+#define zmemzero(dest, len)	memset(dest, 0, len)
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+#  include <stdio.h>
+#  ifndef verbose
+#    define verbose 0
+#  endif
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
+
+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
+/* void   zcfree  OF((voidpf opaque, voidpf ptr)); */
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr, size)	\
+	   (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
+
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/*+++++*/
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+    z_stream *z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+local int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));                      /* initial return code */
+
+local void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    uLongf *));                  /* check value on output */
+
+local int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    uLongf *));                  /* check value on output */
+
+local int inflate_addhistory OF((
+    inflate_blocks_statef *,
+    z_stream *));
+
+local int inflate_packet_flush OF((
+    inflate_blocks_statef *));
+
+/*+++++*/
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt Nalloc;	/* number of these allocated here */
+    Bytef *pad;         /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit machines) */
+  union {
+    uInt Base;          /* literal, length base, or distance base */
+    inflate_huft *Next; /* pointer to next level of table */
+  } more;
+};
+
+#ifdef DEBUG_ZLIB
+  local uInt inflate_hufts;
+#endif
+
+local int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    z_stream *));               /* for zalloc, zfree functions */
+
+local int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_stream *));               /* for zalloc, zfree functions */
+
+local int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *));     /* distance tree result */
+
+local int inflate_trees_free OF((
+    inflate_huft *,             /* tables to free */
+    z_stream *));               /* for zfree function */
+
+
+/*+++++*/
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_stream *));
+
+local int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));
+
+local void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_stream *));
+
+
+/*+++++*/
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+    mode;               /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+int inflateReset(z)
+z_stream *z;
+{
+  uLong c;
+
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, &c);
+  Trace((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int inflateEnd(z)
+z_stream *z;
+{
+  uLong c;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z, &c);
+  ZFREE(z, z->state, sizeof(struct internal_state));
+  z->state = Z_NULL;
+  Trace((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int inflateInit2(z, w)
+z_stream *z;
+int w;
+{
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+/*  if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
+/*  if (z->zfree == Z_NULL) z->zfree = zcfree; */
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Trace((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int inflateInit(z)
+z_stream *z;
+{
+  return inflateInit2(z, DEF_WBITS);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(z, f)
+z_stream *z;
+int f;
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = "unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = "invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      if ((b = NEXTBYTE) & 0x20)
+      {
+        z->state->mode = BAD;
+        z->msg = "invalid reserved bit";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = "incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Trace((stderr, "inflate: zlib header ok\n"));
+      z->state->mode = BLOCKS;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+	  r = inflate_packet_flush(z->state->blocks);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r != Z_STREAM_END)
+        return r;
+      r = Z_OK;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = "incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Trace((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+
+ empty:
+  if (f != Z_PACKET_FLUSH)
+    return r;
+  z->state->mode = BAD;
+  z->state->sub.marker = 0;       /* can try inflateSync */
+  return Z_DATA_ERROR;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int inflateIncomp(z)
+z_stream *z;
+{
+    if (z->state->mode != BLOCKS)
+	return Z_DATA_ERROR;
+    return inflate_addhistory(z->state->blocks, z);
+}
+
+
+int inflateSync(z)
+z_stream *z;
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    if (*p == (Byte)(m < 2 ? 0 : 0xff))
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+#undef NEEDBYTE
+#undef NEXTBYTE
+
+/*+++++*/
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONEB,     /* finished last block, done */
+      BADB}      /* got a data error--stuck here */
+    mode;               /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+      int nblens;		/* # elements allocated at blens */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_huft *tl, *td;    /* trees to free */
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/*
+ * The IBM 150 firmware munges the data right after _etext[].  This
+ * protects it. -- Cort
+ */
+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
+/* And'ing with mask[n] masks the lower n bits */
+local uInt inflate_mask[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));
+
+/*+++++*/
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_stream *));
+
+
+/*+++++*/
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+  if (s->checkfn != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+  if (s->mode == CODES)
+  {
+    inflate_codes_free(s->sub.decode.codes, z);
+    inflate_trees_free(s->sub.decode.td, z);
+    inflate_trees_free(s->sub.decode.tl, z);
+  }
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(0L, Z_NULL, 0);
+  Trace((stderr, "inflate:   blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_stream *z;
+check_func c;
+uInt w;
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s, sizeof(struct inflate_blocks_state));
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Trace((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, &s->check);
+  return s;
+}
+
+
+local int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Trace((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Trace((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+            s->sub.decode.tl = Z_NULL;  /* don't try to free these */
+            s->sub.decode.td = Z_NULL;
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Trace((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BADB;
+          z->msg = "invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if (((~b) >> 16) != (b & 0xffff))
+      {
+        s->mode = BADB;
+        z->msg = "invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : TYPE;
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BADB;
+        z->msg = "too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if (t < 19)
+        t = 19;
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      s->sub.trees.nblens = t;
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, z);
+      if (t != Z_OK)
+      {
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BADB;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->word.what.Bits;
+        c = h->more.Base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            s->mode = BADB;
+            z->msg = "invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      inflate_trees_free(s->sub.trees.tb, z);
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BADB;
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          inflate_trees_free(td, z);
+          inflate_trees_free(tl, z);
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+        s->sub.decode.codes = c;
+        s->sub.decode.tl = tl;
+        s->sub.decode.td = td;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      inflate_trees_free(s->sub.decode.td, z);
+      inflate_trees_free(s->sub.decode.tl, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      if (k > 7)              /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;                    /* can always return one */
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONEB;
+    case DONEB:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADB:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+local int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+  inflate_blocks_reset(s, z, c);
+  ZFREE(z, s->window, s->end - s->window);
+  ZFREE(z, s, sizeof(struct inflate_blocks_state));
+  Trace((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+local int inflate_addhistory(s, z)
+inflate_blocks_statef *s;
+z_stream *z;
+{
+    uLong b;              /* bit buffer */  /* NOT USED HERE */
+    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
+    uInt t;               /* temporary storage */
+    Bytef *p;             /* input data pointer */
+    uInt n;               /* bytes available there */
+    Bytef *q;             /* output window write pointer */
+    uInt m;               /* bytes to end of window or read pointer */
+
+    if (s->read != s->write)
+	return Z_STREAM_ERROR;
+    if (s->mode != TYPE)
+	return Z_DATA_ERROR;
+
+    /* we're ready to rock */
+    LOAD
+    /* while there is input ready, copy to output buffer, moving
+     * pointers as needed.
+     */
+    while (n) {
+	t = n;  /* how many to do */
+	/* is there room until end of buffer? */
+	if (t > m) t = m;
+	/* update check information */
+	if (s->checkfn != Z_NULL)
+	    s->check = (*s->checkfn)(s->check, q, t);
+	zmemcpy(q, p, t);
+	q += t;
+	p += t;
+	n -= t;
+	z->total_out += t;
+	s->read = q;    /* drag read pointer forward */
+/*      WRAP  */ 	/* expand WRAP macro by hand to handle s->read */
+	if (q == s->end) {
+	    s->read = q = s->window;
+	    m = WAVAIL;
+	}
+    }
+    UPDATE
+    return Z_OK;
+}
+
+
+/*
+ * At the end of a Deflate-compressed PPP packet, we expect to have seen
+ * a `stored' block type value but not the (zero) length bytes.
+ */
+local int inflate_packet_flush(s)
+    inflate_blocks_statef *s;
+{
+    if (s->mode != LENS)
+	return Z_DATA_ERROR;
+    s->mode = TYPE;
+    return Z_OK;
+}
+
+
+/*+++++*/
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    uIntf *,            /* list of base values for non-simple codes */
+    uIntf *,            /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    z_stream *));       /* for zalloc function */
+
+local voidpf falloc OF((
+    voidpf,             /* opaque pointer (not used) */
+    uInt,               /* number of items */
+    uInt));             /* size of item */
+
+local void ffree OF((
+    voidpf q,           /* opaque pointer (not used) */
+    voidpf p,           /* what to free (not used) */
+    uInt n));		/* number of bytes (not used) */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* actually lengths - 2; also see note #13 above about 258 */
+local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+local uInt cpdext[] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+#ifdef DEBUG_ZLIB
+  uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
+uInt n;                 /* number of codes (assumed <= N_MAX) */
+uInt s;                 /* number of simple-valued codes (0..s-1) */
+uIntf *d;               /* list of base values for non-simple codes */
+uIntf *e;               /* list of extra bits for non-simple codes */  
+inflate_huft * FAR *t;  /* result: starting table */
+uIntf *m;               /* maximum lookup bits, returns actual */
+z_stream *zs;           /* for zalloc function */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
+   over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  uInt v[N_MAX];                /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = (z = g - w) > (uInt)l ? l : z;      /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        if ((q = (inflate_huft *)ZALLOC
+             (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+        {
+          if (h)
+            inflate_trees_free(u[0], zs);
+          return Z_MEM_ERROR;   /* not enough memory */
+        }
+	q->word.Nalloc = z + 1;
+#ifdef DEBUG_ZLIB
+        inflate_hufts += z + 1;
+#endif
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->next)) = Z_NULL;
+        u[h] = ++q;             /* table starts after link */
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          r.next = q;           /* pointer to this table */
+          j = i >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits(c, bb, tb, z)
+uIntf *c;               /* 19 code lengths */
+uIntf *bb;              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_stream *z;            /* for zfree function */
+{
+  int r;
+
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+  if (r == Z_DATA_ERROR)
+    z->msg = "oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR)
+  {
+    inflate_trees_free(*tb, z);
+    z->msg = "incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  return r;
+}
+
+
+local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
+uInt nl;                /* number of literal/length codes */
+uInt nd;                /* number of distance codes */
+uIntf *c;               /* that many (total) code lengths */
+uIntf *bl;              /* literal desired/actual bit depth */
+uIntf *bd;              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_stream *z;            /* for zfree function */
+{
+  int r;
+
+  /* build literal/length tree */
+  if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = "oversubscribed literal/length tree";
+    else if (r == Z_BUF_ERROR)
+    {
+      inflate_trees_free(*tl, z);
+      z->msg = "incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    return r;
+  }
+
+  /* build distance tree */
+  if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = "oversubscribed literal/length tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      inflate_trees_free(*td, z);
+      z->msg = "incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    inflate_trees_free(*tl, z);
+    return r;
+#endif
+  }
+
+  /* done */
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_lock = 0;
+local int fixed_built = 0;
+#define FIXEDH 530      /* number of hufts used by fixed tables */
+local uInt fixed_left = FIXEDH;
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(q, n, s)
+voidpf q;        /* opaque pointer (not used) */
+uInt n;         /* number of items */
+uInt s;         /* size of item */
+{
+  Assert(s == sizeof(inflate_huft) && n <= fixed_left,
+         "inflate_trees falloc overflow");
+  if (q) s++; /* to make some compilers happy */
+  fixed_left -= n;
+  return (voidpf)(fixed_mem + fixed_left);
+}
+
+
+local void ffree(q, p, n)
+voidpf q;
+voidpf p;
+uInt n;
+{
+  Assert(0, "inflate_trees ffree called!");
+  if (q) q = p; /* to make some compilers happy */
+}
+
+
+local int inflate_trees_fixed(bl, bd, tl, td)
+uIntf *bl;               /* literal desired/actual bit depth */
+uIntf *bd;               /* distance desired/actual bit depth */
+inflate_huft * FAR *tl;  /* literal/length tree result */
+inflate_huft * FAR *td;  /* distance tree result */
+{
+  /* build fixed tables if not built already--lock out other instances */
+  while (++fixed_lock > 1)
+    fixed_lock--;
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    unsigned c[288];    /* length list for huft_build */
+    z_stream z;         /* for falloc function */
+
+    /* set up fake z_stream for memory routines */
+    z.zalloc = falloc;
+    z.zfree = ffree;
+    z.opaque = Z_NULL;
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 7;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+    /* done */
+    fixed_built = 1;
+  }
+  fixed_lock--;
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
+
+
+local int inflate_trees_free(t, z)
+inflate_huft *t;        /* table to free */
+z_stream *z;            /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register inflate_huft *p, *q;
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != Z_NULL)
+  {
+    q = (--p)->next;
+    ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
+    p = q;
+  } 
+  return Z_OK;
+}
+
+/*+++++*/
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+    mode;               /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+z_stream *z;
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+local int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t->next;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = "invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t->next;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = "invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (q - s->window));
+#endif
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+local void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_stream *z;
+{
+  ZFREE(z, c, sizeof(struct inflate_codes_state));
+  Tracev((stderr, "inflate:       codes free\n"));
+}
+
+/*+++++*/
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+  uInt n;
+  Bytef *p, *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
+
+
+/*+++++*/
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+local int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+inflate_blocks_statef *s;
+z_stream *z;
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (q - s->window);  /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+          else
+          {
+            z->msg = "invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = "invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
+
+
+/*+++++*/
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
+
+char *zlib_version = ZLIB_VERSION;
+
+char *z_errmsg[] = {
+"stream end",          /* Z_STREAM_END    1 */
+"",                    /* Z_OK            0 */
+"file error",          /* Z_ERRNO        (-1) */
+"stream error",        /* Z_STREAM_ERROR (-2) */
+"data error",          /* Z_DATA_ERROR   (-3) */
+"insufficient memory", /* Z_MEM_ERROR    (-4) */
+"buffer error",        /* Z_BUF_ERROR    (-5) */
+""};
+
+
+/*+++++*/
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf)  {s1 += *buf++; s2 += s1;}
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+#define DO16(buf) DO8(buf); DO8(buf);
+
+/* ========================================================================= */
+uLong adler32(adler, buf, len)
+    uLong adler;
+    Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+            k -= 16;
+        }
+        if (k != 0) do {
+            DO1(buf);
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/Makefile linux/arch/ppc/boot/mbx/Makefile
--- v2.4.4/linux/arch/ppc/boot/mbx/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/Makefile	Thu May 24 15:02:06 2001
@@ -0,0 +1,127 @@
+# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch
+#
+#
+# arch/ppc/mbxboot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
+#
+.c.s:
+	$(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+	$(AS) -o $*.o $<
+.c.o:
+	$(CC) $(CFLAGS) -c -o $*.o $<
+.S.s:
+	$(CPP) $(AFLAGS) -traditional -o $*.o $<
+.S.o:
+	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
+
+TFTPIMAGE	:= /tftpboot/zImage.embedded
+
+OFFSET		:= ../utils/offset
+SIZE		:= ../utils/size
+
+LIBS		:= ../lib/zlib.a
+OBJCOPY_ARGS	:= -O elf32-powerpc
+
+ifdef CONFIG_8xx
+ZLINKFLAGS	:= -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00180000
+OBJECTS		:= head.o m8xx_tty.o
+CFLAGS		+= -DCONFIG_8xx
+endif
+
+ifdef CONFIG_8260
+ZLINKFLAGS	:= -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00400000
+OBJECTS		:= head_8260.o m8260_tty.o embed_config.o
+CFLAGS		+= -DCONFIG_8260
+endif
+
+OBJECTS		+= ../common/misc-common.o misc.o ../common/string.o
+OBJCOPY_ARGS = -O elf32-powerpc
+
+ifeq ($(CONFIG_MBX),y)
+OBJECTS		+= iic.o embed_config.o pci.o qspan_pci.o
+CFLAGS		+= -DCONFIG_MBX
+endif
+ifeq ($(CONFIG_RPXLITE),y)
+CFLAGS		+= -DCONFIG_RPXLITE
+OBJECTS		+= iic.o embed_config.o
+endif
+ifeq ($(CONFIG_RPXCLASSIC),y)
+CFLAGS		+= -DCONFIG_RPXCLASSIC
+OBJECTS		+= iic.o embed_config.o pci.o qspan_pci.o
+endif
+ifeq ($(CONFIG_BSEIP),y)
+CFLAGS		+= -DCONFIG_BSEIP
+OBJECTS		+= iic.o embed_config.o
+endif
+ifeq ($(CONFIG_FADS),y)
+CFLAGS		+= -DCONFIG_FADS
+OBJECTS		+= embed_config.o
+endif
+
+all:	zImage
+
+misc.o: misc.c
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \
+		-DZIMAGE_SIZE=0 -c -o $@ $*.c
+
+zvmlinux.initrd: $(OBJECTS) $(LIBS) ../images/vmlinux.gz
+	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=initrd=../images/ramdisk.image.gz \
+		--add-section=image=../images/vmlinux.gz \
+		$@.tmp $@
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ initrd` \
+		-DINITRD_SIZE=`sh $(SIZE) $(OBJDUMP) $@ initrd` \
+		-DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ image` \
+		-DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) $@ image` \
+		-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=initrd=../images/ramdisk.image.gz \
+		--add-section=image=../images/vmlinux.gz \
+		$@.tmp ../images/$@.mbx
+
+zImage: zvmlinux
+	ln -sf zvmlinux.mbx ../images/zImage.mbx
+
+zImage.initrd: zvmlinux.initrd
+	ln -sf zvmlinux.initrd.mbx ../images/zImage.initrd.mbx
+
+zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz
+#
+# build the boot loader image and then compute the offset into it
+# for the kernel image
+#
+	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=image=../images/vmlinux.gz \
+		$@.tmp $@
+#
+# then with the offset rebuild the bootloader so we know where the kernel is
+#
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
+		-DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ image` \
+		-DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) $@ image` \
+		-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=image=../images/vmlinux.gz \
+		$@.tmp ../images/$@.mbx
+# Remove zvmlinux and zvmlinux.temp, we have ../images/zvmlinux.mbx
+	rm -f $@.tmp $@
+
+znetboot : zImage
+	cp ../images/zImage.mbx $(TFTPIMAGE)
+
+znetboot.initrd : zImage.initrd
+	cp ../images/zImage.initrd.mbx $(TFTPIMAGE)
+
+include $(TOPDIR)/Rules.make 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/embed_config.c linux/arch/ppc/boot/mbx/embed_config.c
--- v2.4.4/linux/arch/ppc/boot/mbx/embed_config.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/embed_config.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,593 @@
+/*
+ * BK Id: SCCS/s.embed_config.c 1.7 05/18/01 07:54:04 patch
+ */
+
+/* Board specific functions for those embedded 8xx boards that do
+ * not have boot monitor support for board information.
+ */
+#include <linux/types.h>
+#include <linux/config.h>
+#ifdef CONFIG_8xx
+#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#endif
+
+
+/* IIC functions.
+ * These are just the basic master read/write operations so we can
+ * examine serial EEPROM.
+ */
+extern void	iic_read(uint devaddr, u_char *buf, uint offset, uint count);
+static u_char	aschex_to_byte(u_char *cp);
+
+/* Supply a default Ethernet address for those eval boards that don't
+ * ship with one.  This is an address from the MBX board I have, so
+ * it is unlikely you will find it on your network.
+ */
+static	ushort	def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+#if defined(CONFIG_MBX)
+
+/* The MBX hands us a pretty much ready to go board descriptor.  This
+ * is where the idea started in the first place.
+ */
+void
+embed_config(bd_t *bd)
+{
+	u_char	*mp;
+	u_char	eebuf[128];
+	int i;
+
+	/* Read the first 128 bytes of the EEPROM.  There is more,
+	 * but this is all we need.
+	 */
+	iic_read(0xa4, eebuf, 0, 128);
+
+	/* All we are looking for is the Ethernet MAC address.  The
+	 * first 8 bytes are 'MOTOROLA', so check for part of that.
+	 * If it's there, assume we have a valid MAC address.  If not,
+	 * grab our default one.
+	 */
+	if ((*(uint *)eebuf) == 0x4d4f544f)
+		mp = &eebuf[0x4c];
+	else
+		mp = (u_char *)def_enet_addr;
+
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = *mp++;
+	}
+
+	/* The boot rom passes these to us in MHz.  Linux now expects
+	 * them to be in Hz.
+	 */
+	bd->bi_intfreq *= 1000000;
+	bd->bi_busfreq *= 1000000;
+
+	/* Stuff a baud rate here as well.
+	*/
+	bd->bi_baudrate = 9600;
+}
+#endif /* CONFIG_MBX */
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPX6)
+
+/* Helper functions for Embedded Planet boards.
+*/
+static void
+rpx_eth(bd_t *bd, u_char *cp)
+{
+	int	i;
+
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = aschex_to_byte(cp);
+		cp += 2;
+	}
+}
+
+static uint
+rpx_baseten(u_char *cp)
+{
+	uint	retval;
+
+	retval = 0;
+
+	while (*cp != '\n') {
+		retval *= 10;
+		retval += (*cp) - '0';
+		cp++;
+	}
+	return(retval);
+}
+
+static void
+rpx_brate(bd_t *bd, u_char *cp)
+{
+	uint	rate;
+
+	rate = 0;
+
+	while (*cp != '\n') {
+		rate *= 10;
+		rate += (*cp) - '0';
+		cp++;
+	}
+
+	bd->bi_baudrate = rate * 100;
+}
+
+static void
+rpx_memsize(bd_t *bd, u_char *cp)
+{
+	uint	size;
+
+	size = 0;
+
+	while (*cp != '\n') {
+		size *= 10;
+		size += (*cp) - '0';
+		cp++;
+	}
+
+	bd->bi_memsize = size * 1024 * 1024;
+}
+
+static void
+rpx_cpuspeed(bd_t *bd, u_char *cp)
+{
+	uint	num, den;
+
+	num = den = 0;
+
+	while (*cp != '\n') {
+		num *= 10;
+		num += (*cp) - '0';
+		cp++;
+		if (*cp == '/') {
+			cp++;
+			den = (*cp) - '0';
+			break;
+		}
+	}
+
+	/* I don't know why the RPX just can't state the actual
+	 * CPU speed.....
+	 */
+	if (den) {
+		num /= den;
+		num *= den;
+	}
+	bd->bi_intfreq = bd->bi_busfreq = num * 1000000;
+
+	/* The 8xx can only run a maximum 50 MHz bus speed (until
+	 * Motorola changes this :-).  Greater than 50 MHz parts
+	 * run internal/2 for bus speed.
+	 */
+	if (num > 50)
+		bd->bi_busfreq /= 2;
+}
+
+/* Because I didn't find anything that would do this.......
+*/
+u_char
+aschex_to_byte(u_char *cp)
+{
+	u_char	byte, c;
+
+	c = *cp++;
+
+	if ((c >= 'A') && (c <= 'F')) {
+		c -= 'A';
+		c += 10;
+	}
+	else if ((c >= 'a') && (c <= 'f')) {
+		c -= 'a';
+		c += 10;
+	}
+	else {
+		c -= '0';
+	}
+	
+	byte = c * 16;
+
+	c = *cp;
+
+	if ((c >= 'A') && (c <= 'F')) {
+		c -= 'A';
+		c += 10;
+	}
+	else if ((c >= 'a') && (c <= 'f')) {
+		c -= 'a';
+		c += 10;
+	}
+	else {
+		c -= '0';
+	}
+	
+	byte += c;
+
+	return(byte);
+}
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+
+/* Read the EEPROM on the RPX-Lite board.
+*/
+void
+embed_config(bd_t *bd)
+{
+	u_char	eebuf[256], *cp;
+
+	/* Read the first 256 bytes of the EEPROM.  I think this
+	 * is really all there is, and I hope if it gets bigger the
+	 * info we want is still up front.
+	 */
+#if 1
+	iic_read(0xa8, eebuf, 0, 128);
+	iic_read(0xa8, &eebuf[128], 128, 128);
+
+	/* We look for two things, the Ethernet address and the
+	 * serial baud rate.  The records are separated by
+	 * newlines.
+	 */
+	cp = eebuf;
+	for (;;) {
+		if (*cp == 'E') {
+			cp++;
+			if (*cp == 'A') {
+				cp += 2;
+				rpx_eth(bd, cp);
+			}
+		}
+		if (*cp == 'S') {
+			cp++;
+			if (*cp == 'B') {
+				cp += 2;
+				rpx_brate(bd, cp);
+			}
+		}
+		if (*cp == 'D') {
+			cp++;
+			if (*cp == '1') {
+				cp += 2;
+				rpx_memsize(bd, cp);
+			}
+		}
+		if (*cp == 'H') {
+			cp++;
+			if (*cp == 'Z') {
+				cp += 2;
+				rpx_cpuspeed(bd, cp);
+			}
+		}
+
+		/* Scan to the end of the record.
+		*/
+		while ((*cp != '\n') && (*cp != 0xff))
+			cp++;
+
+		/* If the next character is a 0 or ff, we are done.
+		*/
+		cp++;
+		if ((*cp == 0) || (*cp == 0xff))
+			break;
+	}
+	bd->bi_memstart = 0;
+#else
+	/* For boards without initialized EEPROM.
+	*/
+	bd->bi_memstart = 0;
+	bd->bi_memsize = (8 * 1024 * 1024);
+	bd->bi_intfreq = 48000000;
+	bd->bi_busfreq = 48000000;
+	bd->bi_baudrate = 9600;
+#endif
+}
+#endif /* RPXLITE || RPXCLASSIC */
+
+#ifdef CONFIG_BSEIP
+/* Build a board information structure for the BSE ip-Engine.
+ * There is more to come since we will add some environment
+ * variables and a function to read them.
+ */
+void
+embed_config(bd_t *bd)
+{
+	u_char	*cp;
+	int	i;
+
+	/* Baud rate and processor speed will eventually come
+	 * from the environment variables.
+	 */
+	bd->bi_baudrate = 9600;
+
+	/* Get the Ethernet station address from the Flash ROM.
+	*/
+	cp = (u_char *)0xfe003ffa;
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = *cp++;
+	}
+
+	/* The rest of this should come from the environment as well.
+	*/
+	bd->bi_memstart = 0;
+	bd->bi_memsize = (16 * 1024 * 1024);
+	bd->bi_intfreq = 48000000;
+	bd->bi_busfreq = 48000000;
+}
+#endif /* BSEIP */
+
+#ifdef CONFIG_FADS
+/* Build a board information structure for the FADS.
+ */
+void
+embed_config(bd_t *bd)
+{
+	u_char	*cp;
+	int	i;
+
+	/* Just fill in some known values.
+	 */
+	bd->bi_baudrate = 9600;
+
+	/* Use default enet.
+	*/
+	cp = (u_char *)def_enet_addr;
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = *cp++;
+	}
+
+	bd->bi_memstart = 0;
+	bd->bi_memsize = (8 * 1024 * 1024);
+	bd->bi_intfreq = 40000000;
+	bd->bi_busfreq = 40000000;
+}
+#endif /* FADS */
+
+#ifdef CONFIG_8260
+/* Compute 8260 clock values if the rom doesn't provide them.
+ * We can't compute the internal core frequency (I don't know how to
+ * do that).
+ */
+static void
+clk_8260(bd_t *bd)
+{
+	uint	scmr, vco_out, clkin;
+	uint	plldf, pllmf, busdf, brgdf, cpmdf;
+	volatile immap_t	*ip;
+
+	ip = (immap_t *)IMAP_ADDR;
+	scmr = ip->im_clkrst.car_scmr;
+
+	/* The clkin is always bus frequency.
+	*/
+	clkin = bd->bi_busfreq;
+
+	/* Collect the bits from the scmr.
+	*/
+	plldf = (scmr >> 12) & 1;
+	pllmf = scmr & 0xfff;
+	cpmdf = (scmr >> 16) & 0x0f;
+	busdf = (scmr >> 20) & 0x0f;
+
+	/* This is arithmetic from the 8260 manual.
+	*/
+	vco_out = clkin / (plldf + 1);
+	vco_out *= 2 * (pllmf + 1);
+	bd->bi_vco = vco_out;		/* Save for later */
+
+	bd->bi_cpmfreq = vco_out / 2;	/* CPM Freq, in MHz */
+
+	/* Set Baud rate divisor.  The power up default is divide by 16,
+	 * but we set it again here in case it was changed.
+	 */
+	ip->im_clkrst.car_sccr = 1;	/* DIV 16 BRG */
+	bd->bi_brgfreq = vco_out / 16;
+}
+#endif
+
+#ifdef CONFIG_EST8260
+void
+embed_config(bd_t **bdp)
+{
+	u_char	*cp;
+	int	i;
+	bd_t	*bd;
+
+	bd = *bdp;
+#if 0
+	/* This is actually provided by my boot rom.  I have it
+	 * here for those people that may load the kernel with
+	 * a JTAG/COP tool and not the rom monitor.
+	 */
+	bd->bi_baudrate = 115200;
+	bd->bi_intfreq = 200000000;
+	bd->bi_busfreq = 66666666;
+	bd->bi_cpmfreq = 66666666;
+	bd->bi_brgfreq = 33333333;
+	bd->bi_memsize = 16 * 1024 * 1024;
+#else
+	/* The boot rom passes these to us in MHz.  Linux now expects
+	 * them to be in Hz.
+	 */
+	bd->bi_intfreq *= 1000000;
+	bd->bi_busfreq *= 1000000;
+	bd->bi_cpmfreq *= 1000000;
+	bd->bi_brgfreq *= 1000000;
+#endif
+
+	cp = (u_char *)def_enet_addr;
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = *cp++;
+	}
+}
+#endif /* EST8260 */
+
+#ifdef CONFIG_SBS8260
+/* We have to fill in everything.
+*/
+static	bd_t	bdinfo;
+
+void
+embed_config(bd_t **bdp)
+{
+	u_char	*cp;
+	int	i;
+	bd_t	*bd;
+
+	/* This should provided by the boot rom.
+	 */
+	bd = &bdinfo;
+	*bdp = bd;
+	bd->bi_baudrate = 9600;
+	bd->bi_memsize = 64 * 1024 * 1024;
+
+	/* Set all of the clocks.  We have to know the speed of the
+	 * external clock.  The development board had 66 MHz.
+	 */
+	bd->bi_busfreq = 66666666;
+	clk_8260(bd);
+
+	/* I don't know how to compute this yet.
+	*/
+	bd->bi_intfreq = 133000000;
+
+
+	cp = (u_char *)def_enet_addr;
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = *cp++;
+	}
+}
+#endif /* SBS8260 */
+
+#ifdef CONFIG_RPX6
+/* The pointer we are given is for the string of key values.
+ */
+static	bd_t	bdinfo;
+
+void
+embed_config(bd_t **bdp)
+{
+	u_char	*cp, *keyvals;
+	int	i;
+	bd_t	*bd;
+
+	keyvals = (u_char *)*bdp;
+
+	bd = &bdinfo;
+	*bdp = bd;
+
+	/* This is almost identical to the RPX-Lite/Classic functions
+	 * on the 8xx boards.  It would be nice to have a key lookup
+	 * function in a string, but the format of all of the fields
+	 * is slightly different.
+	 */
+	cp = keyvals;
+	for (;;) {
+		if (*cp == 'E') {
+			cp++;
+			if (*cp == 'A') {
+				cp += 2;
+				rpx_eth(bd, cp);
+			}
+		}
+		if (*cp == 'S') {
+			cp++;
+			if (*cp == 'B') {
+				cp += 2;
+				bd->bi_baudrate = rpx_baseten(cp);
+			}
+		}
+		if (*cp == 'D') {
+			cp++;
+			if (*cp == '1') {
+				cp += 2;
+				bd->bi_memsize = rpx_baseten(cp) * 1024 * 1024;
+			}
+		}
+		if (*cp == 'X') {
+			cp++;
+			if (*cp == 'T') {
+				cp += 2;
+				bd->bi_busfreq = rpx_baseten(cp);
+			}
+		}
+		if (*cp == 'N') {
+			cp++;
+			if (*cp == 'V') {
+				cp += 2;
+				bd->bi_nvsize = rpx_baseten(cp) * 1024 * 1024;
+			}
+		}
+
+		/* Scan to the end of the record.
+		*/
+		while ((*cp != '\n') && (*cp != 0xff))
+			cp++;
+
+		/* If the next character is a 0 or ff, we are done.
+		*/
+		cp++;
+		if ((*cp == 0) || (*cp == 0xff))
+			break;
+	}
+	bd->bi_memstart = 0;
+
+	/* The memory size includes both the 60x and local bus DRAM.
+	 * I don't want to use the local bus DRAM for real memory,
+	 * so subtract it out.  It would be nice if they were separate
+	 * keys.
+	 */
+	bd->bi_memsize -= 32 * 1024 * 1024;
+
+	/* Set all of the clocks.  We have to know the speed of the
+	 * external clock.
+	 */
+	clk_8260(bd);
+
+	/* I don't know how to compute this yet.
+	*/
+	bd->bi_intfreq = 200000000;
+}
+#endif /* RPX6 for testing */
+
+#ifdef CONFIG_ADS8260
+/* We have to fill in everything.
+*/
+static	bd_t	bdinfo;
+
+void
+embed_config(bd_t **bdp)
+{
+	u_char	*cp;
+	int	i;
+	bd_t	*bd;
+
+	/* This should provided by the boot rom.
+	 */
+	bd = &bdinfo;
+	*bdp = bd;
+	bd->bi_baudrate = 9600;
+	bd->bi_memsize = 16 * 1024 * 1024;
+
+	/* Set all of the clocks.  We have to know the speed of the
+	 * external clock.  The development board had 66 MHz.
+	 */
+	bd->bi_busfreq = 66666666;
+	clk_8260(bd);
+
+	/* I don't know how to compute this yet.
+	*/
+	bd->bi_intfreq = 200000000;
+
+
+	cp = (u_char *)def_enet_addr;
+	for (i=0; i<6; i++) {
+		bd->bi_enetaddr[i] = *cp++;
+	}
+}
+#endif /* ADS8260 */
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/gzimage.c linux/arch/ppc/boot/mbx/gzimage.c
--- v2.4.4/linux/arch/ppc/boot/mbx/gzimage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/gzimage.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,11 @@
+/*
+ * BK Id: SCCS/s.gzimage.c 1.6 05/18/01 15:17:06 cort
+ */
+/*
+ * gzimage.c
+ *
+ * Dummy file to allow a compressed zImage to be added
+ * into a linker section, accessed by the boot coode
+ */
+
+char dummy_for_gzimage;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/head.S linux/arch/ppc/boot/mbx/head.S
--- v2.4.4/linux/arch/ppc/boot/mbx/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/head.S	Thu May 24 15:02:06 2001
@@ -0,0 +1,243 @@
+/*
+ * BK Id: SCCS/s.head.S 1.9 05/18/01 07:54:04 patch
+ */
+#include <linux/config.h>
+#include "../../kernel/ppc_defs.h"
+#include "../../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+	.text
+
+/*
+ * This code is loaded by the ROM loader at some arbitrary location.
+ * Move it to high memory so that it can load the kernel at 0x0000.
+ *
+ * This is a three step process that will also work when booting from
+ * a Flash PROM normally located in high memory.
+ *
+ * First, the entire image is loaded into some high memory address.
+ * This is usually at or above 0x02000000.  This is done by a network
+ * boot function supported by the board or a debugger over BDM port.
+ *
+ * Second, the start up function here will relocate the decompress
+ * function to run at the link address of 0x01000000.
+ *
+ * Last, the decompression function will reloate the initrd, zImage, and
+ * the residual data to locations under 8 Meg.  This is necessary because
+ * the embedded kernel start up uses 8 Meg translations to access physical
+ * space before the MMU is enabled.  Finally, the zImage is uncompressed
+ * to location 0 and we jump to it.
+ *
+ * On the MBX,
+ *              R1 - Stack pointer at a high memory address.
+ *              R3 - Pointer to Board Information Block.
+ *              R4 - Pointer to argument string.
+ *              Interrupts masked, cache and MMU disabled.
+ *
+ *		...and the first and second functions listed above are
+ *			done for us (it knows ELF images).
+ *
+ * For other embedded boards we build the Board Information Block.
+ */
+
+	.globl	start
+start:
+	bl	start_
+start_:
+#ifndef CONFIG_MBX
+	lis	r11, local_bd_info@h
+	ori	r11, r11, local_bd_info@l
+#else
+	mr	r11, r3
+#endif
+
+	mfmsr	r3		/* Turn off interrupts  */
+	li	r4,0
+	ori	r4,r4,MSR_EE
+	andc	r3,r3,r4
+	mtmsr	r3
+
+	li	r4,0		/* Zero DER to prevent FRZ */
+	mtspr	SPRN_DER,r4
+
+/* check if we need to relocate ourselves to the link addr or were we
+   loaded there to begin with -- Cort */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	mflr	r3
+	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
+	mr	r8,r3
+#if 0
+	cmp	0,r3,r4
+	beq	start_ldr	/* Branch if loaded OK */
+#endif
+
+/* 
+ * no matter where we're loaded, move ourselves to -Ttext address
+ * This computes the sizes we need to determine other things.
+ */
+	lis	r5,end@h
+	ori	r5,r5,end@l
+	addi	r5,r5,3			/* Round up - just in case */
+	sub	r5,r5,r4		/* Compute # longwords to move */
+	srwi	r5,r5,2
+	mtctr	r5
+	mr	r7,r5
+	li	r6,0
+	subi	r3,r3,4			/* Set up for loop */
+	subi	r4,r4,4
+00:	lwzu	r5,4(r3)
+	stwu	r5,4(r4)
+	xor	r6,r6,r5
+	bdnz	00b
+
+  	lis	r3,start_ldr@h
+	ori	r3,r3,start_ldr@l
+	mtlr	r3			/* Easiest way to do an absolute jump */
+	blr
+
+start_ldr:
+/* Most 8xx boards don't boot up with the I-cache enabled.  Do that
+ * now because the decompress runs much faster that way.
+ */
+	lis	r3, IDC_INVALL@h
+	mtspr	IC_CST, r3
+	lis	r3, IDC_ENABLE@h
+	mtspr	IC_CST, r3
+
+/* Clear all of BSS */
+	lis	r3,edata@h
+	ori	r3,r3,edata@l
+	lis	r4,end@h
+	ori	r4,r4,end@l
+	subi	r3,r3,4
+	subi	r4,r4,4
+	li	r0,0
+50:	stwu	r0,4(r3)
+	cmp	0,r3,r4
+	bne	50b
+
+	lis	r1,.stack@h
+	ori	r1,r1,.stack@l
+	addi	r1,r1,4096*2
+	subi	r1,r1,256
+	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
+	andc	r1,r1,r2
+
+	/* Perform configuration of the various boards.  This is done
+	 * by reading some configuration data from EEPROM and building
+	 * the board information structure.
+	 */
+	mr	r3, r11
+        mr      r21, r11
+	mr	r22, r8
+	mr	r23, r7
+	mr	r24, r6
+
+	bl	embed_config
+	mr	r3, r21
+	bl      serial_init		/* Init MBX serial port */
+
+	mr      r11, r21
+	mr	r8, r22
+	mr	r7, r23
+	mr	r6, r24
+
+#ifdef CONFIG_MBX
+	/* On the MBX (or anything that will TFTP load an ELF image),
+	 * we have to find the intermediate address.  The ELF loader
+	 * only moves the Linux boostrap/decompress, not the zImage.
+	 */
+#define ILAP_ADDRESS    0xfa000020
+        lis     r8, ILAP_ADDRESS@h
+        lwz     r8, ILAP_ADDRESS@l(r8)
+        addis   r8, r8, 1               /* Add 64K */
+#endif
+
+	mr	r3,r8			/* Load point */
+	mr	r4,r7			/* Program length */
+	mr	r5,r6			/* Checksum */
+	mr	r6,r11			/* Residual data */
+	bl	decompress_kernel
+
+	/* changed to use r3 (as firmware does) for kernel
+	   as ptr to residual -- Cort*/
+	lis	r6,cmd_line@h
+	ori	r6,r6,cmd_line@l
+	lwz	r6, 0(r6)
+	subi	r7,r6,1
+00:	lbzu	r2,1(r7)
+	cmpi	0,r2,0
+	bne	00b
+
+	/* r4,r5 have initrd_start, size */
+	lis	r2,initrd_start@h
+	ori	r2,r2,initrd_start@l
+	lwz	r4,0(r2)
+	lis	r2,initrd_end@h
+	ori	r2,r2,initrd_end@l
+	lwz	r5,0(r2)
+	
+	/* The world starts from the beginning.
+	*/
+	li	r9,0x0
+	mtlr	r9
+
+	/* Invalidate the instruction cache because we just copied a
+	 * bunch of kernel instructions.
+	 */
+	lis	r9, IDC_INVALL@h
+	mtspr	IC_CST, r9
+
+	blr
+hang:
+	b	hang	
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+	.globl	udelay
+udelay:		
+	mulli	r4,r3,1000	/* nanoseconds */
+	addi	r4,r4,59
+	li	r5,60
+	divw	r4,r4,r5	/* BUS ticks */
+1:	mftbu	r5
+	mftb	r6
+	mftbu	r7
+	cmp	0,r5,r7
+	bne	1b		/* Get [synced] base time */
+	addc	r9,r6,r4	/* Compute end time */
+	addze	r8,r5
+2:	mftbu	r5
+	cmp	0,r5,r8
+	blt	2b
+	bgt	3f
+	mftb	r6
+	cmp	0,r6,r9
+	blt	2b
+3:	blr		
+
+.globl _get_MSR
+_get_MSR:		
+	mfmsr	r3
+	blr
+	
+.globl _put_MSR
+_put_MSR:		
+	mtmsr	r3
+	blr
+
+	.comm	.stack,4096*2,4
+#ifndef CONFIG_MBX
+local_bd_info:
+	.long	0
+	.long	0x01000000
+	.long	64
+	.long	64
+	.long	0
+	.long	0
+	.long	0
+#endif
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/head_8260.S linux/arch/ppc/boot/mbx/head_8260.S
--- v2.4.4/linux/arch/ppc/boot/mbx/head_8260.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/head_8260.S	Thu May 24 15:02:06 2001
@@ -0,0 +1,259 @@
+/*
+ * BK Id: SCCS/s.head_8260.S 1.8 05/18/01 07:54:04 patch
+ */
+#include "../../kernel/ppc_defs.h"
+#include "../../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+	.text
+
+/*
+ * Boot loader philosophy:
+ *
+ *      ROM loads us to some arbitrary location
+ *      ROM loads these registers:
+ *	
+ *          R3 = Pointer to the board configuration data
+ *          R5 = Pointer to Open Firmware data 	
+ *		 	
+ *      ROM jumps to start/start_
+ *      Move the boot code to the link address (4 MB)
+ *      Call decompress_kernel()
+ *         Relocate the initrd, zimage and residual data to 4 MB
+ *         Decompress the kernel to 0
+ *      Jump to the kernel entry
+ *            -- Cort
+ */
+	.globl	start
+start:
+	bl	start_
+start_:
+	mr	r11,r3		/* Save pointer to residual/board data */
+	mr      r25,r5          /* Save OFW pointer */
+	li	r3,MSR_IP	/* Establish default MSR value */
+	mtmsr	r3
+
+/* check if we need to relocate ourselves to the link addr or were we
+   loaded there to begin with -- Cort */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	mflr	r3
+	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
+	mr	r8,r3
+	cmp	0,r3,r4
+	bne	1010f
+/* compute size of whole image in words.  this should be moved to
+ * start_ldr() -- Cort
+ */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	lis	r5,end@h
+	ori	r5,r5,end@l
+	addi	r5,r5,3		/* round up */
+	sub	r5,r5,r4
+	srwi	r5,r5,2
+	mr	r7,r5
+	b	start_ldr
+1010:
+/* 
+ * no matter where we're loaded, move ourselves to -Ttext address
+ */
+relocate:
+	mflr	r3		/* Compute code bias */
+	subi	r3,r3,4
+	mr	r8,r3
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	lis	r5,end@h
+	ori	r5,r5,end@l
+	addi	r5,r5,3			/* Round up - just in case */
+	sub	r5,r5,r4		/* Compute # longwords to move */
+	srwi	r5,r5,2
+	mtctr	r5
+	mr	r7,r5
+	li	r6,0
+	subi	r3,r3,4			/* Set up for loop */
+	subi	r4,r4,4
+00:	lwzu	r5,4(r3)
+	stwu	r5,4(r4)
+	xor	r6,r6,r5
+	bdnz	00b
+  	lis	r3,start_ldr@h
+	ori	r3,r3,start_ldr@l
+	mtlr	r3			/* Easiest way to do an absolute jump */
+	blr
+start_ldr:
+/* Clear all of BSS */
+	lis	r3,edata@h
+	ori	r3,r3,edata@l
+	lis	r4,end@h
+	ori	r4,r4,end@l
+	subi	r3,r3,4
+	subi	r4,r4,4
+	li	r0,0
+50:	stwu	r0,4(r3)
+	cmp	0,r3,r4
+	bne	50b
+90:	mr	r9,r1			/* Save old stack pointer (in case it matters) */
+	lis	r1,.stack@h
+	ori	r1,r1,.stack@l
+	addi	r1,r1,4096*2
+	subi	r1,r1,256
+	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
+	andc	r1,r1,r2
+
+	/* Speed us up a little.
+	*/
+	bl	flush_instruction_cache
+
+/* Run loader */
+	mr	r3,r8			/* Load point */
+	mr	r4,r7			/* Program length */
+	mr	r5,r6			/* Checksum */
+	mr	r6,r11			/* Residual data */
+	mr      r7,r25                  /* OFW interfaces */
+	bl	decompress_kernel
+	
+	/* changed to use r3 (as firmware does) for kernel
+	   as ptr to residual -- Cort*/
+	lis	r6,cmd_line@h
+	ori	r6,r6,cmd_line@l
+	lwz	r6, 0(r6)
+	subi	r7,r6,1
+00:	lbzu	r2,1(r7)
+	cmpi	0,r2,0
+	bne	00b
+
+	/* r4,r5 have initrd_start, size */
+	lis	r2,initrd_start@h
+	ori	r2,r2,initrd_start@l
+	lwz	r4,0(r2)
+	lis	r2,initrd_end@h
+	ori	r2,r2,initrd_end@l
+	lwz	r5,0(r2)
+	
+	/* tell kernel we're prep */
+	/* 
+	 * get start address of kernel code which is stored as a coff
+	 * entry.  see boot/head.S -- Cort 
+	 */
+	li	r9,0x4
+	mtlr	r9
+	lis	r10,0xdeadc0de@h
+	ori	r10,r10,0xdeadc0de@l
+	li	r9,0
+	stw	r10,0(r9)
+/*
+ * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
+ * so disable BATs before setting this to avoid a clash
+ */
+	li      r8,0
+	mtspr   DBAT0U,r8
+	mtspr   DBAT1U,r8
+	mtspr   DBAT2U,r8
+	mtspr   DBAT3U,r8
+	mtspr   IBAT0U,r8
+	mtspr   IBAT1U,r8
+	mtspr   IBAT2U,r8
+	mtspr   IBAT3U,r8
+
+	blr
+hang:
+	b	hang	
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+	.globl	udelay
+udelay:		
+	mfspr	r4,PVR
+	srwi	r4,r4,16
+	cmpi	0,r4,1		/* 601 ? */
+	bne	.udelay_not_601
+00:	li	r0,86	/* Instructions / microsecond? */
+	mtctr	r0
+10:	addi	r0,r0,0 /* NOP */
+	bdnz	10b
+	subic.	r3,r3,1
+	bne	00b
+	blr
+
+.udelay_not_601:		
+	mulli	r4,r3,1000	/* nanoseconds */
+	addi	r4,r4,59
+	li	r5,60
+	divw	r4,r4,r5	/* BUS ticks */
+1:	mftbu	r5
+	mftb	r6
+	mftbu	r7
+	cmp	0,r5,r7
+	bne	1b		/* Get [synced] base time */
+	addc	r9,r6,r4	/* Compute end time */
+	addze	r8,r5
+2:	mftbu	r5
+	cmp	0,r5,r8
+	blt	2b
+	bgt	3f
+	mftb	r6
+	cmp	0,r6,r9
+	blt	2b
+3:	blr		
+
+.globl _get_HID0
+_get_HID0:		
+	mfspr	r3,HID0
+	blr
+
+.globl _put_HID0
+_put_HID0:		
+	mtspr	HID0,r3
+	blr
+		
+.globl _get_MSR
+_get_MSR:		
+	mfmsr	r3
+	blr
+	
+.globl _put_MSR
+_put_MSR:		
+	mtmsr	r3
+	blr
+
+/*
+ * Flush instruction cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_instruction_cache)
+	mflr	r5
+	bl	flush_data_cache
+	mfspr	r3,HID0	/* Caches are controlled by this register */
+	li	r4,0
+	ori	r4,r4,(HID0_ICE|HID0_ICFI)
+	or	r3,r3,r4	/* Need to enable+invalidate to clear */
+	mtspr	HID0,r3
+	andc	r3,r3,r4
+	ori	r3,r3,HID0_ICE	/* Enable cache */
+	mtspr	HID0,r3
+	mtlr	r5
+	blr
+	
+#define NUM_CACHE_LINES 128*8
+#define CACHE_LINE_SIZE 32 
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_data_cache)
+	lis	r3,cache_flush_buffer@h
+	ori	r3,r3,cache_flush_buffer@l
+	li	r4,NUM_CACHE_LINES
+	mtctr	r4
+00:	lwz	r4,0(r3)
+	addi	r3,r3,CACHE_LINE_SIZE	/* Next line, please */
+	bdnz	00b	
+10:	blr
+	.comm	.stack,4096*2,4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/iic.c linux/arch/ppc/boot/mbx/iic.c
--- v2.4.4/linux/arch/ppc/boot/mbx/iic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/iic.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,218 @@
+/*
+ * BK Id: SCCS/s.iic.c 1.8 05/18/01 07:54:04 patch
+ */
+
+/* Minimal support functions to read configuration from IIC EEPROMS
+ * on MPC8xx boards.  Originally written for RPGC RPX-Lite.
+ * Dan Malek (dmalek@jlc.net).
+ */
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/mpc8xx.h>
+#include "../../8xx_io/commproc.h"
+
+
+/* IIC functions.
+ * These are just the basic master read/write operations so we can
+ * examine serial EEPROM.
+ */
+void	iic_read(uint devaddr, u_char *buf, uint offset, uint count);
+
+static	int	iic_init_done;
+
+static void
+iic_init()
+{
+	volatile iic_t *iip;
+	volatile i2c8xx_t *i2c;
+	volatile cpm8xx_t	*cp;
+	volatile immap_t	*immap;
+	uint	dpaddr;
+
+	immap = (immap_t *)IMAP_ADDR;
+	cp = (cpm8xx_t *)&(immap->im_cpm);
+
+	/* Reset the CPM.  This is necessary on the 860 processors
+	 * that may have started the SCC1 ethernet without relocating
+	 * the IIC.
+	 * This also stops the Ethernet in case we were loaded by a
+	 * BOOTP rom monitor.
+	 */
+	cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
+
+	/* Wait for it.
+	*/
+	while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG));
+
+	/* Remove any microcode patches.  We will install our own
+	 * later.
+	 */
+	cp->cp_cpmcr1 = 0;
+	cp->cp_cpmcr2 = 0;
+	cp->cp_cpmcr3 = 0;
+	cp->cp_cpmcr4 = 0;
+	cp->cp_rccr = 0;
+
+	iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+	i2c = (i2c8xx_t *)&(immap->im_i2c);
+
+	/* Initialize Port B IIC pins.
+	*/
+	cp->cp_pbpar |= 0x00000030;
+	cp->cp_pbdir |= 0x00000030;
+	cp->cp_pbodr |= 0x00000030;
+
+	/* Initialize the parameter ram.
+	*/
+
+	/* Allocate space for a two transmit and one receive buffer
+	 * descriptor in the DP ram.
+	 * For now, this address seems OK, but it may have to
+	 * change with newer versions of the firmware.
+	 */
+	dpaddr = 0x0840;
+
+	/* Set up the IIC parameters in the parameter ram.
+	*/
+	iip->iic_tbase = dpaddr;
+	iip->iic_rbase = dpaddr + (2 * sizeof(cbd_t));
+
+	iip->iic_tfcr = SMC_EB;
+	iip->iic_rfcr = SMC_EB;
+
+	/* This should really be done by the reader/writer.
+	*/
+	iip->iic_mrblr = 128;
+
+	/* Initialize Tx/Rx parameters.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Select an arbitrary address.  Just make sure it is unique.
+	*/
+	i2c->i2c_i2add = 0x34;
+
+	/* Make clock run maximum slow.
+	*/
+	i2c->i2c_i2brg = 7;
+
+	/* Disable interrupts.
+	*/
+	i2c->i2c_i2cmr = 0;
+	i2c->i2c_i2cer = 0xff;
+
+	/* Enable SDMA.
+	*/
+	immap->im_siu_conf.sc_sdcr = 1;
+
+	iic_init_done = 1;
+}
+
+/* Read from IIC.
+ * Caller provides device address, memory buffer, and byte count.
+ */
+static	u_char	iitemp[32];
+
+void
+iic_read(uint devaddr, u_char *buf, uint offset, uint count)
+{
+	volatile iic_t		*iip;
+	volatile i2c8xx_t	*i2c;
+	volatile cbd_t		*tbdf, *rbdf;
+	volatile cpm8xx_t	*cp;
+	volatile immap_t	*immap;
+	u_char			*tb;
+	uint			temp;
+
+	/* If the interface has not been initialized, do that now.
+	*/
+	if (!iic_init_done)
+		iic_init();
+
+	immap = (immap_t *)IMAP_ADDR;
+	cp = (cpm8xx_t *)&(immap->im_cpm);
+
+	iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+	i2c = (i2c8xx_t *)&(immap->im_i2c);
+
+	tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
+	rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
+
+	/* Send a "dummy write" operation.  This is a write request with
+	 * only the offset sent, followed by another start condition.
+	 * This will ensure we start reading from the first location
+	 * of the EEPROM.
+	 */
+	tb = iitemp;
+	tb = (u_char *)(((uint)tb + 15) & ~15);
+	tbdf->cbd_bufaddr = (int)tb;
+	*tb = devaddr & 0xfe;	/* Device address */
+	*(tb+1) = offset;		/* Offset */
+	tbdf->cbd_datlen = 2;		/* Length */
+	tbdf->cbd_sc =
+	      BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
+
+	i2c->i2c_i2mod = 1;	/* Enable */
+	i2c->i2c_i2cer = 0xff;
+	i2c->i2c_i2com = 0x81;	/* Start master */
+
+	/* Wait for IIC transfer.
+	*/
+#if 0
+	while ((i2c->i2c_i2cer & 3) == 0);
+
+	if (tbdf->cbd_sc & BD_SC_READY)
+		printf("IIC ra complete but tbuf ready\n");
+#else
+	temp = 10000000;
+	while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
+		temp--;
+#if 0
+	/* We can't do this...there is no serial port yet!
+	*/
+	if (temp == 0) {
+		printf("Timeout reading EEPROM\n");
+		return;
+	}
+#endif
+#endif
+	
+	/* Chip errata, clear enable.
+	*/
+	i2c->i2c_i2mod = 0;
+
+	/* To read, we need an empty buffer of the proper length.
+	 * All that is used is the first byte for address, the remainder
+	 * is just used for timing (and doesn't really have to exist).
+	 */
+	tbdf->cbd_bufaddr = (int)tb;
+	*tb = devaddr | 1;	/* Device address */
+	rbdf->cbd_bufaddr = (uint)buf;		/* Desination buffer */
+	tbdf->cbd_datlen = rbdf->cbd_datlen = count + 1;	/* Length */
+	tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
+	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* Chip bug, set enable here.
+	*/
+	i2c->i2c_i2mod = 1;	/* Enable */
+	i2c->i2c_i2cer = 0xff;
+	i2c->i2c_i2com = 0x81;	/* Start master */
+
+	/* Wait for IIC transfer.
+	*/
+#if 0
+	while ((i2c->i2c_i2cer & 1) == 0);
+
+	if (rbdf->cbd_sc & BD_SC_EMPTY)
+		printf("IIC read complete but rbuf empty\n");
+#else
+	temp = 10000000;
+	while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
+		temp--;
+#endif
+	
+	/* Chip errata, clear enable.
+	*/
+	i2c->i2c_i2mod = 0;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/m8260_tty.c linux/arch/ppc/boot/mbx/m8260_tty.c
--- v2.4.4/linux/arch/ppc/boot/mbx/m8260_tty.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/m8260_tty.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,312 @@
+/*
+ * BK Id: SCCS/s.m8260_tty.c 1.7 05/18/01 07:54:04 patch
+ */
+
+
+/* Minimal serial functions needed to send messages out the serial
+ * port on SMC1.
+ */
+#include <linux/types.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm_8260.h>
+
+uint	no_print;
+extern char	*params[];
+extern int	nparams;
+static		u_char	cons_hold[128], *sgptr;
+static		int	cons_hold_cnt;
+
+/* If defined, enables serial console.  The value (1 through 4)
+ * should designate which SCC is used, but this isn't complete.  Only
+ * SCC1 is known to work at this time.
+ */
+#ifdef CONFIG_SCC_CONSOLE
+#define SCC_CONSOLE 1
+#endif
+
+void
+serial_init(bd_t *bd)
+{
+	volatile smc_t		*sp;
+	volatile smc_uart_t	*up;
+	volatile scc_t		*sccp;
+	volatile scc_uart_t	*sup;
+	volatile cbd_t	*tbdf, *rbdf;
+	volatile immap_t	*ip;
+	volatile iop8260_t	*io;
+	volatile cpm8260_t	*cp;
+	uint	dpaddr, memaddr;
+
+	ip = (immap_t *)IMAP_ADDR;
+	cp = &ip->im_cpm;
+	io = &ip->im_ioport;
+
+	/* Perform a reset.
+	*/
+	cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
+
+	/* Wait for it.
+	*/
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+#ifdef CONFIG_ADS8260
+	/* Enable the RS-232 transceivers.
+	*/
+	*(volatile uint *)(BCSR_ADDR + 4) &=
+					~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2);
+#endif
+
+#ifdef SCC_CONSOLE
+	sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]);
+	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+	sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* Use Port D for SCC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00000003;
+	io->iop_psord &= ~0x00000001;	/* Rx */
+	io->iop_psord |= 0x00000002;	/* Tx */
+	io->iop_pdird &= ~0x00000001;	/* Rx */
+	io->iop_pdird |= 0x00000002;	/* Tx */
+
+#else
+	sp = (smc_t*)&(ip->im_smc[0]);
+	*(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+	up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+	/* Use Port D for SMC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00c00000;
+	io->iop_pdird |= 0x00400000;
+	io->iop_pdird &= ~0x00800000;
+	io->iop_psord &= ~0x00c00000;
+#endif
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * For now, this address seems OK, but it may have to
+	 * change with newer versions of the firmware.
+	 */
+	dpaddr = 0x0800;
+
+	/* Grab a few bytes from the top of memory.
+	 */
+	memaddr = (bd->bi_memsize - 256) & ~15;
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
+	rbdf->cbd_bufaddr = memaddr;
+	rbdf->cbd_sc = 0;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = memaddr+128;
+	tbdf->cbd_sc = 0;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+#ifdef SCC_CONSOLE
+	sup->scc_genscc.scc_rbase = dpaddr;
+	sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t);
+
+	/* Set up the uart parameters in the
+	 * parameter ram.
+	 */
+	sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	sup->scc_genscc.scc_mrblr = 128;
+	sup->scc_maxidl = 8;
+	sup->scc_brkcr = 1;
+	sup->scc_parec = 0;
+	sup->scc_frmec = 0;
+	sup->scc_nosec = 0;
+	sup->scc_brkec = 0;
+	sup->scc_uaddr1 = 0;
+	sup->scc_uaddr2 = 0;
+	sup->scc_toseq = 0;
+	sup->scc_char1 = 0x8000;
+	sup->scc_char2 = 0x8000;
+	sup->scc_char3 = 0x8000;
+	sup->scc_char4 = 0x8000;
+	sup->scc_char5 = 0x8000;
+	sup->scc_char6 = 0x8000;
+	sup->scc_char7 = 0x8000;
+	sup->scc_char8 = 0x8000;
+	sup->scc_rccm = 0xc0ff;
+
+	/* Send the CPM an initialize command.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sccp->scc_gsmrh = 0;
+	sccp->scc_gsmrl = 
+		(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+	/* Disable all interrupts and clear all pending
+	 * events.
+	 */
+	sccp->scc_sccm = 0;
+	sccp->scc_scce = 0xffff;
+	sccp->scc_dsr = 0x7e7e;
+	sccp->scc_pmsr = 0x3000;
+
+	/* Wire BRG1 to SCC1.  The console driver will take care of
+	 * others.
+	 */
+	ip->im_cpmux.cmx_scr = 0;
+#else
+	up->smc_rbase = dpaddr;
+	up->smc_tbase = dpaddr+sizeof(cbd_t);
+	up->smc_rfcr = CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_EB;
+	up->smc_brklen = 0;
+	up->smc_brkec = 0;
+	up->smc_brkcr = 0;
+	up->smc_mrblr = 128;
+	up->smc_maxidl = 8;
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Mask all interrupts and remove anything pending.
+	*/
+	sp->smc_smcm = 0;
+	sp->smc_smce = 0xff;
+
+	/* Set up the baud rate generator.
+	 */
+	ip->im_cpmux.cmx_smr = 0;
+#endif
+
+	/* The baud rate divisor needs to be coordinated with clk_8260().
+	*/
+	ip->im_brgc1 =
+		(((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) |
+								CPM_BRG_EN;
+
+	/* Make the first buffer the only buffer.
+	*/
+	tbdf->cbd_sc |= BD_SC_WRAP;
+	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* Initialize Tx/Rx parameters.
+	*/
+#ifdef SCC_CONSOLE
+	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#else
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Enable transmitter/receiver.
+	*/
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+#endif
+}
+
+void
+serial_putc(void *ignored, const char c)
+{
+	volatile cbd_t		*tbdf;
+	volatile char		*buf;
+	volatile smc_uart_t	*up;
+	volatile scc_uart_t	*sup;
+	volatile immap_t	*ip;
+	extern bd_t		*board_info;
+
+	ip = (immap_t *)IMAP_ADDR;
+#ifdef SCC_CONSOLE
+	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+	tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
+#else
+	up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+	tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
+#endif
+
+	/* Wait for last character to go.
+	*/
+	buf = (char *)tbdf->cbd_bufaddr;
+	while (tbdf->cbd_sc & BD_SC_READY);
+
+	*buf = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc(void *ignored)
+{
+	char	c;
+
+	if (cons_hold_cnt <= 0) {
+		cons_hold_cnt = serial_readbuf(cons_hold);
+		sgptr = cons_hold;
+	}
+	c = *sgptr++;
+	cons_hold_cnt--;
+
+	return(c);
+}
+
+int
+serial_readbuf(u_char *cbuf)
+{
+	volatile cbd_t		*rbdf;
+	volatile char		*buf;
+	volatile smc_uart_t	*up;
+	volatile scc_uart_t	*sup;
+	volatile immap_t	*ip;
+	int	i, nc;
+
+	ip = (immap_t *)IMAP_ADDR;
+
+#ifdef SCC_CONSOLE
+	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+	rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
+#else
+	up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+	rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+#endif
+
+	/* Wait for character to show up.
+	*/
+	buf = (char *)rbdf->cbd_bufaddr;
+	while (rbdf->cbd_sc & BD_SC_EMPTY);
+	nc = rbdf->cbd_datlen;
+	for (i=0; i<nc; i++)
+		*cbuf++ = *buf++;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return(nc);
+}
+
+int
+serial_tstc(void *ignored)
+{
+	volatile cbd_t		*rbdf;
+	volatile smc_uart_t	*up;
+	volatile scc_uart_t	*sup;
+	volatile immap_t	*ip;
+
+	ip = (immap_t *)IMAP_ADDR;
+#ifdef SCC_CONSOLE
+	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+	rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
+#else
+	up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+	rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+#endif
+
+	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/m8xx_tty.c linux/arch/ppc/boot/mbx/m8xx_tty.c
--- v2.4.4/linux/arch/ppc/boot/mbx/m8xx_tty.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/m8xx_tty.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,288 @@
+/*
+ * BK Id: SCCS/s.m8xx_tty.c 1.8 05/18/01 07:54:04 patch
+ */
+
+
+/* Minimal serial functions needed to send messages out the serial
+ * port on the MBX console.
+ *
+ * The MBX uxes SMC1 for the serial port.  We reset the port and use
+ * only the first BD that EPPC-Bug set up as a character FIFO.
+ *
+ * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
+ * use COM1 instead of SMC1 as the console port.  This kinda sucks
+ * for the rest of the kernel, so here we force the use of SMC1 again.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/mpc8xx.h>
+#include "../../8xx_io/commproc.h"
+
+#ifdef CONFIG_MBX
+#define MBX_CSR1	((volatile u_char *)0xfa100000)
+#define CSR1_COMEN	(u_char)0x02
+#endif
+
+#ifdef TQM_SMC2_CONSOLE
+#define PROFF_CONS	PROFF_SMC2
+#define CPM_CR_CH_CONS	CPM_CR_CH_SMC2
+#define SMC_INDEX	1
+static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport);
+#else
+#define PROFF_CONS	PROFF_SMC1
+#define CPM_CR_CH_CONS	CPM_CR_CH_SMC1
+#define SMC_INDEX	0
+#endif
+
+static cpm8xx_t	*cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+void
+serial_init(bd_t *bd)
+{
+	volatile smc_t		*sp;
+	volatile smc_uart_t	*up;
+	volatile cbd_t	*tbdf, *rbdf;
+	volatile cpm8xx_t	*cp;
+	uint	dpaddr, memaddr, ui;
+
+	cp = cpmp;
+	sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]);
+	up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS];
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+#ifdef CONFIG_FADS
+	/* Enable SMC1/2 transceivers.
+	*/
+	*((volatile uint *)BCSR1) &= ~(BCSR1_RS232EN_1|BCSR1_RS232EN_2);
+#endif
+
+#ifndef CONFIG_MBX
+	{
+	/* Initialize SMCx and use it for the console port.
+	 */
+
+	/* Enable SDMA.
+	*/
+	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+
+#ifdef TQM_SMC2_CONSOLE
+	/* Use Port A for SMC2 instead of other functions.
+	*/
+	iopp->iop_papar |=  0x00c0;
+	iopp->iop_padir &= ~0x00c0;
+	iopp->iop_paodr &= ~0x00c0;
+#else
+	/* Use Port B for SMCs instead of other functions.
+	*/
+	cp->cp_pbpar |= 0x00000cc0;
+	cp->cp_pbdir &= ~0x00000cc0;
+	cp->cp_pbodr &= ~0x00000cc0;
+#endif
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	 * For now, this address seems OK, but it may have to
+	 * change with newer versions of the firmware.
+	 */
+	dpaddr = 0x0800;
+
+	/* Grab a few bytes from the top of memory for SMC FIFOs.
+	 */
+	memaddr = (bd->bi_memsize - 32) & ~15;
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+	rbdf->cbd_bufaddr = memaddr;
+	rbdf->cbd_sc = 0;
+	tbdf = rbdf + 1;
+	tbdf->cbd_bufaddr = memaddr+4;
+	tbdf->cbd_sc = 0;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+	up->smc_rbase = dpaddr;
+	up->smc_tbase = dpaddr+sizeof(cbd_t);
+	up->smc_rfcr = SMC_EB;
+	up->smc_tfcr = SMC_EB;
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Mask all interrupts and remove anything pending.
+	*/
+	sp->smc_smcm = 0;
+	sp->smc_smce = 0xff;
+
+	/* Set up the baud rate generator.
+	 * See 8xx_io/commproc.c for details.
+	 * This wires BRG1 to SMC1 and BRG2 to SMC2;
+	 */
+	cp->cp_simode = 0x10000000;
+	ui = bd->bi_intfreq / 16 / bd->bi_baudrate;
+#ifdef TQM_SMC2_CONSOLE
+	cp->cp_brgc2 =
+#else
+	cp->cp_brgc1 =
+#endif
+		((ui - 1) < 4096)
+		? (((ui - 1) << 1) | CPM_BRG_EN)
+		: ((((ui / 16) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16);
+
+#else /* CONFIG_MBX */
+	if (*MBX_CSR1 & CSR1_COMEN) {
+		/* COM1 is enabled.  Initialize SMC1 and use it for
+		 * the console port.
+		 */
+
+		/* Enable SDMA.
+		*/
+		((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+
+		/* Use Port B for SMCs instead of other functions.
+		*/
+		cp->cp_pbpar |= 0x00000cc0;
+		cp->cp_pbdir &= ~0x00000cc0;
+		cp->cp_pbodr &= ~0x00000cc0;
+
+		/* Allocate space for two buffer descriptors in the DP ram.
+		 * For now, this address seems OK, but it may have to
+		 * change with newer versions of the firmware.
+		 */
+		dpaddr = 0x0800;
+
+		/* Grab a few bytes from the top of memory.  EPPC-Bug isn't
+		 * running any more, so we can do this.
+		 */
+		memaddr = (bd->bi_memsize - 32) & ~15;
+
+		/* Set the physical address of the host memory buffers in
+		 * the buffer descriptors.
+		 */
+		rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+		rbdf->cbd_bufaddr = memaddr;
+		rbdf->cbd_sc = 0;
+		tbdf = rbdf + 1;
+		tbdf->cbd_bufaddr = memaddr+4;
+		tbdf->cbd_sc = 0;
+
+		/* Set up the uart parameters in the parameter ram.
+		*/
+		up->smc_rbase = dpaddr;
+		up->smc_tbase = dpaddr+sizeof(cbd_t);
+		up->smc_rfcr = SMC_EB;
+		up->smc_tfcr = SMC_EB;
+
+		/* Set UART mode, 8 bit, no parity, one stop.
+		 * Enable receive and transmit.
+		 */
+		sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+		/* Mask all interrupts and remove anything pending.
+		*/
+		sp->smc_smcm = 0;
+		sp->smc_smce = 0xff;
+
+		/* Set up the baud rate generator.
+		 * See 8xx_io/commproc.c for details.
+		 */
+		cp->cp_simode = 0x10000000;
+		cp->cp_brgc1 =
+			(((bd->bi_intfreq/16) / 9600) << 1) | CPM_BRG_EN;
+
+		/* Enable SMC1 for console output.
+		*/
+		*MBX_CSR1 &= ~CSR1_COMEN;
+	}
+	else {
+#endif /* ndef CONFIG_MBX */
+		/* SMCx is used as console port.
+		*/
+		tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
+		rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase];
+
+		/* Issue a stop transmit, and wait for it.
+		*/
+		cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS,
+					CPM_CR_STOP_TX) | CPM_CR_FLG;
+		while (cp->cp_cpcr & CPM_CR_FLG);
+	}
+
+	/* Make the first buffer the only buffer.
+	*/
+	tbdf->cbd_sc |= BD_SC_WRAP;
+	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+	/* Single character receive.
+	*/
+	up->smc_mrblr = 1;
+	up->smc_maxidl = 0;
+
+	/* Initialize Tx/Rx parameters.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Enable transmitter/receiver.
+	*/
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+}
+
+void
+serial_putc(void *ignored, const char c)
+{
+	volatile cbd_t		*tbdf;
+	volatile char		*buf;
+	volatile smc_uart_t	*up;
+
+	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
+	tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+
+	/* Wait for last character to go.
+	*/
+	buf = (char *)tbdf->cbd_bufaddr;
+	while (tbdf->cbd_sc & BD_SC_READY);
+
+	*buf = c;
+	tbdf->cbd_datlen = 1;
+	tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc(void *ignored)
+{
+	volatile cbd_t		*rbdf;
+	volatile char		*buf;
+	volatile smc_uart_t	*up;
+	char			c;
+
+	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
+	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+	/* Wait for character to show up.
+	*/
+	buf = (char *)rbdf->cbd_bufaddr;
+	while (rbdf->cbd_sc & BD_SC_EMPTY);
+	c = *buf;
+	rbdf->cbd_sc |= BD_SC_EMPTY;
+
+	return(c);
+}
+
+int
+serial_tstc(void *ignored)
+{
+	volatile cbd_t		*rbdf;
+	volatile smc_uart_t	*up;
+
+	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
+	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/misc.c linux/arch/ppc/boot/mbx/misc.c
--- v2.4.4/linux/arch/ppc/boot/mbx/misc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/misc.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,296 @@
+/*
+ * BK Id: SCCS/s.misc.c 1.9 05/18/01 07:54:04 patch
+ */
+/*
+ * Adapted for PowerPC by Gary Thomas
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include "zlib.h"
+#include <asm/residual.h>
+#include <linux/elf.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_8xx
+#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#endif
+
+/*
+ * The following references are needed to cause the linker to pull in the
+ * gzimage.o and rdimage.o files.  These object files are special,
+ * since they get placed into the .gzimage and .rdimage ELF sections 
+ * of the zvmlinux and zvmlinux.initrd files.
+ */
+extern char dummy_for_gzimage;
+extern char dummy_for_rdimage;
+
+/*
+ * Please send me load/board info and such data for hardware not
+ * listed here so I can keep track since things are getting tricky
+ * with the different load addrs with different firmware.  This will
+ * help to avoid breaking the load/boot process.
+ * -- Cort
+ */
+char *avail_ram;
+char *end_avail;
+
+/* See comment below.....
+*/
+unsigned int initrd_offset, initrd_size;
+
+/* Because of the limited amount of memory on embedded, it presents
+ * loading problems.  The biggest is that we load this boot program
+ * into a relatively low memory address, and the Linux kernel Bss often
+ * extends into this space when it get loaded.  When the kernel starts
+ * and zeros the BSS space, it also writes over the information we
+ * save here and pass to the kernel (command line and board info).
+ * On these boards, we grab some known memory holes to hold this information.
+ */
+char	cmd_buf[256];
+char	*cmd_line = cmd_buf;
+
+/* This is the default cmdline that will be given to the user at boot time..
+ * If none was specified at compile time, we'll give it one that should work.
+ * -- Tom */
+#ifdef CONFIG_CMDLINE_BOOL
+char	compiled_string[] = CONFIG_CMDLINE;
+#endif
+char	ramroot_string[] = "root=/dev/ram";
+char	netroot_string[] = "root=/dev/nfs rw";
+
+bd_t hold_resid_buf;
+bd_t *hold_residual = &hold_resid_buf;
+unsigned long initrd_start = 0, initrd_end = 0;
+char *zimage_start;
+int zimage_size;
+
+extern void puts(const char *);
+extern void putc(const char c);
+extern void udelay(long x);
+extern void puthex(unsigned long val);
+extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n);
+extern void gunzip(void *, int, unsigned char *, int *);
+extern int tstc(void);
+extern int getc(void);
+
+unsigned long
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
+{
+	int timer;
+	extern unsigned long start;
+	char *cp, ch;
+
+#ifdef CONFIG_8260
+	/* I don't know why I didn't do it this way on the 8xx.......
+	*/
+	embed_config(&bp);
+	serial_init(bp);
+#endif
+
+	/* These values must be variables.  If not, the compiler optimizer
+	 * will remove some code, causing the size of the code to vary
+	 * when these values are zero.  This is bad because we first
+	 * compile with these zero to determine the size and offsets
+	 * in an image, than compile again with these set to the proper
+	 * discovered value.....Ya know, we used to read these from the
+	 * header a long time ago.....
+	 */
+	initrd_offset = INITRD_OFFSET;
+	initrd_size = INITRD_SIZE;
+
+	/* Grab some space for the command line and board info.  Since
+	 * we no longer use the ELF header, but it was loaded, grab
+	 * that space.
+	 */
+#ifdef CONFIG_MBX
+	cmd_line = (char *)(load_addr - 0x10000);
+
+	/* To be like everyone else, we need one too, although this
+	 * board information is passed from the boot rom.
+	 */
+	bp->bi_baudrate = 9600;
+#else
+	cmd_line = (char *)(0x200000);
+#endif
+	hold_residual = (bd_t *)(cmd_line + sizeof(cmd_buf));
+	/* copy board data */
+	if (bp)
+		memcpy(hold_residual,bp,sizeof(bd_t));
+
+	/* Set end of memory available to us.  It is always the highest
+	 * memory address provided by the board information.
+	 */
+	end_avail = (char *)(bp->bi_memsize);
+
+	puts("loaded at:     "); puthex(load_addr);
+	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
+	if ( (unsigned long)load_addr != (unsigned long)&start )
+	{
+		puts("relocated to:  "); puthex((unsigned long)&start);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+		puts("\n");
+	}
+
+	if ( bp )
+	{
+		puts("board data at: "); puthex((unsigned long)bp);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)bp + sizeof(bd_t)));
+		puts("\n");
+		puts("relocated to:  ");
+		puthex((unsigned long)hold_residual);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
+		puts("\n");
+	}
+
+	/* we have to subtract 0x10000 here to correct for objdump including the
+	   size of the elf header which we strip -- Cort */
+	zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
+	zimage_size = ZIMAGE_SIZE;
+
+	if ( initrd_offset )
+		initrd_start = load_addr - 0x10000 + initrd_offset;
+	else
+		initrd_start = 0;
+	initrd_end = initrd_size + initrd_start;
+
+	/*
+	 * setup avail_ram - this is the first part of ram usable
+	 * by the uncompress code. -- Cort
+	 */
+	avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
+	if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
+		&& (load_addr <= 0x01000000) )
+		avail_ram = (char *)(load_addr+(num_words*4));
+	if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
+		&& (load_addr <= 0x01000000) )
+		avail_ram = (char *)((unsigned long)&start+(num_words*4));
+	
+	/* relocate zimage */
+	puts("zimage at:     "); puthex((unsigned long)zimage_start);
+	puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
+	/*
+	 * There is no reason (yet) to relocate zImage for embedded boards.
+	 * To support boot from flash rom on 8xx embedded boards, I
+	 * assume if zimage start is over 16M we are booting from flash.
+	 * In this case, avilable ram will start just above the space we
+	 * have allocated for the command buffer and board information.
+	 */
+	if ((unsigned long)zimage_start > 0x01000000)
+		avail_ram = (char *)PAGE_ALIGN((unsigned long)hold_residual + sizeof(bd_t));
+
+	/* relocate initrd */
+	if ( initrd_start )
+	{
+		puts("initrd at:     "); puthex(initrd_start);
+		puts(" "); puthex(initrd_end); puts("\n");
+
+		/* We only have to relocate initrd if we find it is in Flash
+		 * rom.  This is because the kernel thinks it can toss the
+		 * pages into the free memory pool after it is done.  Use
+		 * the same 16M test.
+		 */
+		if ((unsigned long)initrd_start > 0x01000000) {
+			memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
+				(void *)initrd_start,
+				initrd_size );
+			initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE);
+			initrd_end = initrd_start + initrd_size;
+			end_avail = (char *)initrd_start;
+			puts("relocated to:  "); puthex(initrd_start);
+			puts(" "); puthex(initrd_end); puts("\n");
+		}
+		else {
+			avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end);
+		}
+	}
+
+
+	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
+	puthex((unsigned long)end_avail); puts("\n");
+	puts("\nLinux/PPC load: ");
+	timer = 0;
+	cp = cmd_line;
+	/* This is where we try and pick the right command line for booting.
+	 * If we were given one at compile time, use it.  It Is Right.
+	 * If we weren't, see if we have a ramdisk.  If so, thats root.
+	 * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom */
+#ifdef CONFIG_CMDLINE_BOOL
+	memcpy (cmd_line, compiled_string, sizeof(compiled_string));
+#else
+	if (initrd_start)
+		memcpy (cmd_line, ramroot_string, sizeof(ramroot_string));
+	else
+		memcpy (cmd_line, netroot_string, sizeof(netroot_string));
+#endif
+	while ( *cp ) putc(*cp++);
+	while (timer++ < 5*1000) {
+		if (tstc()) {
+			while ((ch = getc()) != '\n' && ch != '\r') {
+				if (ch == '\b' || ch == '\177') {
+					if (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				} else if (ch == '\030'		/* ^x */
+					   || ch == '\025') {	/* ^u */
+					while (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				} else {
+					*cp++ = ch;
+					putc(ch);
+				}
+			}
+			break;  /* Exit 'timer' loop */
+		}
+		udelay(1000);  /* 1 msec */
+	}
+	*cp = 0;
+	puts("\nUncompressing Linux...");
+
+	gunzip(0, 0x400000, zimage_start, &zimage_size);
+	puts("done.\n");
+	puts("Now booting the kernel\n");
+	return (unsigned long)hold_residual;
+}
+
+/*
+ * PCI/ISA I/O support
+ */
+
+volatile unsigned char *ISA_io  = (unsigned char *)0x80000000;
+volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
+
+void
+outb(int port, char val)
+{
+	/* Ensure I/O operations complete */
+	__asm__ volatile("eieio");
+	ISA_io[port] = val;
+}
+
+unsigned char
+inb(int port)
+{
+	/* Ensure I/O operations complete */
+	__asm__ volatile("eieio");
+	return (ISA_io[port]);
+}
+
+unsigned long
+local_to_PCI(unsigned long addr)
+{
+	return ((addr & 0x7FFFFFFF) | 0x80000000);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/pci.c linux/arch/ppc/boot/mbx/pci.c
--- v2.4.4/linux/arch/ppc/boot/mbx/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/pci.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,255 @@
+/*
+ * BK Id: SCCS/s.pci.c 1.6 05/18/01 15:17:06 cort
+ */
+/* Stand alone funtions for QSpan Tundra support.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/mpc8xx.h>
+
+/* To map PCI devices, you first write 0xffffffff into the device
+ * base address registers.  When the register is read back, the
+ * number of most significant '1' bits describes the amount of address
+ * space needed for mapping.  If the most significant bit is not set,
+ * either the device does not use that address register, or it has
+ * a fixed address that we can't change.  After the address is assigned,
+ * the command register has to be written to enable the card.
+ */
+typedef struct {
+	u_char	pci_bus;
+	u_char	pci_devfn;
+	ushort	pci_command;
+	uint	pci_addrs[6];
+} pci_map_t;
+
+/* We should probably dynamically allocate these structures.
+*/
+#define MAX_PCI_DEVS	32
+int	pci_dev_cnt;
+pci_map_t	pci_map[MAX_PCI_DEVS];
+
+void pci_conf_write(int bus, int device, int func, int reg, uint writeval);
+void pci_conf_read(int bus, int device, int func, int reg, void *readval);
+void probe_addresses(int bus, int devfn);
+void map_pci_addrs(void);
+
+/* This is a really stripped version of PCI bus scan.  All we are
+ * looking for are devices that exist.
+ */
+pci_scanner(int addr_probe)
+{
+	unsigned int devfn, l, max, class, bus_number;
+	unsigned char cmd, irq, tmp, hdr_type, is_multi;
+	int reg;
+
+	is_multi = 0;
+	bus_number = 0;
+	for (devfn = 0; devfn < 0xff; ++devfn) {
+		/* The device numbers are comprised of upper 5 bits of
+		 * device number and lower 3 bits of multi-function number.
+		 */
+		if ((devfn & 7) && !is_multi) {
+			/* Don't scan multifunction addresses if this is
+			 * not a multifunction device.
+			 */
+			continue;
+		}
+
+		/* Read the header to determine card type.
+		*/
+		qs_pci_read_config_byte(bus_number, devfn, PCI_HEADER_TYPE,
+								&hdr_type);
+
+		/* If this is a base device number, check the header to
+		 * determine if it is mulifunction.
+		 */
+		if ((devfn & 7) == 0)
+			is_multi = hdr_type & 0x80;
+
+		/* Check to see if the board is really in the slot.
+		*/
+		qs_pci_read_config_dword(bus_number, devfn, PCI_VENDOR_ID, &l);
+		/* some broken boards return 0 if a slot is empty: */
+		if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff ||
+							l == 0xffff0000) {
+			/* Nothing there.
+			*/
+			is_multi = 0;
+			continue;
+		}
+
+		/* If we are not performing an address probe,
+		 * just simply print out some information.
+		 */
+		if (!addr_probe) {
+			qs_pci_read_config_dword(bus_number, devfn,
+						PCI_CLASS_REVISION, &class);
+
+			class >>= 8;	    /* upper 3 bytes */
+
+#if 0
+			printf("Found (%3d:%d): vendor 0x%04x, device 0x%04x, class 0x%06x\n",
+				(devfn >> 3), (devfn & 7),
+				(l & 0xffff),  (l >> 16) & 0xffff, class);
+#else
+			puts("Found ("); puthex(devfn >> 3);
+			puts(":"); puthex(devfn & 7);
+			puts("): vendor "); puthex(l & 0xffff);
+			puts(", device "); puthex((l >> 16) & 0xffff);
+			puts(", class "); puthex(class); puts("\n");
+#endif
+		}
+		else {
+			/* If this is a "normal" device, build address list.
+			*/
+			if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL)
+				probe_addresses(bus_number, devfn);
+		}
+	}
+
+	/* Now map the boards.
+	*/
+	if (addr_probe)
+		map_pci_addrs();
+}
+
+/* Probe addresses for the specified device.  This is a destructive
+ * operation because it writes the registers.
+ */
+void
+probe_addresses(bus, devfn)
+{
+	int	i;
+	uint	pciaddr;
+	ushort	pcicmd;
+	pci_map_t	*pm;
+
+	if (pci_dev_cnt >= MAX_PCI_DEVS) {
+		puts("Too many PCI devices\n");
+		return;
+	}
+
+	pm = &pci_map[pci_dev_cnt++];
+
+	pm->pci_bus = bus;
+	pm->pci_devfn = devfn;
+
+	for (i=0; i<6; i++) {
+		qs_pci_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), -1);
+		qs_pci_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4),
+								&pciaddr);
+		pm->pci_addrs[i] = pciaddr;
+		qs_pci_read_config_word(bus, devfn, PCI_COMMAND, &pcicmd);
+		pm->pci_command = pcicmd;
+	}
+}
+
+/* Map the cards into the PCI space.  The PCI has separate memory
+ * and I/O spaces.  In addition, some memory devices require mapping
+ * below 1M.  The least significant 4 bits of the address register
+ * provide information.  If this is an I/O device, only the LS bit
+ * is used to indicate that, so I/O devices can be mapped to a two byte
+ * boundard.  Memory addresses can be mapped to a 32 byte boundary.
+ * The QSpan implementations usually have a 1Gbyte space for each
+ * memory and I/O spaces.
+ *
+ * This isn't a terribly fancy algorithm.  I just map the spaces from
+ * the top starting with the largest address space.  When finished,
+ * the registers are written and the card enabled.
+ *
+ * While the Tundra can map a large address space on most boards, we
+ * need to be careful because it may overlap other devices (like IMMR).
+ */
+#define MEMORY_SPACE_SIZE	0x20000000
+#define IO_SPACE_SIZE		0x20000000
+
+void
+map_pci_addrs()
+{
+	uint	pci_mem_top, pci_mem_low;
+	uint	pci_io_top;
+	uint	addr_mask, reg_addr, space;
+	int	i, j;
+	pci_map_t *pm;
+
+	pci_mem_top = MEMORY_SPACE_SIZE;
+	pci_io_top = IO_SPACE_SIZE;
+	pci_mem_low = (1 * 1024 * 1024);	/* Below one meg addresses */
+
+	/* We can't map anything more than the maximum space, but test
+	 * for it anyway to catch devices out of range.
+	 */
+	addr_mask = 0x80000000;
+
+	do {
+		space = (~addr_mask) + 1;	/* Size of the space */
+		for (i=0; i<pci_dev_cnt; i++) {
+			pm = &pci_map[i];
+			for (j=0; j<6; j++) {
+				/* If the MS bit is not set, this has either
+				 * already been mapped, or is not used.
+				 */
+				reg_addr = pm->pci_addrs[j];
+				if ((reg_addr & 0x80000000) == 0)
+					continue;
+				if (reg_addr & PCI_BASE_ADDRESS_SPACE_IO) {
+					if ((reg_addr & PCI_BASE_ADDRESS_IO_MASK) != addr_mask)
+						continue;
+					if (pci_io_top < space) {
+						puts("Out of PCI I/O space\n");
+					}
+					else {
+						pci_io_top -= space;
+						pm->pci_addrs[j] = pci_io_top;
+						pm->pci_command |= PCI_COMMAND_IO;
+					}
+				}
+				else {
+					if ((reg_addr & PCI_BASE_ADDRESS_MEM_MASK) != addr_mask)
+						continue;
+
+					/* Memory space.  Test if below 1M.
+					*/
+					if (reg_addr & PCI_BASE_ADDRESS_MEM_TYPE_1M) {
+						if (pci_mem_low < space) {
+							puts("Out of PCI 1M space\n");
+						}
+						else {
+							pci_mem_low -= space;
+							pm->pci_addrs[j] = pci_mem_low;
+						}
+					}
+					else {
+						if (pci_mem_top < space) {
+							puts("Out of PCI Mem space\n");
+						}
+						else {
+							pci_mem_top -= space;
+							pm->pci_addrs[j] = pci_mem_top;
+						}
+					}
+					pm->pci_command |= PCI_COMMAND_MEMORY;
+				}
+			}
+		}
+		addr_mask >>= 1;
+		addr_mask |= 0x80000000;
+	} while (addr_mask != 0xfffffffe);
+	
+	/* Now, run the list one more time and map everything.
+	*/
+	for (i=0; i<pci_dev_cnt; i++) {
+		pm = &pci_map[i];
+		for (j=0; j<6; j++) {
+			qs_pci_write_config_dword(pm->pci_bus, pm->pci_devfn,
+				PCI_BASE_ADDRESS_0 + (j * 4), pm->pci_addrs[j]);
+		}
+
+		/* Enable memory or address mapping.
+		*/
+		qs_pci_write_config_word(pm->pci_bus, pm->pci_devfn, PCI_COMMAND,
+			pm->pci_command);
+	}
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/qspan_pci.c linux/arch/ppc/boot/mbx/qspan_pci.c
--- v2.4.4/linux/arch/ppc/boot/mbx/qspan_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/qspan_pci.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,271 @@
+/*
+ * BK Id: SCCS/s.qspan_pci.c 1.6 05/18/01 15:17:06 cort
+ */
+/*
+ * LinuxPPC arch/ppc/kernel/qspan_pci.c   Dan Malek (dmalek@jlc.net)
+ *
+ * QSpan Motorola bus to PCI bridge.  The config address register
+ * is located 0x500 from the base of the bridge control/status registers.
+ * The data register is located at 0x504.
+ * This is a two step operation.  First, the address register is written,
+ * then the data register is read/written as required.
+ * I don't know what to do about interrupts (yet).
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/mpc8xx.h>
+
+/*
+ * When reading the configuration space, if something does not respond
+ * the bus times out and we get a machine check interrupt.  So, the
+ * good ol' exception tables come to mind to trap it and return some
+ * value.
+ *
+ * On an error we just return a -1, since that is what the caller wants
+ * returned if nothing is present.  I copied this from __get_user_asm,
+ * with the only difference of returning -1 instead of EFAULT.
+ * There is an associated hack in the machine check trap code.
+ *
+ * The QSPAN is also a big endian device, that is it makes the PCI
+ * look big endian to us.  This presents a problem for the Linux PCI
+ * functions, which assume little endian.  For example, we see the
+ * first 32-bit word like this:
+ *	------------------------
+ *	| Device ID | Vendor ID |
+ *	------------------------
+ * If we read/write as a double word, that's OK.  But in our world,
+ * when read as a word, device ID is at location 0, not location 2 as
+ * the little endian PCI would believe.  We have to switch bits in
+ * the PCI addresses given to us to get the data to/from the correct
+ * byte lanes.
+ *
+ * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5.
+ * It always forces the MS bit to zero.  Therefore, dev_fn values
+ * greater than 128 are returned as "no device found" errors.
+ *
+ * The QSPAN can only perform long word (32-bit) configuration cycles.
+ * The "offset" must have the two LS bits set to zero.  Read operations
+ * require we read the entire word and then sort out what should be
+ * returned.  Write operations other than long word require that we
+ * read the long word, update the proper word or byte, then write the
+ * entire long word back.
+ *
+ * PCI Bridge hack.  We assume (correctly) that bus 0 is the primary
+ * PCI bus from the QSPAN.  If we are called with a bus number other
+ * than zero, we create a Type 1 configuration access that a downstream
+ * PCI bridge will interpret.
+ */
+
+#define __get_pci_config(x, addr, op)		\
+	__asm__ __volatile__(				\
+		"1:	"op" %0,0(%1)\n"		\
+		"	eieio\n"			\
+		"2:\n"					\
+		".section .fixup,\"ax\"\n"		\
+		"3:	li %0,-1\n"			\
+		"	b 2b\n"				\
+		".section __ex_table,\"a\"\n"		\
+		"	.align 2\n"			\
+		"	.long 1b,3b\n"			\
+		".text"					\
+		: "=r"(x) : "r"(addr))
+
+#define QS_CONFIG_ADDR	((volatile uint *)(PCI_CSR_ADDR + 0x500))
+#define QS_CONFIG_DATA	((volatile uint *)(PCI_CSR_ADDR + 0x504))
+
+#define mk_config_addr(bus, dev, offset) \
+	(((bus)<<16) | ((dev)<<8) | (offset & 0xfc))
+
+#define mk_config_type1(bus, dev, offset) \
+	mk_config_addr(bus, dev, offset) | 1;
+
+/* Initialize the QSpan device registers after power up.
+*/
+qspan_init()
+{
+	uint	*qptr;
+
+
+
+	qptr = (uint *)PCI_CSR_ADDR;
+
+	/* PCI Configuration/status.  Upper bits written to clear
+	 * pending interrupt or status.  Lower bits enable QSPAN as
+	 * PCI master, enable memory and I/O cycles, and enable PCI
+	 * parity error checking.
+	 * IMPORTANT:  The last two bits of this word enable PCI
+	 * master cycles into the QBus.  The QSpan is broken and can't
+	 * meet the timing specs of the PQ bus for this to work.  Therefore,
+	 * if you don't have external bus arbitration, you can't use
+	 * this function.
+	 */
+#ifdef EXTERNAL_PQ_ARB
+	qptr[1] = 0xf9000147;
+#else
+	qptr[1] = 0xf9000144;
+#endif
+
+	/* PCI Misc configuration.  Set PCI latency timer resolution
+	 * of 8 cycles, set cache size to 4 x 32.
+	 */
+	qptr[3] = 0;
+
+	/* Set up PCI Target address mapping.  Enable, Posted writes,
+	 * 2Gbyte space (processor memory controller determines actual size).
+	 */
+	qptr[64] = 0x8f000080;
+
+	/* Map processor 0x80000000 to PCI 0x00000000.
+	 * Processor address bit 1 determines I/O type access (0x80000000)
+	 * or memory type access (0xc0000000).
+	 */
+	qptr[65] = 0x80000000;
+
+	/* Enable error logging and clear any pending error status.
+	*/
+	qptr[80] = 0x90000000;
+
+	qptr[512] = 0x000c0003;
+
+	/* Set up Qbus slave image.
+	*/
+	qptr[960] = 0x01000000;
+	qptr[961] = 0x000000d1;
+	qptr[964] = 0x00000000;
+	qptr[965] = 0x000000d1;
+
+}
+
+/* Functions to support PCI bios-like features to read/write configuration
+ * space.  If the function fails for any reason, a -1 (0xffffffff) value
+ * must be returned.
+ */
+#define DEVICE_NOT_FOUND	(-1)
+#define SUCCESSFUL		0
+
+int qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,
+				  unsigned char offset, unsigned char *val)
+{
+	uint	temp;
+	u_char	*cp;
+
+	if ((bus > 7) || (dev_fn > 127)) {
+		*val = 0xff;
+		return DEVICE_NOT_FOUND;
+	}
+
+	if (bus == 0)
+		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+	else
+		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+	__get_pci_config(temp, QS_CONFIG_DATA, "lwz");
+
+	offset ^= 0x03;
+	cp = ((u_char *)&temp) + (offset & 0x03);
+	*val = *cp;
+	return SUCCESSFUL;
+}
+
+int qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn,
+				  unsigned char offset, unsigned short *val)
+{
+	uint	temp;
+	ushort	*sp;
+
+	if ((bus > 7) || (dev_fn > 127)) {
+		*val = 0xffff;
+		return DEVICE_NOT_FOUND;
+	}
+
+	if (bus == 0)
+		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+	else
+		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+	__get_pci_config(temp, QS_CONFIG_DATA, "lwz");
+	offset ^= 0x02;
+
+	sp = ((ushort *)&temp) + ((offset >> 1) & 1);
+	*val = *sp;
+	return SUCCESSFUL;
+}
+
+int qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,
+				   unsigned char offset, unsigned int *val)
+{
+	if ((bus > 7) || (dev_fn > 127)) {
+		*val = 0xffffffff;
+		return DEVICE_NOT_FOUND;
+	}
+	if (bus == 0)
+		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+	else
+		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+	__get_pci_config(*val, QS_CONFIG_DATA, "lwz");
+	return SUCCESSFUL;
+}
+
+int qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,
+				   unsigned char offset, unsigned char val)
+{
+	uint	temp;
+	u_char	*cp;
+
+	if ((bus > 7) || (dev_fn > 127))
+		return DEVICE_NOT_FOUND;
+
+	qs_pci_read_config_dword(bus, dev_fn, offset, &temp);
+
+	offset ^= 0x03;
+	cp = ((u_char *)&temp) + (offset & 0x03);
+	*cp = val;
+
+	if (bus == 0)
+		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+	else
+		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+	*QS_CONFIG_DATA = temp;
+
+	return SUCCESSFUL;
+}
+
+int qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn,
+				   unsigned char offset, unsigned short val)
+{
+	uint	temp;
+	ushort	*sp;
+
+	if ((bus > 7) || (dev_fn > 127))
+		return DEVICE_NOT_FOUND;
+
+	qs_pci_read_config_dword(bus, dev_fn, offset, &temp);
+
+	offset ^= 0x02;
+	sp = ((ushort *)&temp) + ((offset >> 1) & 1);
+	*sp = val;
+
+	if (bus == 0)
+		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+	else
+		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+	*QS_CONFIG_DATA = temp;
+
+	return SUCCESSFUL;
+}
+
+int qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,
+				    unsigned char offset, unsigned int val)
+{
+	if ((bus > 7) || (dev_fn > 127))
+		return DEVICE_NOT_FOUND;
+
+	if (bus == 0)
+		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
+	else
+		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
+	*(unsigned int *)QS_CONFIG_DATA = val;
+
+	return SUCCESSFUL;
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mbx/rdimage.c linux/arch/ppc/boot/mbx/rdimage.c
--- v2.4.4/linux/arch/ppc/boot/mbx/rdimage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mbx/rdimage.c	Thu May 24 15:02:06 2001
@@ -0,0 +1,11 @@
+/*
+ * BK Id: SCCS/s.rdimage.c 1.6 05/18/01 15:17:06 cort
+ */
+/*
+ * rdimage.c
+ *
+ * Dummy file to allow a compressed initrd to be added
+ * into a linker section, accessed by the boot coode
+ */
+
+char dummy_for_rdimage;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.4.4/linux/arch/ppc/boot/misc.c	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/boot/misc.c	Wed Dec 31 16:00:00 1969
@@ -1,845 +0,0 @@
-/*
- * misc.c
- *
- * $Id: misc.c,v 1.68 1999/10/20 22:08:08 cort Exp $
- * 
- * Adapted for PowerPC by Gary Thomas
- *
- * Rewritten by Cort Dougan (cort@cs.nmt.edu)
- * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
- */
-
-#include <linux/types.h>
-#include "../coffboot/zlib.h"
-#include "asm/residual.h"
-#include <linux/elf.h>
-#include <linux/config.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/bootinfo.h>
-#include <asm/mmu.h>
-#if defined(CONFIG_SERIAL_CONSOLE)
-#include "ns16550.h"
-struct NS16550 *com_port;
-#endif /* CONFIG_SERIAL_CONSOLE */
-
-/*
- * Please send me load/board info and such data for hardware not
- * listed here so I can keep track since things are getting tricky
- * with the different load addrs with different firmware.  This will
- * help to avoid breaking the load/boot process.
- * -- Cort
- */
-char *avail_ram;
-char *end_avail;
-extern char _end[];
-
-#ifdef CONFIG_CMDLINE
-#define CMDLINE CONFIG_CMDLINE
-#else
-#define CMDLINE "";
-#endif
-char cmd_preset[] = CMDLINE;
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
-
-int keyb_present = 1;	/* keyboard controller is present by default */
-RESIDUAL hold_resid_buf;
-RESIDUAL *hold_residual = &hold_resid_buf;
-unsigned long initrd_start = 0, initrd_end = 0;
-char *zimage_start;
-int zimage_size;
-
-char *vidmem = (char *)0xC00B8000;
-int lines, cols;
-int orig_x, orig_y;
-
-void puts(const char *);
-void putc(const char c);
-void puthex(unsigned long val);
-void _bcopy(char *src, char *dst, int len);
-void * memcpy(void * __dest, __const void * __src,
-			    int __n);
-void gunzip(void *, int, unsigned char *, int *);
-static int _cvt(unsigned long val, char *buf, long radix, char *digits);
-unsigned char inb(int);
-
-void pause()
-{
-	puts("pause\n");
-}
-
-void exit()
-{
-	puts("exit\n");
-	while(1); 
-}
-
-static void clear_screen()
-{
-	int i, j;
-	for (i = 0;  i < lines;  i++) {
-	  for (j = 0;  j < cols;  j++) {
-	    vidmem[((i*cols)+j)*2] = ' ';
-	    vidmem[((i*cols)+j)*2+1] = 0x07;
-	  }
-	}
-}
-
-static void scroll()
-{
-	int i;
-
-	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
-	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
-		vidmem[i] = ' ';
-}
-
-tstc(void)
-{
-#if defined(CONFIG_SERIAL_CONSOLE)
-	if (keyb_present)
-		return (CRT_tstc() || NS16550_tstc(com_port));
-	else
-		NS16550_tstc(com_port);
-#else
-	return (CRT_tstc() );
-#endif /* CONFIG_SERIAL_CONSOLE */
-}
-
-getc(void)
-{
-	while (1) {
-#if defined(CONFIG_SERIAL_CONSOLE)
-		if (NS16550_tstc(com_port)) return (NS16550_getc(com_port));
-#endif /* CONFIG_SERIAL_CONSOLE */
-		if (keyb_present)
-			if (CRT_tstc()) return (CRT_getc());
-	}
-}
-
-void 
-putc(const char c)
-{
-	int x,y;
-
-#if defined(CONFIG_SERIAL_CONSOLE)
-	NS16550_putc(com_port, c);
-	if ( c == '\n' ) NS16550_putc(com_port, '\r');
-#endif /* CONFIG_SERIAL_CONSOLE */
-
-	x = orig_x;
-	y = orig_y;
-
-	if ( c == '\n' ) {
-		x = 0;
-		if ( ++y >= lines ) {
-			scroll();
-			y--;
-		}
-	} else if (c == '\r') {
-		x = 0;
-	} else if (c == '\b') {
-		if (x > 0) {
-			x--;
-		}
-	} else {
-		vidmem [ ( x + cols * y ) * 2 ] = c; 
-		if ( ++x >= cols ) {
-			x = 0;
-			if ( ++y >= lines ) {
-				scroll();
-				y--;
-			}
-		}
-	}
-
-	cursor(x, y);
-
-	orig_x = x;
-	orig_y = y;
-}
-
-void puts(const char *s)
-{
-	int x,y;
-	char c;
-
-	x = orig_x;
-	y = orig_y;
-
-	while ( ( c = *s++ ) != '\0' ) {
-#if defined(CONFIG_SERIAL_CONSOLE)
-	        NS16550_putc(com_port, c);
-	        if ( c == '\n' ) NS16550_putc(com_port, '\r');
-#endif /* CONFIG_SERIAL_CONSOLE */
-
-		if ( c == '\n' ) {
-			x = 0;
-			if ( ++y >= lines ) {
-				scroll();
-				y--;
-			}
-		} else if (c == '\b') {
-		  if (x > 0) {
-		    x--;
-		  }
-		} else {
-			vidmem [ ( x + cols * y ) * 2 ] = c; 
-			if ( ++x >= cols ) {
-				x = 0;
-				if ( ++y >= lines ) {
-					scroll();
-					y--;
-				}
-			}
-		}
-	}
-
-	cursor(x, y);
-
-	orig_x = x;
-	orig_y = y;
-}
-
-void * memcpy(void * __dest, __const void * __src,
-			    int __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++) d[i] = s[i];
-}
-
-int memcmp(__const void * __dest, __const void * __src,
-			    int __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++, d++, s++)
-	{
-		if (*d != *s)
-		{
-			return (*s - *d);
-		}
-	}
-	return (0);
-}
-
-void error(char *x)
-{
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
-
-	while(1);	/* Halt */
-}
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-	void *p = avail_ram;
-	
-	size *= items;
-	size = (size + 7) & -8;
-	avail_ram += size;
-	if (avail_ram > end_avail) {
-		puts("oops... out of memory\n");
-		pause();
-	}
-	return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-	z_stream s;
-	int r, i, flags;
-	
-	/* skip header */
-	i = 10;
-	flags = src[3];
-	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-		puts("bad gzipped data\n");
-		exit();
-	}
-	if ((flags & EXTRA_FIELD) != 0)
-		i = 12 + src[10] + (src[11] << 8);
-	if ((flags & ORIG_NAME) != 0)
-		while (src[i++] != 0)
-			;
-	if ((flags & COMMENT) != 0)
-		while (src[i++] != 0)
-			;
-	if ((flags & HEAD_CRC) != 0)
-		i += 2;
-	if (i >= *lenp) {
-		puts("gunzip: ran out of data in header\n");
-		exit();
-	}
-	
-	s.zalloc = zalloc;
-	s.zfree = zfree;
-	r = inflateInit2(&s, -MAX_WBITS);
-	if (r != Z_OK) {
-		puts("inflateInit2 returned %d\n");
-		exit();
-	}
-	s.next_in = src + i;
-	s.avail_in = *lenp - i;
-	s.next_out = dst;
-	s.avail_out = dstlen;
-	r = inflate(&s, Z_FINISH);
-	if (r != Z_OK && r != Z_STREAM_END) {
-		puts("inflate returned %d\n");
-		exit();
-	}
-	*lenp = s.next_out - (unsigned char *) dst;
-	inflateEnd(&s);
-}
-
-unsigned long
-decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
-		  RESIDUAL *residual, void *OFW_interface)
-{
-	int timer;
-	extern unsigned long start;
-	char *cp, ch;
-	unsigned long i;
-	BATU *u;
-	BATL *l;
-	unsigned long TotalMemory;
-	unsigned long orig_MSR;
-	int dev_handle;
-	int mem_info[2];
-	int res, size;
-	unsigned char board_type;
-	unsigned char base_mod;
-
-	lines = 25;
-	cols = 80;
-	orig_x = 0;
-	orig_y = 24;
-	
-	/*
-	 * IBM's have the MMU on, so we have to disable it or
-	 * things get really unhappy in the kernel when
-	 * trying to setup the BATs with the MMU on
-	 * -- Cort
-	 */
-	flush_instruction_cache();
-	_put_HID0(_get_HID0() & ~0x0000C000);
-	_put_MSR((orig_MSR = _get_MSR()) & ~0x0030);
-
-#if defined(CONFIG_SERIAL_CONSOLE)
-	com_port = (struct NS16550 *)NS16550_init(0);
-#endif /* CONFIG_SERIAL_CONSOLE */
-	vga_init(0xC0000000);
-
-	if (residual)
-	{
-		/* Is this Motorola PPCBug? */
-		if ((1 & residual->VitalProductData.FirmwareSupports) &&
-		    (1 == residual->VitalProductData.FirmwareSupplier)) {
-			board_type = inb(0x800) & 0xF0;
-
-			/* If this is genesis 2 board then check for no
-			 * keyboard controller and more than one processor.
-			 */
-			if (board_type == 0xe0) {	
-				base_mod = inb(0x803);
-				/* if a MVME2300/2400 or a Sitka then no keyboard */
-				if((base_mod == 0xFA) || (base_mod == 0xF9) ||
-				   (base_mod == 0xE1)) {
-					keyb_present = 0;	/* no keyboard */
-				}
-			}
-		}
-		memcpy(hold_residual,residual,sizeof(RESIDUAL));
-	} else {
-		/* Assume 32M in the absence of more info... */
-		TotalMemory = 0x02000000;
-		/*
-		 * This is a 'best guess' check.  We want to make sure
-		 * we don't try this on a PReP box without OF
-		 *     -- Cort
-		 */
-		while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) )
-		{
-			/* The MMU needs to be on when we call OFW */
-			_put_MSR(orig_MSR);
-			of_init(OFW_interface);
-
-			/* get handle to memory description */
-			res = of_finddevice("/memory@0", 
-					    &dev_handle);
-			// puthex(res);  puts("\n");
-			if (res) break;
-			
-			/* get the info */
-			// puts("get info = ");
-			res = of_getprop(dev_handle, 
-					 "reg", 
-					 mem_info, 
-					 sizeof(mem_info), 
-					 &size);
-			// puthex(res);  puts(", info = "); puthex(mem_info[0]);  
-			// puts(" ");  puthex(mem_info[1]);   puts("\n");
-			if (res) break;
-			
-			TotalMemory = mem_info[1];
-			break;
-		}
-		hold_residual->TotalMemory = TotalMemory;
-		residual = hold_residual;
-		/* Turn MMU back off */
-		_put_MSR(orig_MSR & ~0x0030);
-        }
-
-	/* assume the chunk below 8M is free */
-	end_avail = (char *)0x00800000;
-
-	/* tell the user where we were loaded at and where we
-	 * were relocated to for debugging this process
-	 */
-	puts("loaded at:     "); puthex(load_addr);
-	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
-	if ( (unsigned long)load_addr != (unsigned long)&start )
-	{
-		puts("relocated to:  "); puthex((unsigned long)&start);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
-		puts("\n");
-	}
-
-	if ( residual )
-	{
-		puts("board data at: "); puthex((unsigned long)residual);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL)));
-		puts("\n");
-		puts("relocated to:  ");
-		puthex((unsigned long)hold_residual);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL)));
-		puts("\n");
-	}
-
-	/* we have to subtract 0x10000 here to correct for objdump including the
-	   size of the elf header which we strip -- Cort */
-	zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
-	zimage_size = ZIMAGE_SIZE;
-
-	if ( INITRD_OFFSET )
-		initrd_start = load_addr - 0x10000 + INITRD_OFFSET;
-	else
-		initrd_start = 0;
-	initrd_end = INITRD_SIZE + initrd_start;
-
-	/*
-	 * Find a place to stick the zimage and initrd and 
-	 * relocate them if we have to. -- Cort
-	 */
-	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
-	puts("zimage at:     "); puthex((unsigned long)zimage_start);
-	puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
-	if ( (unsigned long)zimage_start <= 0x00800000 )
-	{
-		memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
-		zimage_start = (char *)avail_ram;
-		puts("relocated to:  "); puthex((unsigned long)zimage_start);
-		puts(" ");
-		puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
-		puts("\n");
-		avail_ram += zimage_size;
-	}
-
-	/* relocate initrd */
-	if ( initrd_start )
-	{
-		puts("initrd at:     "); puthex(initrd_start);
-		puts(" "); puthex(initrd_end); puts("\n");
-		if ( (unsigned long)initrd_start <= 0x00800000 )
-		{
-			memcpy( (void *)avail_ram,
-				(void *)initrd_start, initrd_end-initrd_start );
-			puts("relocated to:  ");
-			initrd_end = (unsigned long) avail_ram + (initrd_end-initrd_start);
-			initrd_start = (unsigned long)avail_ram;
-			puthex((unsigned long)initrd_start);
-			puts(" ");
-			puthex((unsigned long)initrd_end);
-			puts("\n");
-		}
-		avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end);
-	}
-
-	avail_ram = (char *)0x00400000;
-	end_avail = (char *)0x00800000;
-	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
-	puthex((unsigned long)end_avail); puts("\n");
-
-	if (keyb_present)
-		CRT_tstc();  /* Forces keyboard to be initialized */
-
-	puts("\nLinux/PPC load: ");
-	timer = 0;
-	cp = cmd_line;
-	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
-	while ( *cp ) putc(*cp++);
-	while (timer++ < 5*1000) {
-		if (tstc()) {
-			while ((ch = getc()) != '\n' && ch != '\r') {
-				if (ch == '\b') {
-					if (cp != cmd_line) {
-						cp--;
-						puts("\b \b");
-					}
-				} else {
-					*cp++ = ch;
-					putc(ch);
-				}
-			}
-			break;  /* Exit 'timer' loop */
-		}
-		udelay(1000);  /* 1 msec */
-	}
-	*cp = 0;
-	puts("\n");
-
-	puts("Uncompressing Linux...");
-	gunzip(0, 0x400000, zimage_start, &zimage_size);
-	puts("done.\n");
-	
-	{
-		struct bi_record *rec;
-	    
-		rec = (struct bi_record *)PAGE_ALIGN(zimage_size);
-	    
-		rec->tag = BI_FIRST;
-		rec->size = sizeof(struct bi_record);
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-		rec->tag = BI_BOOTLOADER_ID;
-		memcpy( (void *)rec->data, "prepboot", 9);
-		rec->size = sizeof(struct bi_record) + 8 + 1;
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-		rec->tag = BI_MACHTYPE;
-		rec->data[0] = _MACH_prep;
-		rec->data[1] = 1;
-		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-		rec->tag = BI_CMD_LINE;
-		memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
-		rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
-		rec = (struct bi_record *)((ulong)rec + rec->size);
-		
-		rec->tag = BI_LAST;
-		rec->size = sizeof(struct bi_record);
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	}
-	puts("Now booting the kernel\n");
-	return (unsigned long)hold_residual;
-}
-
-void puthex(unsigned long val)
-{
-	unsigned char buf[10];
-	int i;
-	for (i = 7;  i >= 0;  i--)
-	{
-		buf[i] = "0123456789ABCDEF"[val & 0x0F];
-		val >>= 4;
-	}
-	buf[8] = '\0';
-	puts(buf);
-}
-
-/*
- * PCI/ISA I/O support
- */
-
-volatile unsigned char *ISA_io  = (unsigned char *)0x80000000;
-volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
-
-void
-outb(int port, char val)
-{
-	/* Ensure I/O operations complete */
-	__asm__ volatile("eieio");
-	ISA_io[port] = val;
-}
-
-unsigned char
-inb(int port)
-{
-	/* Ensure I/O operations complete */
-	__asm__ volatile("eieio");
-	return (ISA_io[port]);
-}
-
-unsigned long
-local_to_PCI(unsigned long addr)
-{
-	return ((addr & 0x7FFFFFFF) | 0x80000000);
-}
-
-void
-_bcopy(char *src, char *dst, int len)
-{
-	while (len--) *dst++ = *src++;
-}
-
-
-#define FALSE 0
-#define TRUE  1
-#include <stdarg.h>
-
-int
-strlen(char *s)
-{
-	int len = 0;
-	while (*s++) len++;
-	return len;
-}
-
-_printk(char const *fmt, ...)
-{
-	int ret;
-	va_list ap;
-
-	va_start(ap, fmt);
-	ret = _vprintk(putc, fmt, ap);
-	va_end(ap);
-	return (ret);
-}
-
-#define is_digit(c) ((c >= '0') && (c <= '9'))
-
-int
-_vprintk(putc, fmt0, ap)
-int (*putc)();
-const char *fmt0;
-va_list ap;
-{
-	char c, sign, *cp;
-	int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
-	char buf[32];
-	long val;
-	while (c = *fmt0++)
-	{
-		if (c == '%')
-		{
-			c = *fmt0++;
-			left_prec = right_prec = pad_on_right = 0;
-			if (c == '-')
-			{
-				c = *fmt0++;
-				pad_on_right++;
-			}
-			if (c == '0')
-			{
-				zero_fill = TRUE;
-				c = *fmt0++;
-			} else
-			{
-				zero_fill = FALSE;
-			}
-			while (is_digit(c))
-			{
-				left_prec = (left_prec * 10) + (c - '0');
-				c = *fmt0++;
-			}
-			if (c == '.')
-			{
-				c = *fmt0++;
-				zero_fill++;
-				while (is_digit(c))
-				{
-					right_prec = (right_prec * 10) + (c - '0');
-					c = *fmt0++;
-				}
-			} else
-			{
-				right_prec = left_prec;
-			}
-			sign = '\0';
-			switch (c)
-			{
-			case 'd':
-			case 'x':
-			case 'X':
-				val = va_arg(ap, long);
-				switch (c)
-				{
-				case 'd':
-					if (val < 0)
-					{
-						sign = '-';
-						val = -val;
-					}
-					length = _cvt(val, buf, 10, "0123456789");
-					break;
-				case 'x':
-					length = _cvt(val, buf, 16, "0123456789abcdef");
-					break;
-				case 'X':
-					length = _cvt(val, buf, 16, "0123456789ABCDEF");
-					break;
-				}
-				cp = buf;
-				break;
-			case 's':
-				cp = va_arg(ap, char *);
-				length = strlen(cp);
-				break;
-			case 'c':
-				c = va_arg(ap, long /*char*/);
-				(*putc)(c);
-				continue;
-			default:
-				(*putc)('?');
-			}
-			pad = left_prec - length;
-			if (sign != '\0')
-			{
-				pad--;
-			}
-			if (zero_fill)
-			{
-				c = '0';
-				if (sign != '\0')
-				{
-					(*putc)(sign);
-					sign = '\0';
-				}
-			} else
-			{
-				c = ' ';
-			}
-			if (!pad_on_right)
-			{
-				while (pad-- > 0)
-				{
-					(*putc)(c);
-				}
-			}
-			if (sign != '\0')
-			{
-				(*putc)(sign);
-			}
-			while (length-- > 0)
-			{
-				(*putc)(c = *cp++);
-				if (c == '\n')
-				{
-					(*putc)('\r');
-				}
-			}
-			if (pad_on_right)
-			{
-				while (pad-- > 0)
-				{
-					(*putc)(c);
-				}
-			}
-		} else
-		{
-			(*putc)(c);
-			if (c == '\n')
-			{
-				(*putc)('\r');
-			}
-		}
-	}
-}
-
-int _cvt(unsigned long val, char *buf, long radix, char *digits)
-{
-	char temp[80];
-	char *cp = temp;
-	int length = 0;
-	if (val == 0)
-	{ /* Special case */
-		*cp++ = '0';
-	} else
-		while (val)
-		{
-			*cp++ = digits[val % radix];
-			val /= radix;
-		}
-	while (cp != temp)
-	{
-		*buf++ = *--cp;
-		length++;
-	}
-	*buf = '\0';
-	return (length);
-}
-
-_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
-{
-	int i, c;
-	if ((unsigned int)s > (unsigned int)p)
-	{
-		s = (unsigned int)s - (unsigned int)p;
-	}
-	while (s > 0)
-	{
-		if (base)
-		{
-			_printk("%06X: ", (int)p - (int)base);
-		} else
-		{
-			_printk("%06X: ", p);
-		}
-		for (i = 0;  i < 16;  i++)
-		{
-			if (i < s)
-			{
-				_printk("%02X", p[i] & 0xFF);
-			} else
-			{
-				_printk("  ");
-			}
-			if ((i % 2) == 1) _printk(" ");
-			if ((i % 8) == 7) _printk(" ");
-		}
-		_printk(" |");
-		for (i = 0;  i < 16;  i++)
-		{
-			if (i < s)
-			{
-				c = p[i] & 0xFF;
-				if ((c < 0x20) || (c >= 0x7F)) c = '.';
-			} else
-			{
-				c = ' ';
-			}
-			_printk("%c", c);
-		}
-		_printk("|\n");
-		s -= 16;
-		p += 16;
-	}
-}
-
-_dump_buf(unsigned char *p, int s)
-{
-	_printk("\n");
-	_dump_buf_with_offset(p, s, 0);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/mkprep.c linux/arch/ppc/boot/mkprep.c
--- v2.4.4/linux/arch/ppc/boot/mkprep.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/boot/mkprep.c	Wed Dec 31 16:00:00 1969
@@ -1,287 +0,0 @@
-/*
- * Makes a prep bootable image which can be dd'd onto
- * a disk device to make a bootdisk.  Will take
- * as input a elf executable, strip off the header
- * and write out a boot image as:
- * 1) default - strips elf header
- *      suitable as a network boot image
- * 2) -pbp - strips elf header and writes out prep boot partition image
- *      cat or dd onto disk for booting
- * 3) -asm - strips elf header and writes out as asm data
- *      useful for generating data for a compressed image
- *                  -- Cort
- *
- * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
- */
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <errno.h>
-
-#define cpu_to_le32(x) le32_to_cpu((x))
-unsigned long le32_to_cpu(unsigned long x)
-{
-     	return (((x & 0x000000ffU) << 24) |
-		((x & 0x0000ff00U) <<  8) |
-		((x & 0x00ff0000U) >>  8) |
-		((x & 0xff000000U) >> 24));
-}
-
-
-#define cpu_to_le16(x) le16_to_cpu((x))
-unsigned short le16_to_cpu(unsigned short x)
-{
-	return (((x & 0x00ff) << 8) |
-		((x & 0xff00) >> 8));
-}
-
-#define cpu_to_be32(x) (x)
-#define be32_to_cpu(x) (x)
-#define cpu_to_be16(x) (x)
-#define be16_to_cpu(x) (x)
-
-/* size of read buffer */
-#define SIZE 0x1000
-
-
-typedef unsigned long dword_t;
-typedef unsigned short word_t;
-typedef unsigned char byte_t;
-typedef byte_t block_t[512];
-typedef byte_t page_t[4096];
-
-
-/*
- * Partition table entry
- *  - from the PReP spec
- */
-typedef struct partition_entry {
-  byte_t	boot_indicator;
-  byte_t	starting_head;
-  byte_t	starting_sector;
-  byte_t	starting_cylinder;
-
-  byte_t	system_indicator;
-  byte_t	ending_head;
-  byte_t	ending_sector;
-  byte_t	ending_cylinder;
-
-  dword_t	beginning_sector;
-  dword_t	number_of_sectors;
-} partition_entry_t;
-
-#define BootActive	0x80
-#define SystemPrep	0x41
-
-void copy_image(int , int);
-void write_prep_partition(int , int );
-void write_asm_data( int in, int out );
-
-unsigned int elfhdr_size = 65536;
-
-int main(int argc, char *argv[])
-{
-  int in_fd, out_fd;
-  int argptr = 1;
-  unsigned int prep = 0;
-  unsigned int asmoutput = 0;
-
-  if ( (argc < 3) || (argc > 4) )
-  {
-    fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]);
-    exit(-1);
-  }
-
-  /* needs to handle args more elegantly -- but this is a small/simple program */
-  
-  /* check for -pbp */
-  if ( !strcmp( argv[argptr], "-pbp" ) )
-  {
-    prep = 1;
-    argptr++;
-  }
-  
-  /* check for -asm */
-  if ( !strcmp( argv[argptr], "-asm" ) )
-  {
-    asmoutput = 1;
-    argptr++;
-  }
-
-  /* input file */
-  if ( !strcmp( argv[argptr], "-" ) )
-    in_fd = 0;			/* stdin */
-  else
-    if ((in_fd = open( argv[argptr] , 0)) < 0)
-      exit(-1);
-  argptr++;
-
-  /* output file */
-  if ( !strcmp( argv[argptr], "-" ) )
-    out_fd = 1;			/* stdout */
-  else
-    if ((out_fd = creat( argv[argptr] , 0755)) < 0)
-      exit(-1);
-  argptr++;
-
-  /* skip elf header in input file */
-  /*if ( !prep )*/
-  lseek(in_fd, elfhdr_size, SEEK_SET);
-  
-  /* write prep partition if necessary */
-  if ( prep )
-	  write_prep_partition( in_fd, out_fd );
-
-  /* write input image to bootimage */
-  if ( asmoutput )
-	  write_asm_data( in_fd, out_fd );
-  else
-	  copy_image(in_fd, out_fd);
-  
-  return 0;
-}
-
-void write_prep_partition(int in, int out)
-{
-  unsigned char block[512];
-  partition_entry_t *pe = (partition_entry_t *)&block[0x1BE];
-  dword_t *entry  = (dword_t *)&block[0];
-  dword_t *length = (dword_t *)&block[sizeof(long)];
-  struct stat info;
-  
-  if (fstat(in, &info) < 0)
-  {
-    fprintf(stderr,"info failed\n");
-    exit(-1);
-  }
-  
-  bzero( block, sizeof block );
- 
-  /* set entry point and boot image size skipping over elf header */
-#ifdef __i386__
-  *entry = 0x400/*+65536*/;
-  *length = info.st_size-elfhdr_size+0x400;
-#else
-  *entry = cpu_to_le32(0x400/*+65536*/);
-  *length = cpu_to_le32(info.st_size-elfhdr_size+0x400);
-#endif /* __i386__ */
-
-  /* sets magic number for msdos partition (used by linux) */
-  block[510] = 0x55;
-  block[511] = 0xAA;
-  
-  /*
-   * Build a "PReP" partition table entry in the boot record
-   *  - "PReP" may only look at the system_indicator
-   */
-  pe->boot_indicator   = BootActive;
-  pe->system_indicator = SystemPrep;
-  /*
-   * The first block of the diskette is used by this "boot record" which
-   * actually contains the partition table. (The first block of the
-   * partition contains the boot image, but I digress...)  We'll set up
-   * one partition on the diskette and it shall contain the rest of the
-   * diskette.
-   */
-  pe->starting_head     = 0;	/* zero-based			     */
-  pe->starting_sector   = 2;	/* one-based			     */
-  pe->starting_cylinder = 0;	/* zero-based			     */
-  pe->ending_head       = 1;	/* assumes two heads		     */
-  pe->ending_sector     = 18;	/* assumes 18 sectors/track	     */
-  pe->ending_cylinder   = 79;	/* assumes 80 cylinders/diskette     */
-
-  /*
-   * The "PReP" software ignores the above fields and just looks at
-   * the next two.
-   *   - size of the diskette is (assumed to be)
-   *     (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
-   *   - unlike the above sector numbers, the beginning sector is zero-based!
-   */
-#if 0
-  pe->beginning_sector  = cpu_to_le32(1);
-#else
-  /* This has to be 0 on the PowerStack? */   
-#ifdef __i386__
-  pe->beginning_sector  = 0;
-#else
-  pe->beginning_sector  = cpu_to_le32(0);
-#endif /* __i386__ */
-#endif    
-
-#ifdef __i386__
-  pe->number_of_sectors = 2*18*80-1;
-#else
-  pe->number_of_sectors = cpu_to_le32(2*18*80-1);
-#endif /* __i386__ */
-
-  write( out, block, sizeof(block) );
-  write( out, entry, sizeof(*entry) );
-  write( out, length, sizeof(*length) );  
-  /* set file position to 2nd sector where image will be written */
-  lseek( out, 0x400, SEEK_SET );
-}
-
-
-
-void
-copy_image(int in, int out)
-{
-  char buf[SIZE];
-  int n;
-
-  while ( (n = read(in, buf, SIZE)) > 0 )
-    write(out, buf, n);
-}
-
-
-void
-write_asm_data( int in, int out )
-{
-  int i, cnt, pos, len;
-  unsigned int cksum, val;
-  unsigned char *lp;
-  unsigned char buf[SIZE];
-  unsigned char str[256];
-  
-  write( out, "\t.data\n\t.globl input_data\ninput_data:\n",
-	 strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) );
-  pos = 0;
-  cksum = 0;
-  while ((len = read(in, buf, sizeof(buf))) > 0)
-  {
-    cnt = 0;
-    lp = (unsigned char *)buf;
-    len = (len + 3) & ~3;  /* Round up to longwords */
-    for (i = 0;  i < len;  i += 4)
-    {
-      if (cnt == 0)
-      {
-	write( out, "\t.long\t", strlen( "\t.long\t" ) );
-      }
-      sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
-      write( out, str, strlen(str) );
-      val = *(unsigned long *)lp;
-      cksum ^= val;
-      lp += 4;
-      if (++cnt == 4)
-      {
-	cnt = 0;
-	sprintf( str, " # %x \n", pos+i-12);
-	write( out, str, strlen(str) );
-      } else
-      {
-	write( out, ",", 1 );
-      }
-    }
-    if (cnt)
-    {
-      write( out, "0\n", 2 );
-    }
-    pos += len;
-  }
-  sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
-  write( out, str, strlen(str) );
-
-  fprintf(stderr, "cksum = %x\n", cksum);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/ns16550.c linux/arch/ppc/boot/ns16550.c
--- v2.4.4/linux/arch/ppc/boot/ns16550.c	Thu Jan  7 12:06:57 1999
+++ linux/arch/ppc/boot/ns16550.c	Wed Dec 31 16:00:00 1969
@@ -1,56 +0,0 @@
-/*
- * COM1 NS16550 support
- */
-
-#include "ns16550.h"
-typedef struct NS16550 *NS16550_t;
-
-const NS16550_t COM_PORTS[] = { (NS16550_t) COM1,
-    (NS16550_t) COM2,
-    (NS16550_t) COM3,
-    (NS16550_t) COM4 };
-
-volatile struct NS16550 *
-NS16550_init(int chan)
-{
- volatile struct NS16550 *com_port;
- volatile unsigned char xx;
- com_port = (struct NS16550 *) COM_PORTS[chan];
- /* See if port is present */
- com_port->lcr = 0x00;
- com_port->ier = 0xFF;
-#if 0
- if (com_port->ier != 0x0F) return ((struct NS16550 *)0);
-#endif
- com_port->ier = 0x00;
- com_port->lcr = 0x80;  /* Access baud rate */
- com_port->dll = 0xc;  /* 9600 baud */
- com_port->dlm = 0xc >> 8;
- com_port->lcr = 0x03;  /* 8 data, 1 stop, no parity */
- com_port->mcr = 0x03;  /* RTS/DTR */
- com_port->fcr = 0x07;  /* Clear & enable FIFOs */
- return (com_port);
-}
-
-
-NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
-{
- volatile int i;
- while ((com_port->lsr & LSR_THRE) == 0) ;
- com_port->thr = c;
-}
-
-unsigned char
-NS16550_getc(volatile struct NS16550 *com_port)
-{
- while ((com_port->lsr & LSR_DR) == 0) ;
- return (com_port->rbr);
-}
-
-NS16550_tstc(volatile struct NS16550 *com_port)
-{
- return ((com_port->lsr & LSR_DR) != 0);
-}
-
-
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/ns16550.h linux/arch/ppc/boot/ns16550.h
--- v2.4.4/linux/arch/ppc/boot/ns16550.h	Thu Jan  7 12:06:57 1999
+++ linux/arch/ppc/boot/ns16550.h	Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-/*
- * NS16550 Serial Port
- */
-
-struct NS16550
- {
-  unsigned char rbr;  /* 0 */
-  unsigned char ier;  /* 1 */
-  unsigned char fcr;  /* 2 */
-  unsigned char lcr;  /* 3 */
-  unsigned char mcr;  /* 4 */
-  unsigned char lsr;  /* 5 */
-  unsigned char msr;  /* 6 */
-  unsigned char scr;  /* 7 */
- };
-
-#define thr rbr
-#define iir fcr
-#define dll rbr
-#define dlm ier
-
-#define LSR_DR   0x01  /* Data ready */
-#define LSR_OE   0x02  /* Overrun */
-#define LSR_PE   0x04  /* Parity error */
-#define LSR_FE   0x08  /* Framing error */
-#define LSR_BI   0x10  /* Break */
-#define LSR_THRE 0x20  /* Xmit holding register empty */
-#define LSR_TEMT 0x40  /* Xmitter empty */
-#define LSR_ERR  0x80  /* Error */
-
-#define COM1 0x800003F8
-#define COM2 0x800002F8
-#define COM3 0x800003F8
-#define COM4 0x80000388
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/of1275.c linux/arch/ppc/boot/of1275.c
--- v2.4.4/linux/arch/ppc/boot/of1275.c	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/boot/of1275.c	Wed Dec 31 16:00:00 1969
@@ -1,427 +0,0 @@
-/* Open Firmware Client Interface */
-
-
-#include "of1275.h"
-
-
-static int (*of_server)(void *) = (int(*)(void*))-1;
-
-void
-of_init(void *handler)
-{
-	of_server = (int(*)(void*))handler;
-}
-
-
-/* 6.3.2.1 Client interface */
-
-
-int
-of_test(const char *name, int *missing)
-{
-	int result;
-	static of_test_service s;
-	s.service = "test";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.name = name;
-	result = of_server(&s);
-	*missing = s.missing;
-	return result;
-}
-
-
-/* 6.3.2.2 Device tree */
-
-
-int
-of_peer(int phandle, int *sibling_phandle)
-{
-	int result;
-	static of_peer_service s;
-	s.service = "peer";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	result = of_server(&s);
-	*sibling_phandle = s.sibling_phandle;
-	return result;
-}
-
-int
-of_child(int phandle, int *child_phandle)
-{
-	int result;
-	static of_child_service s;
-	s.service = "child";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	result = of_server(&s);
-	*child_phandle = s.child_phandle;
-	return result;
-}
-
-int
-of_parent(int phandle, int *parent_phandle)
-{
-	int result;
-	static of_parent_service s;
-	s.service = "parent";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	result = of_server(&s);
-	*parent_phandle = s.parent_phandle;
-	return result;
-}
-
-int
-of_instance_to_package(int ihandle, int *phandle)
-{
-	int result;
-	static of_instance_to_package_service s;
-	s.service = "instance-to-package";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.ihandle = ihandle;
-	result = of_server(&s);
-	*phandle = s.phandle;
-	return result;
-}
-
-int
-of_getproplen(int phandle, const char *name, int *proplen)
-{
-	int result;
-	static of_getproplen_service s;
-	s.service = "getproplen";
-	s.n_args = 2;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	s.name = name;
-	result = of_server(&s);
-	*proplen = s.proplen;
-	return result;
-}
-
-int
-of_getprop(int phandle, const char *name, void *buf, int buflen, int *size)
-{
-	int result;
-	static of_getprop_service s;
-	s.service = "getprop";
-	s.n_args = 4;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	s.name = name;
-	s.buf = buf;
-	s.buflen = buflen;
-	result = of_server(&s);
-	*size = s.size;
-	return result;
-}
-
-int
-of_nextprop(int phandle, const char *previous, void *buf, int *flag)
-{
-	int result;
-	static of_nextprop_service s;
-	s.service = "nextprop";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	s.previous = previous;
-	s.buf = buf;
-	result = of_server(&s);
-	*flag = s.flag;
-	return result;
-}
-
-int
-of_setprop(int phandle, const char *name, void *buf, int len, int *size)
-{
-	int result;
-	static of_setprop_service s;
-	s.service = "setprop";
-	s.n_args = 4;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	s.name = name;
-	s.buf = buf;
-	s.len = len;
-	result = of_server(&s);
-	*size = s.size;
-	return result;
-}
-
-int
-of_canon(const char *device_specifier, void *buf, int buflen, int *length)
-{
-	int result;
-	static of_canon_service s;
-	s.service = "canon";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.device_specifier = device_specifier;
-	s.buf = buf;
-	s.buflen = buflen;
-	result = of_server(&s);
-	*length = s.length;
-	return result;
-}
-
-int
-of_finddevice(const char *device_specifier, int *phandle)
-{
-	int result;
-	static of_finddevice_service s;
-	s.service = "finddevice";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.device_specifier = device_specifier;
-	result = of_server(&s);
-	*phandle = s.phandle;
-	return result;
-}
-
-int
-of_instance_to_path(int ihandle, void *buf, int buflen, int *length)
-{
-	int result;
-	static of_instance_to_path_service s;
-	s.service = "instance-to-path";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.ihandle = ihandle;
-	s.buf = buf;
-	s.buflen = buflen;
-	result = of_server(&s);
-	*length = s.length;
-	return result;
-}
-
-int
-of_package_to_path(int phandle, void *buf, int buflen, int *length)
-{
-	int result;
-	static of_package_to_path_service s;
-	s.service = "package-to-path";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.phandle = phandle;
-	s.buf = buf;
-	s.buflen = buflen;
-	result = of_server(&s);
-	*length = s.length;
-	return result;
-}
-
-/* int of_call_method(const char *method, int ihandle, ...); */
-
-
-/* 6.3.2.3 Device I/O */
-
-
-int
-of_open(const char *device_specifier, int *ihandle)
-{
-	int result;
-	static of_open_service s;
-	s.service = "open";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.device_specifier = device_specifier;
-	result = of_server(&s);
-	*ihandle = s.ihandle;
-	return result;
-}
-
-int
-of_close(int ihandle)
-{
-	int result;
-	static of_close_service s;
-	s.service = "close";
-	s.n_args = 1;
-	s.n_returns = 0;
-	s.ihandle = ihandle;
-	result = of_server(&s);
-	return result;
-}
-
-int
-of_read(int ihandle, void *addr, int len, int *actual)
-{
-	int result;
-	static of_read_service s;
-	s.service = "read";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.ihandle = ihandle;
-	s.addr = addr;
-	s.len = len;
-	result = of_server(&s);
-	*actual = s.actual;
-	return result;
-}
-
-int
-of_write(int ihandle, void *addr, int len, int *actual)
-{
-	int result;
-	static of_write_service s;
-	s.service = "write";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.ihandle = ihandle;
-	s.addr = addr;
-	s.len = len;
-	result = of_server(&s);
-	*actual = s.actual;
-	return result;
-}
-
-int
-of_seek(int ihandle, int pos_hi, int pos_lo, int *status)
-{
-	int result;
-	static of_seek_service s;
-	s.service = "seek";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.ihandle = ihandle;
-	s.pos_hi = pos_hi;
-	s.pos_lo = pos_lo;
-	result = of_server(&s);
-	*status = s.status;
-	return result;
-}
-
-
-/* 6.3.2.4 Memory */
-
-
-int
-of_claim(void *virt, int size, int align, void **baseaddr)
-{
-	int result;
-	static of_claim_service s;
-	s.service = "claim";
-	s.n_args = 3;
-	s.n_returns = 1;
-	s.virt = virt;
-	s.size = size;
-	s.align = align;
-	result = of_server(&s);
-	*baseaddr = s.baseaddr;
-	return result;
-}
-
-int
-of_release(void *virt, int size)
-{
-	int result;
-	static of_release_service s;
-	s.service = "release";
-	s.n_args = 2;
-	s.n_returns = 0;
-	s.virt = virt;
-	s.size = size;
-	result = of_server(&s);
-	return result;
-}
-
-
-/* 6.3.2.5 Control transfer */
-
-
-int
-of_boot(const char *bootspec)
-{
-	int result;
-	static of_boot_service s;
-	s.service = "boot";
-	s.n_args = 1;
-	s.n_returns = 0;
-	s.bootspec = bootspec;
-	result = of_server(&s);
-	return result;
-}
-
-int
-of_enter(void)
-{
-	int result;
-	static of_enter_service s;
-	s.service = "enter";
-	s.n_args = 0;
-	s.n_returns = 0;
-	result = of_server(&s);
-	return result;
-}
-
-int
-of_exit(void)
-{
-	int result;
-	static of_exit_service s;
-	s.service = "exit";
-	s.n_args = 0;
-	s.n_returns = 0;
-	result = of_server(&s);
-	return result;
-}
-
-/* int of_chain(void *virt, int size, void *entry, void *args, int len); */
-
-
-/* 6.3.2.6 User interface */
-
-
-/* int of_interpret(const char *arg, ...); */
-
-int
-of_set_callback(void *newfunc, void **oldfunc)
-{
-	int result;
-	static of_set_callback_service s;
-	s.service = "set-callback";
-	s.n_args = 1;
-	s.n_returns = 1;
-	s.newfunc = newfunc;
-	result = of_server(&s);
-	*oldfunc = s.oldfunc;
-	return result;
-}
-
-int
-of_set_symbol_lookup(void *sym_to_value, void *value_to_sym)
-{
-	int result;
-	static of_set_symbol_lookup_service s;
-	s.service = "set-symbol-lookup";
-	s.n_args = 2;
-	s.n_returns = 0;
-	s.sym_to_value = sym_to_value;
-	s.value_to_sym = s.value_to_sym;
-	result = of_server(&s);
-	return result;
-}
-
-
-/* 6.3.2.7 Time */
-
-
-int
-of_milliseconds(int *ms)
-{
-	int result;
-	static of_milliseconds_service s;
-	s.service = "milliseconds";
-	s.n_args = 0;
-	s.n_returns = 1;
-	result = of_server(&s);
-	*ms = s.ms;
-	return result;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/of1275.h linux/arch/ppc/boot/of1275.h
--- v2.4.4/linux/arch/ppc/boot/of1275.h	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/boot/of1275.h	Wed Dec 31 16:00:00 1969
@@ -1,421 +0,0 @@
-/* 6.3.2.1 Client interface */
-
-
-typedef struct _of_test_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *name;
-	/*out*/
-	int missing;
-} of_test_service;
-
-int of_test(const char *name, int *missing);
-
-
-/* 6.3.2.2 Device tree */
-
-
-typedef struct _of_peer_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	/*out*/
-	int sibling_phandle;
-} of_peer_service;
-
-int of_peer(int phandle, int *sibling_phandle);
-
-
-typedef struct _of_child_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	/*out*/
-	int child_phandle;
-} of_child_service;
-
-int of_child(int phandle, int *child_phandle);
-
-
-typedef struct _of_parent_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	/*out*/
-	int parent_phandle;
-} of_parent_service;
-
-int of_child(int phandle, int *parent_phandle);
-
-
-typedef struct _of_instance_to_package_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int ihandle;
-	/*out*/
-	int phandle;
-} of_instance_to_package_service;
-
-int of_instance_to_package(int ihandle, int *phandle);
-
-
-typedef struct _of_getproplen_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	const char *name;
-	/*out*/
-	int proplen;
-} of_getproplen_service;
-
-int of_getproplen(int phandle, const char *name, int *proplen);
-
-
-typedef struct _of_getprop_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	const char *name;
-	void *buf;
-	int buflen;
-	/*out*/
-	int size;
-} of_getprop_service;
-
-int of_getprop(int phandle, const char *name, void *buf, int buflen,
-	       int *size);
-
-
-typedef struct _of_nextprop_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	const char *previous;
-	void *buf;
-	/*out*/
-	int flag;
-} of_nextprop_service;
-
-int of_nextprop(int phandle, const char *previous, void *buf, int *flag);
-
-
-typedef struct _of_setprop_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	const char *name;
-	void *buf;
-	int len;
-	/*out*/
-	int size;
-} of_setprop_service;
-
-int of_setprop(int phandle, const char *name, void *buf, int len, int *size);
-
-
-typedef struct _of_canon_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *device_specifier;
-	void *buf;
-	int buflen;
-	/*out*/
-	int length;
-} of_canon_service;
-
-int of_canon(const char *device_specifier, void *buf, int buflen, int *length);
-
-
-typedef struct _of_finddevice_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *device_specifier;
-	/*out*/
-	int phandle;
-} of_finddevice_service;
-
-int of_finddevice(const char *device_specifier, int *phandle);
-
-
-typedef struct _of_instance_to_path_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int ihandle;
-	void *buf;
-	int buflen;
-	/*out*/
-	int length;
-} of_instance_to_path_service;
-
-int of_instance_to_path(int ihandle, void *buf, int buflen, int *length);
-
-
-typedef struct _of_package_to_path_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int phandle;
-	void *buf;
-	int buflen;
-	/*out*/
-	int length;
-} of_package_to_path_service;
-
-int of_package_to_path(int phandle, void *buf, int buflen, int *length);
-
-
-typedef struct _of_call_method_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *method;
-	int ihandle;
-	/*...*/
-	int args[0]; 
-} of_call_method_service;
-
-int of_call_method(const char *method, int ihandle, ...);
-
-
-/* 6.3.2.3 Device I/O */
-
-
-typedef struct _of_open_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *device_specifier;
-	/*out*/
-	int ihandle;
-} of_open_service;
-
-int of_open(const char *device_specifier,
-	    int *ihandle);
-
-
-typedef struct _of_close_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int ihandle;
-	/*out*/
-} of_close_service;
-
-int of_close(int ihandle);
-
-
-typedef struct _of_read_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int ihandle;
-	void *addr;
-	int len;
-	/*out*/
-	int actual;
-} of_read_service;
-
-int of_read(int ihandle, void *addr, int len, int *actual);
-
-
-typedef struct _of_write_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int ihandle;
-	void *addr;
-	int len;
-	/*out*/
-	int actual;
-} of_write_service;
-
-int of_write(int ihandle, void *addr, int len, int *actual);
-
-
-typedef struct _of_seek_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	int ihandle;
-	int pos_hi;
-	int pos_lo;
-	/*out*/
-	int status;
-} of_seek_service;
-
-int of_seek(int ihandle, int pos_hi, int pos_lo, int *status);
-
-
-/* 6.3.2.4 Memory */
-
-
-typedef struct _of_claim_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	void *virt;
-	int size;
-	int align;
-	/*out*/
-	void *baseaddr;
-} of_claim_service;
-
-int of_claim(void *virt, int size, int align, void **baseaddr);
-
-
-typedef struct _of_release_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	void *virt;
-	int size;
-	int align;
-	/*out*/
-} of_release_service;
-
-int of_release(void *virt, int size);
-
-
-/* 6.3.2.5 Control transfer */
-
-
-typedef struct _of_boot_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *bootspec;
-	/*out*/
-} of_boot_service;
-
-int of_boot(const char *bootspec);
-
-
-typedef struct _of_enter_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	/*out*/
-} of_enter_service;
-
-int of_enter(void);
-
-
-typedef struct _of_exit_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	/*out*/
-} of_exit_service;
-
-int of_exit(void);
-
-
-typedef struct _of_chain_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	void *virt;
-	int size;
-	void *entry;
-	void *args;
-	int len;
-	/*out*/
-} of_chain_service;
-
-int of_chain(void *virt, int size, void *entry, void *args, int len);
-
-
-/* 6.3.2.6 User interface */
-
-
-typedef struct _of_interpret_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	const char *cmd;
-	int args[0];
-	/*...*/
-	/*out*/
-	/*...*/
-} of_interpret_service;
-
-int of_interpret(const char *arg, ...);
-
-
-typedef struct _of_set_callback_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	void *newfunc;
-	/*out*/
-	void *oldfunc;
-} of_set_callback_service;
-
-int of_set_callback(void *newfunc, void **oldfunc);
-
-
-typedef struct _of_set_symbol_lookup_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	void *sym_to_value;
-	void *value_to_sym;
-	/*out*/
-} of_set_symbol_lookup_service;
-
-int of_set_symbol_lookup(void *sym_to_value, void *value_to_sym);
-
-
-/* 6.3.2.7 Time */
-
-
-typedef struct _of_milliseconds_service {
-	const char *service;
-	int n_args;
-	int n_returns;
-	/*in*/
-	/*out*/
-	int ms;
-} of_milliseconds_service;
-
-int of_milliseconds(int *ms);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/offset linux/arch/ppc/boot/offset
--- v2.4.4/linux/arch/ppc/boot/offset	Wed Sep 30 10:14:16 1998
+++ linux/arch/ppc/boot/offset	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux| awk '{print $6}'`
-echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/Makefile linux/arch/ppc/boot/pmac/Makefile
--- v2.4.4/linux/arch/ppc/boot/pmac/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/Makefile	Thu May 24 15:02:07 2001
@@ -0,0 +1,115 @@
+# BK Id: SCCS/s.Makefile 1.8 05/21/01 09:10:38 trini
+#
+# Makefile for making XCOFF bootable images for booting on PowerMacs
+# using Open Firmware.
+#
+# Paul Mackerras	January 1997
+#
+# Cleaned up, moved into arch/ppc/boot/pmac
+# Tom Rini		January 2001
+ 
+OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
+COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic
+CHRP_LD_ARGS = -Ttext 0x01000000
+
+COMMONOBJS = start.o misc.o ../common/string.o image.o
+COFFOBJS = ../common/coffcrt0.o $(COMMONOBJS) coffmain.o
+CHRPOBJS = ../common/crt0.o $(COMMONOBJS) chrpmain.o
+LIBS = $(TOPDIR)/lib/lib.a ../lib/zlib.a
+
+MKNOTE := ../utils/mknote
+SIZE := ../utils/size
+OFFSET := ../utils/offset
+PIGGYBACK := ../utils/piggyback
+HACKCOFF := ../utils/hack-coff
+
+ifeq ($(CONFIG_PPC64BRIDGE),y)
+MSIZE=.64
+else
+MSIZE=
+endif
+
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE)
+else
+TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE)
+endif
+
+../common/crt0.o:
+	$(MAKE) -C ../common crt0.o
+
+../common/coffcrt0.o:
+	$(MAKE) -C ../common coffcrt0.o
+
+chrpmain.o: chrpmain.c
+	$(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c
+
+znetboot: vmlinux.coff vmlinux.elf-pmac zImage
+	cp ../images/vmlinux.coff $(TFTPIMAGE)
+	cp ../images/vmlinux.elf-pmac $(TFTPIMAGE).elf
+
+znetboot.initrd: vmlinux.coff.initrd vmlinux.initrd.elf-pmac
+	cp ../images/vmlinux.coff.initrd $(TFTPIMAGE)
+	cp ../images/vmlinux.elf-pmac.initrd $(TFTPIMAGE).elf
+
+#floppy: zImage
+#	mount -t hfs /dev/fd0 /mnt
+#	cp vmlinux.coff /mnt
+#	umount /mnt
+
+miboot.image: dummy.o ../images/vmlinux.gz
+	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=../images/vmlinux.gz \
+		dummy.o ../images/$@
+
+miboot.image.initrd: miboot.image ../images/ramdisk.image.gz
+	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=../images/ramdisk.image.gz \
+		../images/miboot.image ../images/$@
+
+coffboot: $(COFFOBJS) $(LIBS) ../common/no_initrd.o ld.script ../images/vmlinux.gz
+	$(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) ../common/no_initrd.o $(LIBS)
+
+coffboot.initrd: $(COFFOBJS) $(LIBS) initrd.o ld.script ../images/vmlinux.gz
+	$(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) initrd.o $(LIBS)
+
+image.o: $(PIGGYBACK) ../images/vmlinux.gz
+	$(PIGGYBACK) image < ../images/vmlinux.gz | $(AS) -o $@
+
+initrd.o: ../images/ramdisk.image.gz $(PIGGYBACK)
+	$(PIGGYBACK) initrd < ../images/ramdisk.image.gz | $(AS) -o $@
+
+vmlinux.coff: coffboot $(HACKCOFF)
+	$(OBJCOPY) $(OBJCOPY_ARGS) coffboot ../images/$@
+	$(HACKCOFF) ../images/$@
+	rm -f coffboot
+	ln -sf vmlinux.coff ../images/zImage.pmac
+
+vmlinux.coff.initrd: coffboot.initrd $(HACKCOFF)
+	$(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd ../images/$@
+	$(HACKCOFF) ../images/$@
+	rm -f coffboot.initrd
+	ln -sf vmlinux.coff.initrd ../images/zImage.initrd.pmac
+
+vmlinux.elf-pmac: $(CHRPOBJS) $(LIBS) ../common/no_initrd.o $(MKNOTE) ../images/vmlinux.gz
+	$(LD) $(CHRP_LD_ARGS) -o ../images/$@ $(CHRPOBJS) ../common/no_initrd.o $(LIBS)
+	$(MKNOTE) > note
+	$(OBJCOPY) ../images/$@ ../images/$@ --add-section=.note=note \
+		--add-section=sysmap=$(TOPDIR)/System.map -R .comment
+	$(CC) $(CFLAGS) chrpmain.c -c -o chrpmain.o \
+		-DSYSMAP_OFFSET=`sh $(OFFSET) $(OBJDUMP) ../images/$@ sysmap` \
+		-DSYSMAP_SIZE=`sh $(SIZE) $(OBJDUMP) ../images/$@ sysmap`
+	$(LD) $(CHRP_LD_ARGS) -o ../images/$@ $(CHRPOBJS) ../common/no_initrd.o $(LIBS)
+	$(OBJCOPY) ../images/$@ ../images/$@ --add-section=.note=note \
+		--add-section=sysmap=$(TOPDIR)/System.map -R .comment
+	rm -f note
+
+vmlinux.initrd.elf-pmac: $(CHRPOBJS) $(LIBS) initrd.o $(MKNOTE) ../images/vmlinux.gz
+	$(LD) $(CHRP_LD_ARGS) -o ../images/$@ $(CHRPOBJS) initrd.o $(LIBS)
+	$(MKNOTE) > note
+	$(OBJCOPY) ../images/$@ ../images/$@ --add-section=.note=note -R .comment
+	rm -f note
+
+zImage: vmlinux.coff vmlinux.elf-pmac miboot.image
+
+zImage.initrd: vmlinux.coff.initrd vmlinux.initrd.elf-pmac miboot.image.initrd
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/chrpmain.c linux/arch/ppc/boot/pmac/chrpmain.c
--- v2.4.4/linux/arch/ppc/boot/pmac/chrpmain.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/chrpmain.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,312 @@
+/*
+ * BK Id: SCCS/s.chrpmain.c 1.9 05/18/01 06:20:29 patch
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 "nonstdio.h"
+#include "zlib.h"
+#include <asm/bootinfo.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+extern void *finddevice(const char *);
+extern int getprop(void *, const char *, void *, int);
+extern void *claim(unsigned int, unsigned int, unsigned int);
+extern void release(void *ptr, unsigned int len);
+void make_bi_recs(unsigned long);
+void gunzip(void *, int, unsigned char *, int *);
+void stop_imac_ethernet(void);
+void stop_imac_usb(void);
+
+#define get_16be(x)	(*(unsigned short *)(x))
+#define get_32be(x)	(*(unsigned *)(x))
+
+#define RAM_END		(16 << 20)
+
+#define PROG_START	0x00010000
+#define PROG_SIZE	0x003f0000
+
+#define SCRATCH_SIZE	(128 << 10)
+
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE ""
+#endif
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+unsigned int heap_use;
+unsigned int heap_max;
+
+extern char _end[];
+extern char image_data[];
+extern int image_len;
+extern char initrd_data[];
+extern int initrd_len;
+
+
+boot(int a1, int a2, void *prom)
+{
+    int ns, oh, i;
+    unsigned sa, len;
+    void *dst;
+    unsigned char *im;
+    unsigned initrd_start, initrd_size;
+    extern char _start;
+    
+    printf("chrpboot starting: loaded at 0x%x\n", &_start);
+    if (initrd_len) {
+	initrd_size = initrd_len;
+	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+	a1 = initrd_start;
+	a2 = initrd_size;
+	claim(initrd_start, RAM_END - initrd_start, 0);
+	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n", initrd_start,
+	       initrd_data,initrd_size);
+	memcpy((char *)initrd_start, initrd_data, initrd_size);
+    }
+    im = image_data;
+    len = image_len;
+    /* claim 3MB starting at PROG_START */
+    claim(PROG_START, PROG_SIZE, 0);
+    dst = (void *) PROG_START;
+    if (im[0] == 0x1f && im[1] == 0x8b) {
+	/* claim some memory for scratch space */
+	avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
+	begin_avail = avail_high = avail_ram;
+	end_avail = avail_ram + SCRATCH_SIZE;
+	printf("heap at 0x%x\n", avail_ram);
+	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
+	gunzip(dst, PROG_SIZE, im, &len);
+	printf("done %u bytes\n", len);
+	printf("%u bytes of heap consumed, max in use %u\n",
+	       avail_high - begin_avail, heap_max);
+	release(begin_avail, SCRATCH_SIZE);
+    } else {
+	memmove(dst, im, len);
+    }
+
+    flush_cache(dst, len);
+    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+    make_bi_recs((unsigned long) dst + len);
+
+    sa = (unsigned long)PROG_START;
+    printf("start address = 0x%x\n", sa);
+
+    (*(void (*)())sa)(a1, a2, prom);
+
+    printf("returned?\n");
+
+    pause();
+}
+
+void make_bi_recs(unsigned long addr)
+{
+	struct bi_record *rec;
+
+	/* leave a 1MB gap then align to the next 1MB boundary */
+	addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
+	if (addr >= PROG_START + PROG_SIZE)
+		claim(addr, 0x1000, 0);
+
+	rec = (struct bi_record *)addr;
+	rec->tag = BI_FIRST;
+	rec->size = sizeof(struct bi_record);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+	rec->tag = BI_BOOTLOADER_ID;
+	sprintf( (char *)rec->data, "coffboot");
+	rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1;
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	    
+	rec->tag = BI_MACHTYPE;
+	rec->data[0] = _MACH_Pmac;
+	rec->data[1] = 1;
+	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+	rec->tag = BI_CMD_LINE;
+	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
+	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+#ifdef SYSMAP_OFFSET
+	rec->tag = BI_SYSMAP;
+	rec->data[0] = SYSMAP_OFFSET;
+	rec->data[1] = SYSMAP_SIZE;
+	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+#endif /* SYSMAP_OFFSET */
+	
+	rec->tag = BI_LAST;
+	rec->size = sizeof(struct bi_record);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+}
+
+#if 0
+#define eieio()	asm volatile("eieio");
+
+void stop_imac_ethernet(void)
+{
+    void *macio, *enet;
+    unsigned int macio_addr[5], enet_reg[6];
+    int len;
+    volatile unsigned int *dbdma;
+
+    macio = finddevice("/pci/mac-io");
+    enet = finddevice("/pci/mac-io/ethernet");
+    if (macio == NULL || enet == NULL)
+	return;
+    len = getprop(macio, "assigned-addresses", macio_addr, sizeof(macio_addr));
+    if (len != sizeof(macio_addr))
+	return;
+    len = getprop(enet, "reg", enet_reg, sizeof(enet_reg));
+    if (len != sizeof(enet_reg))
+	return;
+    printf("macio base %x, dma at %x & %x\n",
+	   macio_addr[2], enet_reg[2], enet_reg[4]);
+
+    /* hope this is mapped... */
+    dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[2]);
+    *dbdma = 0x80;	/* clear the RUN bit */
+    eieio();
+    dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[4]);
+    *dbdma = 0x80;	/* clear the RUN bit */
+    eieio();
+}
+
+void stop_imac_usb(void)
+{
+    void *usb;
+    unsigned int usb_addr[5];
+    int len;
+    volatile unsigned int *usb_ctrl;
+
+    usb = finddevice("/pci/usb");
+    if (usb == NULL)
+	return;
+    len = getprop(usb, "assigned-addresses", usb_addr, sizeof(usb_addr));
+    if (len != sizeof(usb_addr))
+	return;
+    printf("usb base %x\n", usb_addr[2]);
+
+    usb_ctrl = (volatile unsigned int *) (usb_addr[2] + 8);
+    *usb_ctrl = 0x01000000;	/* cpu_to_le32(1) */
+    eieio();
+}
+#endif
+
+struct memchunk {
+    unsigned int size;
+    struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+    void *p;
+    struct memchunk **mpp, *mp;
+
+    size *= items;
+    size = (size + 7) & -8;
+    heap_use += size;
+    if (heap_use > heap_max)
+	heap_max = heap_use;
+    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+	if (mp->size == size) {
+	    *mpp = mp->next;
+	    return mp;
+	}
+    }
+    p = avail_ram;
+    avail_ram += size;
+    if (avail_ram > avail_high)
+	avail_high = avail_ram;
+    if (avail_ram > end_avail) {
+	printf("oops... out of memory\n");
+	pause();
+    }
+    return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+    struct memchunk *mp = addr;
+
+    nb = (nb + 7) & -8;
+    heap_use -= nb;
+    if (avail_ram == addr + nb) {
+	avail_ram = addr;
+	return;
+    }
+    mp->size = nb;
+    mp->next = freechunks;
+    freechunks = mp;
+}
+
+#define HEAD_CRC	2
+#define EXTRA_FIELD	4
+#define ORIG_NAME	8
+#define COMMENT		0x10
+#define RESERVED	0xe0
+
+#define DEFLATED	8
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+    z_stream s;
+    int r, i, flags;
+
+    /* skip header */
+    i = 10;
+    flags = src[3];
+    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+	printf("bad gzipped data\n");
+	exit();
+    }
+    if ((flags & EXTRA_FIELD) != 0)
+	i = 12 + src[10] + (src[11] << 8);
+    if ((flags & ORIG_NAME) != 0)
+	while (src[i++] != 0)
+	    ;
+    if ((flags & COMMENT) != 0)
+	while (src[i++] != 0)
+	    ;
+    if ((flags & HEAD_CRC) != 0)
+	i += 2;
+    if (i >= *lenp) {
+	printf("gunzip: ran out of data in header\n");
+	exit();
+    }
+
+    s.zalloc = zalloc;
+    s.zfree = zfree;
+    r = inflateInit2(&s, -MAX_WBITS);
+    if (r != Z_OK) {
+	printf("inflateInit2 returned %d\n", r);
+	exit();
+    }
+    s.next_in = src + i;
+    s.avail_in = *lenp - i;
+    s.next_out = dst;
+    s.avail_out = dstlen;
+    r = inflate(&s, Z_FINISH);
+    if (r != Z_OK && r != Z_STREAM_END) {
+	printf("inflate returned %d msg: %s\n", r, s.msg);
+	exit();
+    }
+    *lenp = s.next_out - (unsigned char *) dst;
+    inflateEnd(&s);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/coffmain.c linux/arch/ppc/boot/pmac/coffmain.c
--- v2.4.4/linux/arch/ppc/boot/pmac/coffmain.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/coffmain.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,249 @@
+/*
+ * BK Id: SCCS/s.coffmain.c 1.9 05/18/01 06:20:29 patch
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 "nonstdio.h"
+#include "zlib.h"
+#include <asm/bootinfo.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+extern void *finddevice(const char *);
+extern int getprop(void *, const char *, void *, int);
+extern char *claim(unsigned, unsigned, unsigned);
+void make_bi_recs(unsigned long);
+void gunzip(void *, int, unsigned char *, int *);
+
+#define get_16be(x)	(*(unsigned short *)(x))
+#define get_32be(x)	(*(unsigned *)(x))
+
+#define RAM_START	0xc0000000
+#define RAM_END		(RAM_START + 0x800000)	/* only 8M mapped with BATs */
+
+#define PROG_START	RAM_START
+#define PROG_SIZE	0x00400000
+
+#define SCRATCH_SIZE	(128 << 10)
+
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE ""
+#endif
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+char *avail_ram;
+char *begin_avail, *end_avail;
+char *avail_high;
+unsigned int heap_use;
+unsigned int heap_max;
+
+extern char _start[], _end[];
+extern char image_data[];
+extern int image_len;
+extern char initrd_data[];
+extern int initrd_len;
+
+char heap[SCRATCH_SIZE];
+
+boot(int a1, int a2, void *prom)
+{
+    int ns, oh, i;
+    unsigned sa, len;
+    void *dst;
+    unsigned char *im;
+    unsigned initrd_start, initrd_size;
+    
+    printf("coffboot starting: loaded at 0x%x\n", _start);
+    setup_bats(RAM_START);
+    if (initrd_len) {
+	initrd_size = initrd_len;
+	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+	a1 = initrd_start;
+	a2 = initrd_size;
+	claim(initrd_start - RAM_START, RAM_END - initrd_start, 0);
+	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n",
+	       initrd_start, initrd_data, initrd_size);
+	memcpy((char *)initrd_start, initrd_data, initrd_size);
+    }
+    im = image_data;
+    len = image_len;
+    /* claim 3MB starting at 0 */
+    claim(0, PROG_SIZE, 0);
+    dst = (void *) RAM_START;
+    if (im[0] == 0x1f && im[1] == 0x8b) {
+	/* claim some memory for scratch space */
+	begin_avail = avail_high = avail_ram = heap;
+	end_avail = heap + sizeof(heap);
+	printf("heap at 0x%x\n", avail_ram);
+	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
+	gunzip(dst, PROG_SIZE, im, &len);
+	printf("done %u bytes\n", len);
+	printf("%u bytes of heap consumed, max in use %u\n",
+	       avail_high - begin_avail, heap_max);
+    } else {
+	memmove(dst, im, len);
+    }
+
+    flush_cache(dst, len);
+    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+    make_bi_recs((unsigned long)dst + len);
+    
+    sa = (unsigned long)PROG_START;
+    printf("start address = 0x%x\n", sa);
+
+    (*(void (*)())sa)(a1, a2, prom);
+
+    printf("returned?\n");
+
+    pause();
+}
+
+void make_bi_recs(unsigned long addr)
+{
+	struct bi_record *rec;
+
+	addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
+#if 0
+	if (addr >= PROG_START + PROG_SIZE)
+		claim(addr, 0x1000, 0);
+#endif
+
+	rec = (struct bi_record *)addr;
+	rec->tag = BI_FIRST;
+	rec->size = sizeof(struct bi_record);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+	rec->tag = BI_BOOTLOADER_ID;
+	sprintf( (char *)rec->data, "coffboot");
+	rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1;
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	    
+	rec->tag = BI_MACHTYPE;
+	rec->data[0] = _MACH_Pmac;
+	rec->data[1] = 1;
+	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+    
+	rec->tag = BI_CMD_LINE;
+	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
+	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+    
+	rec->tag = BI_LAST;
+	rec->size = sizeof(struct bi_record);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+}
+
+struct memchunk {
+    unsigned int size;
+    struct memchunk *next;
+};
+
+static struct memchunk *freechunks;
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+    void *p;
+    struct memchunk **mpp, *mp;
+
+    size *= items;
+    size = (size + 7) & -8;
+    heap_use += size;
+    if (heap_use > heap_max)
+	heap_max = heap_use;
+    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
+	if (mp->size == size) {
+	    *mpp = mp->next;
+	    return mp;
+	}
+    }
+    p = avail_ram;
+    avail_ram += size;
+    if (avail_ram > avail_high)
+	avail_high = avail_ram;
+    if (avail_ram > end_avail) {
+	printf("oops... out of memory\n");
+	pause();
+    }
+    return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+    struct memchunk *mp = addr;
+
+    nb = (nb + 7) & -8;
+    heap_use -= nb;
+    if (avail_ram == addr + nb) {
+	avail_ram = addr;
+	return;
+    }
+    mp->size = nb;
+    mp->next = freechunks;
+    freechunks = mp;
+}
+
+#define HEAD_CRC	2
+#define EXTRA_FIELD	4
+#define ORIG_NAME	8
+#define COMMENT		0x10
+#define RESERVED	0xe0
+
+#define DEFLATED	8
+
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+    z_stream s;
+    int r, i, flags;
+
+    /* skip header */
+    i = 10;
+    flags = src[3];
+    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+	printf("bad gzipped data\n");
+	exit();
+    }
+    if ((flags & EXTRA_FIELD) != 0)
+	i = 12 + src[10] + (src[11] << 8);
+    if ((flags & ORIG_NAME) != 0)
+	while (src[i++] != 0)
+	    ;
+    if ((flags & COMMENT) != 0)
+	while (src[i++] != 0)
+	    ;
+    if ((flags & HEAD_CRC) != 0)
+	i += 2;
+    if (i >= *lenp) {
+	printf("gunzip: ran out of data in header\n");
+	exit();
+    }
+
+    s.zalloc = zalloc;
+    s.zfree = zfree;
+    r = inflateInit2(&s, -MAX_WBITS);
+    if (r != Z_OK) {
+	printf("inflateInit2 returned %d\n", r);
+	exit();
+    }
+    s.next_in = src + i;
+    s.avail_in = *lenp - i;
+    s.next_out = dst;
+    s.avail_out = dstlen;
+    r = inflate(&s, Z_FINISH);
+    if (r != Z_OK && r != Z_STREAM_END) {
+	printf("inflate returned %d msg: %s\n", r, s.msg);
+	exit();
+    }
+    *lenp = s.next_out - (unsigned char *) dst;
+    inflateEnd(&s);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/dummy.c linux/arch/ppc/boot/pmac/dummy.c
--- v2.4.4/linux/arch/ppc/boot/pmac/dummy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/dummy.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,7 @@
+/*
+ * BK Id: SCCS/s.dummy.c 1.6 05/18/01 15:17:15 cort
+ */
+int main(void)
+{
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/ld.script linux/arch/ppc/boot/pmac/ld.script
--- v2.4.4/linux/arch/ppc/boot/pmac/ld.script	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/ld.script	Thu May 24 15:02:07 2001
@@ -0,0 +1,68 @@
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	} =0
+  .plt : { *(.plt) }
+  .text      :
+  {
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    *(.got1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+  _etext = .;
+  PROVIDE (etext = .);
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.got.plt) *(.got)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/misc.S linux/arch/ppc/boot/pmac/misc.S
--- v2.4.4/linux/arch/ppc/boot/pmac/misc.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/misc.S	Thu May 24 15:02:07 2001
@@ -0,0 +1,60 @@
+/*
+ * BK Id: SCCS/s.misc.S 1.6 05/18/01 15:17:15 cort
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+	.text
+
+/*
+ * Use the BAT3 registers to map the 1st 8MB of RAM to
+ * the address given as the 1st argument.
+ */
+	.globl	setup_bats
+setup_bats:
+	mfpvr	5
+	rlwinm	5,5,16,16,31		/* r3 = 1 for 601, 4 for 604 */
+	cmpi	0,5,1
+	li	0,0
+	bne	4f
+	mtibatl	3,0			/* invalidate BAT first */
+	ori	3,3,4			/* set up BAT registers for 601 */
+	li	4,0x7f
+	mtibatu	3,3
+	mtibatl	3,4
+	b	5f
+4:	mtdbatu	3,0			/* invalidate BATs first */
+	mtibatu	3,0
+	ori	3,3,0xff		/* set up BAT registers for 604 */
+	li	4,2
+	mtdbatl	3,4
+	mtdbatu	3,3
+	mtibatl	3,4
+	mtibatu	3,3
+5:	sync
+	isync
+	blr
+
+/*
+ * Flush the dcache and invalidate the icache for a range of addresses.
+ *
+ * flush_cache(addr, len)
+ */
+	.global	flush_cache
+flush_cache:
+	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
+	rlwinm.	4,4,27,5,31
+	mtctr	4
+	beqlr
+1:	dcbf	0,3
+	icbi	0,3
+	addi	3,3,0x20
+	bdnz	1b
+	sync
+	isync
+	blr
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/pmac/start.c linux/arch/ppc/boot/pmac/start.c
--- v2.4.4/linux/arch/ppc/boot/pmac/start.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/pmac/start.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,343 @@
+/*
+ * BK Id: SCCS/s.start.c 1.8 05/18/01 15:17:15 cort
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stdarg.h>
+
+int (*prom)();
+
+void *chosen_handle;
+void *stdin;
+void *stdout;
+void *stderr;
+
+void exit(void);
+void *finddevice(const char *name);
+int getprop(void *phandle, const char *name, void *buf, int buflen);
+void printk(char *fmt, ...);
+
+void
+start(int a1, int a2, void *promptr)
+{
+    prom = (int (*)()) promptr;
+    chosen_handle = finddevice("/chosen");
+    if (chosen_handle == (void *) -1)
+	exit();
+    if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
+	exit();
+    stderr = stdout;
+    if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
+	exit();
+
+    boot(a1, a2, promptr);
+    for (;;)
+	exit();
+}
+
+int
+write(void *handle, void *ptr, int nb)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *ihandle;
+	void *addr;
+	int len;
+	int actual;
+    } args;
+
+    args.service = "write";
+    args.nargs = 3;
+    args.nret = 1;
+    args.ihandle = handle;
+    args.addr = ptr;
+    args.len = nb;
+    args.actual = -1;
+    (*prom)(&args);
+    return args.actual;
+}
+
+int writestring(void *f, char *ptr, int nb)
+{
+	int w = 0, i;
+	char *ret = "\r";
+
+	for (i = 0; i < nb; ++i) {
+		if (ptr[i] == '\n') {
+			if (i > w) {
+				write(f, ptr + w, i - w);
+				w = i;
+			}
+			write(f, ret, 1);
+		}
+	}
+	if (w < nb)
+		write(f, ptr + w, nb - w);
+	return nb;
+}
+
+int
+read(void *handle, void *ptr, int nb)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *ihandle;
+	void *addr;
+	int len;
+	int actual;
+    } args;
+
+    args.service = "read";
+    args.nargs = 3;
+    args.nret = 1;
+    args.ihandle = handle;
+    args.addr = ptr;
+    args.len = nb;
+    args.actual = -1;
+    (*prom)(&args);
+    return args.actual;
+}
+
+void
+exit()
+{
+    struct prom_args {
+	char *service;
+    } args;
+
+    for (;;) {
+	args.service = "exit";
+	(*prom)(&args);
+    }
+}
+
+void
+pause()
+{
+    struct prom_args {
+	char *service;
+    } args;
+
+    args.service = "enter";
+    (*prom)(&args);
+}
+
+void *
+finddevice(const char *name)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	const char *devspec;
+	void *phandle;
+    } args;
+
+    args.service = "finddevice";
+    args.nargs = 1;
+    args.nret = 1;
+    args.devspec = name;
+    args.phandle = (void *) -1;
+    (*prom)(&args);
+    return args.phandle;
+}
+
+void *
+claim(unsigned int virt, unsigned int size, unsigned int align)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	unsigned int virt;
+	unsigned int size;
+	unsigned int align;
+	void *ret;
+    } args;
+
+    args.service = "claim";
+    args.nargs = 3;
+    args.nret = 1;
+    args.virt = virt;
+    args.size = size;
+    args.align = align;
+    (*prom)(&args);
+    return args.ret;
+}
+
+void
+release(void *virt, unsigned int size)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *virt;
+	unsigned int size;
+    } args;
+
+    args.service = "release";
+    args.nargs = 2;
+    args.nret = 0;
+    args.virt = virt;
+    args.size = size;
+    (*prom)(&args);
+}
+
+int
+getprop(void *phandle, const char *name, void *buf, int buflen)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *phandle;
+	const char *name;
+	void *buf;
+	int buflen;
+	int size;
+    } args;
+
+    args.service = "getprop";
+    args.nargs = 4;
+    args.nret = 1;
+    args.phandle = phandle;
+    args.name = name;
+    args.buf = buf;
+    args.buflen = buflen;
+    args.size = -1;
+    (*prom)(&args);
+    return args.size;
+}
+
+int
+putc(int c, void *f)
+{
+    char ch = c;
+
+    return writestring(f, &ch, 1) == 1? c: -1;
+}
+
+int
+putchar(int c)
+{
+    return putc(c, stdout);
+}
+
+int
+fputs(char *str, void *f)
+{
+    int n = strlen(str);
+
+    return writestring(f, str, n) == n? 0: -1;
+}
+
+int
+readchar()
+{
+    char ch;
+
+    for (;;) {
+	switch (read(stdin, &ch, 1)) {
+	case 1:
+	    return ch;
+	case -1:
+	    printk("read(stdin) returned -1\n");
+	    return -1;
+	}
+    }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+int
+getchar()
+{
+    int c;
+
+    if (lineleft == 0) {
+	lineptr = line;
+	for (;;) {
+	    c = readchar();
+	    if (c == -1 || c == 4)
+		break;
+	    if (c == '\r' || c == '\n') {
+		*lineptr++ = '\n';
+		putchar('\n');
+		break;
+	    }
+	    switch (c) {
+	    case 0177:
+	    case '\b':
+		if (lineptr > line) {
+		    putchar('\b');
+		    putchar(' ');
+		    putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    case 'U' & 0x1F:
+		while (lineptr > line) {
+		    putchar('\b');
+		    putchar(' ');
+		    putchar('\b');
+		    --lineptr;
+		}
+		break;
+	    default:
+		if (lineptr >= &line[sizeof(line) - 1])
+		    putchar('\a');
+		else {
+		    putchar(c);
+		    *lineptr++ = c;
+		}
+	    }
+	}
+	lineleft = lineptr - line;
+	lineptr = line;
+    }
+    if (lineleft == 0)
+	return -1;
+    --lineleft;
+    return *lineptr++;
+}
+
+extern int vsprintf(char *buf, const char *fmt, va_list args);
+static char sprint_buf[1024];
+
+void
+printk(char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_buf, fmt, args);
+	va_end(args);
+	writestring(stdout, sprint_buf, n);
+}
+
+int
+printf(char *fmt, ...)
+{
+	va_list args;
+	int n;
+
+	va_start(args, fmt);
+	n = vsprintf(sprint_buf, fmt, args);
+	va_end(args);
+	writestring(stdout, sprint_buf, n);
+	return n;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/Makefile linux/arch/ppc/boot/prep/Makefile
--- v2.4.4/linux/arch/ppc/boot/prep/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/Makefile	Thu May 24 15:02:07 2001
@@ -0,0 +1,114 @@
+# BK Id: SCCS/s.Makefile 1.15 05/21/01 11:51:32 trini
+#
+# arch/ppc/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Tom Rini	January 2001
+#
+# Originally:
+# arch/ppc/boot/Makefile
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
+#
+
+.c.s:
+	$(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+	$(AS) -o $*.o $<
+.c.o:
+	$(CC) $(CFLAGS) -c -o $*.o $<
+.S.s:
+	$(CPP) $(AFLAGS) -traditional -o $*.o $<
+.S.o:
+	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
+
+ifeq ($(CONFIG_SMP),y)
+TFTPIMAGE=/tftpboot/zImage.prep.smp
+else
+TFTPIMAGE=/tftpboot/zImage.prep
+endif
+
+ZLINKFLAGS = -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00800000
+OBJECTS := head.o misc.o vreset.o kbd.o ../common/misc-common.o \
+		../common/string.o of1275.o
+OBJCOPY_ARGS = -O elf32-powerpc
+LIBS = ../lib/zlib.a
+
+ifeq ($(CONFIG_SERIAL_CONSOLE),y)
+OBJECTS += ns16550.o
+endif
+
+# Tools
+MKPREP := ../utils/mkprep
+SIZE := ../utils/size
+OFFSET := ../utils/offset
+
+all:	zImage
+
+misc.o: misc.c
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \
+		-DZIMAGE_SIZE=0 -c -o $@ $*.c
+
+ns16550.o: ../common/ns16550.c
+	$(CC) $(CFLAGS) -DIOOFFSET=0x80000000 -c -o $@ ../common/$*.c
+
+zvmlinux.initrd: zvmlinux ../images/vmlinux.gz
+	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=initrd=../images/ramdisk.image.gz \
+		--add-section=image=../images/vmlinux.gz \
+		$@.tmp $@
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ initrd` \
+		-DINITRD_SIZE=`sh $(SIZE) $(OBJDUMP) $@ initrd` \
+		-DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) $@ image` \
+		-DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) $@ image` \
+		-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=initrd=../images/ramdisk.image.gz \
+		--add-section=image=../images/vmlinux.gz \
+		$@.tmp $@
+	rm -f $@.tmp zvmlinux
+
+zImage: zvmlinux $(MKPREP)
+	$(MKPREP) -pbp zvmlinux ../images/$@.prep
+	rm -f zvmlinux
+
+zImage.initrd: zvmlinux.initrd $(MKPREP)
+	$(MKPREP) -pbp zvmlinux.initrd ../images/$@.prep
+	rm -f zvmlinux.initrd
+
+zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz
+#
+# build the boot loader image and then compute the offset into it
+# for the kernel image
+#
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=image=../images/vmlinux.gz zvmlinux.tmp $@
+#
+# then with the offset rebuild the bootloader so we know where the kernel is
+#
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
+		-DZIMAGE_OFFSET=`sh $(OFFSET) $(OBJDUMP) zvmlinux image` \
+		-DZIMAGE_SIZE=`sh $(SIZE) $(OBJDUMP) zvmlinux image` \
+		-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) $(LIBS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=image=../images/vmlinux.gz $@.tmp $@
+	rm $@.tmp
+
+floppy: zImage
+	dd if=../images/zImage.prep of=/dev/fd0H1440 bs=64b
+
+znetboot : zImage
+	cp ../images/zImage.prep $(TFTPIMAGE)
+
+znetboot.initrd : zImage.initrd
+	cp ../images/zImage.initrd.prep $(TFTPIMAGE)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/head.S linux/arch/ppc/boot/prep/head.S
--- v2.4.4/linux/arch/ppc/boot/prep/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/head.S	Thu May 24 15:02:07 2001
@@ -0,0 +1,248 @@
+/*
+ * BK Id: SCCS/s.head.S 1.8 05/18/01 06:20:29 patch
+ */
+#include "../../kernel/ppc_defs.h"
+#include "../../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+	.text
+
+/*
+ * Boot loader philosophy:
+ *      ROM loads us to some arbitrary location
+ *      Move the boot code to the link address (8M)
+ *      Call decompress_kernel()
+ *         Relocate the initrd, zimage and residual data to 8M
+ *         Decompress the kernel to 0
+ *      Jump to the kernel entry
+ *            -- Cort
+ */
+	.globl	start
+start:
+	bl	start_
+start_:
+	mr	r11,r3		/* Save pointer to residual/board data */
+	mr      r25,r5          /* Save OFW pointer */
+	li	r3,MSR_IP	/* Establish default MSR value */
+	mtmsr	r3
+
+/* check if we need to relocate ourselves to the link addr or were we
+   loaded there to begin with -- Cort */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	mflr	r3
+	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
+	mr	r8,r3
+	cmp	0,r3,r4
+	bne	1010f
+/* compute size of whole image in words.  this should be moved to
+ * start_ldr() -- Cort
+ */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	lis	r5,end@h
+	ori	r5,r5,end@l
+	addi	r5,r5,3		/* round up */
+	sub	r5,r5,r4
+	srwi	r5,r5,2
+	mr	r7,r5
+	b	start_ldr
+1010:
+/* 
+ * no matter where we're loaded, move ourselves to -Ttext address
+ */
+relocate:
+	mflr	r3		/* Compute code bias */
+	subi	r3,r3,4
+	mr	r8,r3
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	lis	r5,end@h
+	ori	r5,r5,end@l
+	addi	r5,r5,3			/* Round up - just in case */
+	sub	r5,r5,r4		/* Compute # longwords to move */
+	srwi	r5,r5,2
+	mtctr	r5
+	mr	r7,r5
+	li	r6,0
+	subi	r3,r3,4			/* Set up for loop */
+	subi	r4,r4,4
+00:	lwzu	r5,4(r3)
+	stwu	r5,4(r4)
+	xor	r6,r6,r5
+	bdnz	00b
+  	lis	r3,start_ldr@h
+	ori	r3,r3,start_ldr@l
+	mtlr	r3			/* Easiest way to do an absolute jump */
+	blr
+start_ldr:
+/* Clear all of BSS */
+	lis	r3,edata@h
+	ori	r3,r3,edata@l
+	lis	r4,end@h
+	ori	r4,r4,end@l
+	subi	r3,r3,4
+	subi	r4,r4,4
+	li	r0,0
+50:	stwu	r0,4(r3)
+	cmp	0,r3,r4
+	bne	50b
+90:	mr	r9,r1			/* Save old stack pointer (in case it matters) */
+	lis	r1,.stack@h
+	ori	r1,r1,.stack@l
+	addi	r1,r1,4096*2
+	subi	r1,r1,256
+	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
+	andc	r1,r1,r2
+/* Run loader */
+	mr	r3,r8			/* Load point */
+	mr	r4,r7			/* Program length */
+	mr	r5,r6			/* Checksum */
+	mr	r6,r11			/* Residual data */
+	mr      r7,r25                  /* OFW interfaces */
+	bl	decompress_kernel
+	
+	/* changed to use r3 (as firmware does) for kernel
+	   as ptr to residual -- Cort*/
+	lis	r6,cmd_line@h
+	ori	r6,r6,cmd_line@l
+	lwz	r6, 0(r6)
+	subi	r7,r6,1
+00:	lbzu	r2,1(r7)
+	cmpi	0,r2,0
+	bne	00b
+
+	/* r4,r5 have initrd_start, size */
+	lis	r2,initrd_start@h
+	ori	r2,r2,initrd_start@l
+	lwz	r4,0(r2)
+	lis	r2,initrd_end@h
+	ori	r2,r2,initrd_end@l
+	lwz	r5,0(r2)
+
+
+	/* tell kernel we're prep */
+	/* 
+	 * get start address of kernel code which is stored as a coff
+	 * entry.  see boot/head.S -- Cort 
+	 */
+	li	r9,0x4
+	mtlr	r9
+	lis	r10,0xdeadc0de@h
+	ori	r10,r10,0xdeadc0de@l
+	li	r9,0
+	stw	r10,0(r9)
+/*
+ * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
+ * so disable BATs before setting this to avoid a clash
+ */
+	li      r8,0
+	mtspr   DBAT0U,r8
+	mtspr   DBAT1U,r8
+	mtspr   DBAT2U,r8
+	mtspr   DBAT3U,r8
+	mtspr   IBAT0U,r8
+	mtspr   IBAT1U,r8
+	mtspr   IBAT2U,r8
+	mtspr   IBAT3U,r8
+
+	blr
+hang:
+	b	hang	
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+	.globl	udelay
+udelay:		
+	mfspr	r4,PVR
+	srwi	r4,r4,16
+	cmpi	0,r4,1		/* 601 ? */
+	bne	.udelay_not_601
+00:	li	r0,86	/* Instructions / microsecond? */
+	mtctr	r0
+10:	addi	r0,r0,0 /* NOP */
+	bdnz	10b
+	subic.	r3,r3,1
+	bne	00b
+	blr
+
+.udelay_not_601:		
+	mulli	r4,r3,1000	/* nanoseconds */
+	addi	r4,r4,59
+	li	r5,60
+	divw	r4,r4,r5	/* BUS ticks */
+1:	mftbu	r5
+	mftb	r6
+	mftbu	r7
+	cmp	0,r5,r7
+	bne	1b		/* Get [synced] base time */
+	addc	r9,r6,r4	/* Compute end time */
+	addze	r8,r5
+2:	mftbu	r5
+	cmp	0,r5,r8
+	blt	2b
+	bgt	3f
+	mftb	r6
+	cmp	0,r6,r9
+	blt	2b
+3:	blr		
+
+.globl _get_HID0
+_get_HID0:		
+	mfspr	r3,HID0
+	blr
+
+.globl _put_HID0
+_put_HID0:		
+	mtspr	HID0,r3
+	blr
+		
+.globl _get_MSR
+_get_MSR:		
+	mfmsr	r3
+	blr
+	
+.globl _put_MSR
+_put_MSR:		
+	mtmsr	r3
+	blr
+
+/*
+ * Flush instruction cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_instruction_cache)
+	mflr	r5
+	bl	flush_data_cache
+	mfspr	r3,HID0	/* Caches are controlled by this register */
+	li	r4,0
+	ori	r4,r4,(HID0_ICE|HID0_ICFI)
+	or	r3,r3,r4	/* Need to enable+invalidate to clear */
+	mtspr	HID0,r3
+	andc	r3,r3,r4
+	ori	r3,r3,HID0_ICE	/* Enable cache */
+	mtspr	HID0,r3
+	mtlr	r5
+	blr
+	
+#define NUM_CACHE_LINES 128*8
+#define CACHE_LINE_SIZE 32 
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_data_cache)
+	lis	r3,cache_flush_buffer@h
+	ori	r3,r3,cache_flush_buffer@l
+	li	r4,NUM_CACHE_LINES
+	mtctr	r4
+00:	lwz	r4,0(r3)
+	addi	r3,r3,CACHE_LINE_SIZE	/* Next line, please */
+	bdnz	00b	
+10:	blr
+	.comm	.stack,4096*2,4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/iso_font.h linux/arch/ppc/boot/prep/iso_font.h
--- v2.4.4/linux/arch/ppc/boot/prep/iso_font.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/iso_font.h	Thu May 24 15:02:07 2001
@@ -0,0 +1,260 @@
+/*
+ * BK Id: SCCS/s.iso_font.h 1.6 05/18/01 15:16:42 cort
+ */
+static const unsigned char font[] = {
+/* 0x00 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x01 */ 0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,
+/* 0x02 */ 0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00,
+/* 0x03 */ 0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,
+/* 0x04 */ 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
+/* 0x05 */ 0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x06 */ 0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x07 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x08 */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0x09 */ 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,
+/* 0x0A */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0x0B */ 0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
+/* 0x0C */ 0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x0D */ 0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,
+/* 0x0E */ 0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,
+/* 0x0F */ 0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x10 */ 0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
+/* 0x11 */ 0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
+/* 0x12 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
+/* 0x13 */ 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
+/* 0x14 */ 0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,
+/* 0x15 */ 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,
+/* 0x16 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,
+/* 0x17 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
+/* 0x18 */ 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x19 */ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,
+/* 0x1A */ 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1B */ 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1C */ 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1D */ 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x1E */ 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,
+/* 0x1F */ 0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
+/* 0x20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x21 */ 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x22 */ 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x23 */ 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,
+/* 0x24 */ 0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,
+/* 0x25 */ 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,
+/* 0x26 */ 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x27 */ 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x28 */ 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,
+/* 0x29 */ 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,
+/* 0x2A */ 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x2B */ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x2C */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
+/* 0x2D */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x2E */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x2F */ 0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,
+/* 0x30 */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
+/* 0x31 */ 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
+/* 0x32 */ 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0x33 */ 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x34 */ 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
+/* 0x35 */ 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x36 */ 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x37 */ 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
+/* 0x38 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x39 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
+/* 0x3A */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+/* 0x3B */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
+/* 0x3C */ 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,
+/* 0x3D */ 0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x3E */ 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
+/* 0x3F */ 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x40 */ 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00,
+/* 0x41 */ 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x42 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,
+/* 0x43 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,
+/* 0x44 */ 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
+/* 0x45 */ 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+/* 0x46 */ 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x47 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,
+/* 0x48 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x49 */ 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x4A */ 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
+/* 0x4B */ 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x4C */ 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
+/* 0x4D */ 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x4E */ 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x4F */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x50 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x51 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,
+/* 0x52 */ 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x53 */ 0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x54 */ 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x55 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x56 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
+/* 0x57 */ 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,
+/* 0x58 */ 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x59 */ 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x5A */ 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0x5B */ 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
+/* 0x5C */ 0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
+/* 0x5D */ 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,
+/* 0x5E */ 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x5F */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,
+/* 0x60 */ 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x61 */ 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x62 */ 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,
+/* 0x63 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x64 */ 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x65 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x66 */ 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x67 */ 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,
+/* 0x68 */ 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x69 */ 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x6A */ 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,
+/* 0x6B */ 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,
+/* 0x6C */ 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x6D */ 0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x6E */ 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+/* 0x6F */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x70 */ 0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
+/* 0x71 */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
+/* 0x72 */ 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
+/* 0x73 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x74 */ 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,
+/* 0x75 */ 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x76 */ 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,
+/* 0x77 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,
+/* 0x78 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,
+/* 0x79 */ 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
+/* 0x7A */ 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0x7B */ 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,
+/* 0x7C */ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x7D */ 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
+/* 0x7E */ 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0x7F */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,
+/* 0x80 */ 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,
+/* 0x81 */ 0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x82 */ 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x83 */ 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x84 */ 0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x85 */ 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x86 */ 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x87 */ 0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,
+/* 0x88 */ 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x89 */ 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x8A */ 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x8B */ 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x8C */ 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x8D */ 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0x8E */ 0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x8F */ 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0x90 */ 0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00,
+/* 0x91 */ 0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,
+/* 0x92 */ 0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,
+/* 0x93 */ 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x94 */ 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x95 */ 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x96 */ 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x97 */ 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0x98 */ 0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
+/* 0x99 */ 0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x9A */ 0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0x9B */ 0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x9C */ 0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,
+/* 0x9D */ 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0x9E */ 0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,
+/* 0x9F */ 0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,
+/* 0xA0 */ 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0xA1 */ 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
+/* 0xA2 */ 0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0xA3 */ 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
+/* 0xA4 */ 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
+/* 0xA5 */ 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0xA6 */ 0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xA7 */ 0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xA8 */ 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
+/* 0xA9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,
+/* 0xAA */ 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
+/* 0xAB */ 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,
+/* 0xAC */ 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00,
+/* 0xAD */ 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,
+/* 0xAE */ 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xAF */ 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xB0 */ 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
+/* 0xB1 */ 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
+/* 0xB2 */ 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,
+/* 0xB3 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB4 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB5 */ 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB6 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xB7 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xB8 */ 0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xB9 */ 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xBA */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xBB */ 0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xBC */ 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xBD */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xBE */ 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xBF */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC0 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC1 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC2 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC3 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC4 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC5 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC6 */ 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xC7 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xC8 */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xC9 */ 0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCA */ 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xCB */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCC */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCD */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xCE */ 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xCF */ 0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD0 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD1 */ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xD2 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xD3 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD4 */ 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xD5 */ 0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xD6 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xD7 */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
+/* 0xD8 */ 0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xD9 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xDA */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xDB */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0xDC */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+/* 0xDD */ 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
+/* 0xDE */ 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+/* 0xDF */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xE0 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,
+/* 0xE1 */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00,
+/* 0xE2 */ 0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,
+/* 0xE3 */ 0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,
+/* 0xE4 */ 0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
+/* 0xE5 */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
+/* 0xE6 */ 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00,
+/* 0xE7 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
+/* 0xE8 */ 0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
+/* 0xE9 */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
+/* 0xEA */ 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,
+/* 0xEB */ 0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,
+/* 0xEC */ 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xED */ 0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,
+/* 0xEE */ 0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,
+/* 0xEF */ 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
+/* 0xF0 */ 0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,
+/* 0xF1 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
+/* 0xF2 */ 0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00,
+/* 0xF3 */ 0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00,
+/* 0xF4 */ 0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+/* 0xF5 */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
+/* 0xF6 */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
+/* 0xF7 */ 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xF8 */ 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xF9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFA */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFB */ 0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,
+/* 0xFC */ 0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFD */ 0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* 0xFE */ 0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,
+};
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/kbd.c linux/arch/ppc/boot/prep/kbd.c
--- v2.4.4/linux/arch/ppc/boot/prep/kbd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/kbd.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,218 @@
+/*
+ * BK Id: SCCS/s.kbd.c 1.7 05/18/01 06:20:29 patch
+ */
+#include <linux/keyboard.h>
+
+#include <../drivers/char/defkeymap.c>	/* yeah I know it's bad -- Cort */
+
+
+unsigned char shfts, ctls, alts, caps;
+
+#define	KBDATAP		0x60	/* kbd data port */
+#define	KBSTATUSPORT	0x61	/* kbd status */
+#define	KBSTATP		0x64	/* kbd status port */
+#define	KBINRDY		0x01
+#define	KBOUTRDY	0x02
+
+extern unsigned char inb(int port);
+extern void outb(int port, char val);
+extern void puts(const char *);
+extern void puthex(unsigned long val);
+extern void udelay(long x);
+
+static int kbd(int noblock)
+{
+	unsigned char dt, brk, val;
+	unsigned code;
+loop:
+	if (noblock) {
+	    if ((inb(KBSTATP) & KBINRDY) == 0)
+		return (-1);
+	} else while((inb(KBSTATP) & KBINRDY) == 0) ;
+
+	dt = inb(KBDATAP);
+
+	brk = dt & 0x80;	/* brk == 1 on key release */
+	dt = dt & 0x7f;		/* keycode */
+
+	if (shfts)
+	    code = shift_map[dt];
+	else if (ctls)
+	    code = ctrl_map[dt];
+	else
+	    code = plain_map[dt];
+
+	val = KVAL(code);
+	switch (KTYP(code) & 0x0f) {
+	    case KT_LATIN:
+		if (brk)
+		    break;
+		if (alts)
+		    val |= 0x80;
+		if (val == 0x7f)	/* map delete to backspace */
+		    val = '\b';
+		return val;
+
+	    case KT_LETTER:
+		if (brk)
+		    break;
+		if (caps)
+		    val -= 'a'-'A';
+		return val;
+
+	    case KT_SPEC:
+		if (brk)
+		    break;
+		if (val == KVAL(K_CAPS))
+		    caps = !caps;
+		else if (val == KVAL(K_ENTER)) {
+enter:		    /* Wait for key up */
+		    while (1) {
+			while((inb(KBSTATP) & KBINRDY) == 0) ;
+			dt = inb(KBDATAP);
+			if (dt & 0x80) /* key up */ break;
+		    }
+		    return 10;
+		}
+		break;
+
+	    case KT_PAD:
+		if (brk)
+		    break;
+		if (val < 10)
+		    return val;
+		if (val == KVAL(K_PENTER))
+		    goto enter;
+		break;
+
+	    case KT_SHIFT:
+		switch (val) {
+		    case KG_SHIFT:
+		    case KG_SHIFTL:
+		    case KG_SHIFTR:
+			shfts = brk ? 0 : 1;
+			break;
+		    case KG_ALT:
+		    case KG_ALTGR:
+			alts = brk ? 0 : 1;
+			break;
+		    case KG_CTRL:
+		    case KG_CTRLL:
+		    case KG_CTRLR:
+			ctls = brk ? 0 : 1;
+			break;
+		}
+		break;
+
+	    case KT_LOCK:
+		switch (val) {
+		    case KG_SHIFT:
+		    case KG_SHIFTL:
+		    case KG_SHIFTR:
+			if (brk)
+			    shfts = !shfts;
+			break;
+		    case KG_ALT:
+		    case KG_ALTGR:
+			if (brk)
+			    alts = !alts;
+			break;
+		    case KG_CTRL:
+		    case KG_CTRLL:
+		    case KG_CTRLR:
+			if (brk)
+			    ctls = !ctls;
+			break;
+		}
+		break;
+	}
+	if (brk) return (-1);  /* Ignore initial 'key up' codes */
+	goto loop;
+}
+
+static void kbdreset(void)
+{
+	unsigned char c;
+	int i;
+
+	/* flush input queue */
+	while ((inb(KBSTATP) & KBINRDY))
+	{
+		(void)inb(KBDATAP);
+	}
+	/* Send self-test */
+	while (inb(KBSTATP) & KBOUTRDY) ;
+	outb(KBSTATP,0xAA);
+	while ((inb(KBSTATP) & KBINRDY) == 0) ;	/* wait input ready */
+	if ((c = inb(KBDATAP)) != 0x55)
+	{
+		puts("Keyboard self test failed - result:");
+		puthex(c);
+		puts("\n");
+	}
+	/* Enable interrupts and keyboard controller */
+	while (inb(KBSTATP) & KBOUTRDY) ;
+	outb(KBSTATP,0x60);	
+	while (inb(KBSTATP) & KBOUTRDY) ;
+	outb(KBDATAP,0x45);
+	for (i = 0;  i < 10000;  i++) udelay(1);
+	
+	while (inb(KBSTATP) & KBOUTRDY) ;
+	outb(KBSTATP,0x20);
+	while ((inb(KBSTATP) & KBINRDY) == 0) ; /* wait input ready */
+	if (! (inb(KBDATAP) & 0x40)) {
+		/*
+		 * Quote from PS/2 System Reference Manual:
+		 *
+		 * "Address hex 0060 and address hex 0064 should be
+		 * written only when the input-buffer-full bit and
+		 * output-buffer-full bit in the Controller Status
+		 * register are set 0." (KBINRDY and KBOUTRDY)
+		 */
+		
+		while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
+		outb(KBDATAP,0xF0);
+		while (inb(KBSTATP) & (KBINRDY | KBOUTRDY)) ;
+		outb(KBDATAP,0x01);
+	}
+	
+	while (inb(KBSTATP) & KBOUTRDY) ;
+	outb(KBSTATP,0xAE);
+}
+
+/* We have to actually read the keyboard when CRT_tstc is called,
+ * since the pending data might be a key release code, and therefore
+ * not valid data.  In this case, kbd() will return -1, even though there's
+ * data to be read.  Of course, we might actually read a valid key press,
+ * in which case it gets queued into key_pending for use by CRT_getc.
+ */
+
+static int kbd_reset = 0;
+
+static int key_pending = -1;
+
+int CRT_getc(void)
+{
+	int c;
+	if (!kbd_reset) {kbdreset(); kbd_reset++; }
+
+        if (key_pending != -1) {
+                c = key_pending;
+                key_pending = -1;
+                return c;
+        } else {
+	while ((c = kbd(0)) == 0) ;
+                return c;
+        }
+}
+
+int CRT_tstc(void)
+{
+	if (!kbd_reset) {kbdreset(); kbd_reset++; }
+
+        while (key_pending == -1 && ((inb(KBSTATP) & KBINRDY) != 0)) {
+                key_pending = kbd(1);
+        }
+
+        return (key_pending != -1);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/misc.c linux/arch/ppc/boot/prep/misc.c
--- v2.4.4/linux/arch/ppc/boot/prep/misc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/misc.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,453 @@
+/*
+ * BK Id: SCCS/s.misc.c 1.8 05/18/01 06:20:29 patch
+ */
+/*
+ * misc.c
+ *
+ * Adapted for PowerPC by Gary Thomas
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
+ */
+
+#include <linux/types.h>
+#include "zlib.h"
+#include <asm/residual.h>
+#include <linux/elf.h>
+#include <linux/config.h>
+#include <linux/pci_ids.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/bootinfo.h>
+#include <asm/mmu.h>
+#include <asm/byteorder.h>
+#if defined(CONFIG_SERIAL_CONSOLE)
+unsigned long com_port;
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+/*
+ * Please send me load/board info and such data for hardware not
+ * listed here so I can keep track since things are getting tricky
+ * with the different load addrs with different firmware.  This will
+ * help to avoid breaking the load/boot process.
+ * -- Cort
+ */
+char *avail_ram;
+char *end_avail;
+extern char _end[];
+
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE "";
+#endif
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+
+int keyb_present = 1;	/* keyboard controller is present by default */
+RESIDUAL hold_resid_buf;
+RESIDUAL *hold_residual = &hold_resid_buf;
+unsigned long initrd_start = 0, initrd_end = 0;
+char *zimage_start;
+int zimage_size;
+
+char *vidmem = (char *)0xC00B8000;
+int lines, cols;
+int orig_x, orig_y;
+
+extern void puts(const char *);
+extern void putc(const char c);
+extern int tstc(void);
+extern int getc(void);
+extern void puthex(unsigned long val);
+extern void * memcpy(void * __dest, __const void * __src, __kernel_size_t __n);
+extern int CRT_tstc(void);
+extern void of_init(void *handler);
+extern int of_finddevice(const char *device_specifier, int *phandle);
+extern int of_getprop(int phandle, const char *name, void *buf, int buflen, 
+		int *size);
+extern __kernel_size_t strlen(const char *s);
+extern int vga_init(unsigned char *ISA_mem);
+extern void udelay(long x);
+void gunzip(void *, int, unsigned char *, int *);
+unsigned char inb(int);
+
+void
+writel(unsigned int val, unsigned int address)
+{
+	/* Ensure I/O operations complete */
+	__asm__ volatile("eieio");
+	*(unsigned int *)address = cpu_to_le32(val);
+}
+
+unsigned int 
+readl(unsigned int address)
+{
+	/* Ensure I/O operations complete */
+	__asm__ volatile("eieio");
+	return le32_to_cpu(*(unsigned int *)address);
+}
+
+#define PCI_CFG_ADDR(dev,off)	((0x80<<24) | (dev<<8) | (off&0xfc)) 
+#define PCI_CFG_DATA(off)	(0x80000cfc+(off&3))  
+
+static void
+pci_read_config_32(unsigned char devfn,
+		unsigned char offset,
+		unsigned int *val)
+{
+	writel(PCI_CFG_ADDR(devfn,offset), 0x80000cf8);
+	*val = readl(PCI_CFG_DATA(offset));
+	return;
+}
+
+void
+scroll()
+{
+	int i;
+
+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+		vidmem[i] = ' ';
+}
+
+/*
+ * This routine is used to control the second processor on the 
+ * Motorola dual processor platforms.  
+ */
+void
+park_cpus()
+{
+	volatile void (*go)(RESIDUAL *, int, int, char *, int);
+	unsigned int i;
+	volatile unsigned long *smp_iar = &(hold_residual->VitalProductData.SmpIar);
+
+	/* Wait for indication to continue.  If the kernel
+	   was not compiled with SMP support then the second 
+	   processor will spin forever here makeing the kernel
+	   multiprocessor safe. */
+	while (*smp_iar == 0) {
+                for (i=0; i < 512; i++);
+	}
+
+	(unsigned long)go = hold_residual->VitalProductData.SmpIar;
+	go(hold_residual, 0, 0, cmd_line, sizeof(cmd_preset));
+}
+
+unsigned long
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+		  RESIDUAL *residual, void *OFW_interface)
+{
+	int timer;
+	extern unsigned long start;
+	char *cp, ch;
+	unsigned long TotalMemory;
+	unsigned long orig_MSR;
+	int dev_handle;
+	int mem_info[2];
+	int res, size;
+	unsigned char board_type;
+	unsigned char base_mod;
+	int start_multi = 0;
+	unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base;
+
+	lines = 25;
+	cols = 80;
+	orig_x = 0;
+	orig_y = 24;
+	
+	/*
+	 * IBM's have the MMU on, so we have to disable it or
+	 * things get really unhappy in the kernel when
+	 * trying to setup the BATs with the MMU on
+	 * -- Cort
+	 */
+	flush_instruction_cache();
+	_put_HID0(_get_HID0() & ~0x0000C000);
+	_put_MSR((orig_MSR = _get_MSR()) & ~0x0030);
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+	com_port = serial_init(0);
+#endif /* CONFIG_SERIAL_CONSOLE */
+	vga_init((char)0xC0000000);
+
+	if (residual)
+	{
+		/* Is this Motorola PPCBug? */
+		if ((1 & residual->VitalProductData.FirmwareSupports) &&
+		    (1 == residual->VitalProductData.FirmwareSupplier)) {
+			board_type = inb(0x800) & 0xF0;
+
+			/*
+			 * Reset the onboard 21x4x Ethernet
+			 * Motorola Ethernet is at IDSEL 14 (devfn 0x70)
+			 */
+			pci_read_config_32(0x70, 0x00, &pci_viddid);
+			pci_did = (pci_viddid & 0xffff0000) >> 16;
+			/* Be sure we've really found a 21x4x chip */
+			if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) &&
+				((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) ||
+				(pci_did == PCI_DEVICE_ID_DEC_TULIP) ||
+				(pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) ||
+				(pci_did == PCI_DEVICE_ID_DEC_21142)))
+			{
+				pci_read_config_32(0x70,
+						0x10,
+						&tulip_pci_base);
+				/* Get the physical base address */
+				tulip_base =
+					(tulip_pci_base & ~0x03UL) + 0x80000000;
+				/* Strobe the 21x4x reset bit in CSR0 */
+				writel(0x1, tulip_base);
+			}
+
+			/* If this is genesis 2 board then check for no
+			 * keyboard controller and more than one processor.
+			 */
+			if (board_type == 0xe0) {	
+				base_mod = inb(0x803);
+				/* if a MVME2300/2400 or a Sitka then no keyboard */
+				if((base_mod == 0xFA) || (base_mod == 0xF9) ||
+				   (base_mod == 0xE1)) {
+					keyb_present = 0;	/* no keyboard */
+				}
+			}
+			/* If this is a multiprocessor system then
+			 * park the other processor so that the
+			 * kernel knows where to find them.
+			 */
+			if (residual->MaxNumCpus > 1) {
+				start_multi = 1;
+			}
+		}
+		memcpy(hold_residual,residual,sizeof(RESIDUAL));
+	} else {
+		/* Assume 32M in the absence of more info... */
+		TotalMemory = 0x02000000;
+		/*
+		 * This is a 'best guess' check.  We want to make sure
+		 * we don't try this on a PReP box without OF
+		 *     -- Cort
+		 */
+		while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) )
+		{
+			/* The MMU needs to be on when we call OFW */
+			_put_MSR(orig_MSR);
+			of_init(OFW_interface);
+
+			/* get handle to memory description */
+			res = of_finddevice("/memory@0", 
+					    &dev_handle);
+			// puthex(res);  puts("\n");
+			if (res) break;
+			
+			/* get the info */
+			// puts("get info = ");
+			res = of_getprop(dev_handle, 
+					 "reg", 
+					 mem_info, 
+					 sizeof(mem_info), 
+					 &size);
+			// puthex(res);  puts(", info = "); puthex(mem_info[0]);  
+			// puts(" ");  puthex(mem_info[1]);   puts("\n");
+			if (res) break;
+			
+			TotalMemory = mem_info[1];
+			break;
+		}
+		hold_residual->TotalMemory = TotalMemory;
+		residual = hold_residual;
+		/* Turn MMU back off */
+		_put_MSR(orig_MSR & ~0x0030);
+        }
+
+	if (start_multi) {
+		hold_residual->VitalProductData.SmpIar = 0;
+		hold_residual->Cpus[1].CpuState = CPU_GOOD_FW;
+		residual->VitalProductData.SmpIar = (unsigned long)park_cpus;
+		residual->Cpus[1].CpuState = CPU_GOOD;
+		hold_residual->VitalProductData.Reserved5 = 0xdeadbeef;
+	}
+
+	/* assume the chunk below 8M is free */
+	end_avail = (char *)0x00800000;
+
+	/* tell the user where we were loaded at and where we
+	 * were relocated to for debugging this process
+	 */
+	puts("loaded at:     "); puthex(load_addr);
+	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
+	if ( (unsigned long)load_addr != (unsigned long)&start )
+	{
+		puts("relocated to:  "); puthex((unsigned long)&start);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+		puts("\n");
+	}
+
+	if ( residual )
+	{
+		puts("board data at: "); puthex((unsigned long)residual);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL)));
+		puts("\n");
+		puts("relocated to:  ");
+		puthex((unsigned long)hold_residual);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL)));
+		puts("\n");
+	}
+
+	/* we have to subtract 0x10000 here to correct for objdump including the
+	   size of the elf header which we strip -- Cort */
+	zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
+	zimage_size = ZIMAGE_SIZE;
+
+	if ( INITRD_OFFSET )
+		initrd_start = load_addr - 0x10000 + INITRD_OFFSET;
+	else
+		initrd_start = 0;
+	initrd_end = INITRD_SIZE + initrd_start;
+
+	/*
+	 * Find a place to stick the zimage and initrd and 
+	 * relocate them if we have to. -- Cort
+	 */
+	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
+	puts("zimage at:     "); puthex((unsigned long)zimage_start);
+	puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
+	if ( (unsigned long)zimage_start <= 0x00800000 )
+	{
+		memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
+		zimage_start = (char *)avail_ram;
+		puts("relocated to:  "); puthex((unsigned long)zimage_start);
+		puts(" ");
+		puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
+		puts("\n");
+
+		/* relocate initrd */
+		if ( initrd_start )
+		{
+			puts("initrd at:     "); puthex(initrd_start);
+			puts(" "); puthex(initrd_end); puts("\n");
+			avail_ram = (char *)PAGE_ALIGN(
+				(unsigned long)zimage_size+(unsigned long)zimage_start);
+			memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
+			initrd_start = (unsigned long)avail_ram;
+			initrd_end = initrd_start + INITRD_SIZE;
+			puts("relocated to:  "); puthex(initrd_start);
+			puts(" "); puthex(initrd_end); puts("\n");
+		}
+	} else if ( initrd_start ) {
+		puts("initrd at:     "); puthex(initrd_start);
+		puts(" "); puthex(initrd_end); puts("\n");
+	}
+
+	avail_ram = (char *)0x00400000;
+	end_avail = (char *)0x00800000;
+	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
+	puthex((unsigned long)end_avail); puts("\n");
+
+	if (keyb_present)
+		CRT_tstc();  /* Forces keyboard to be initialized */
+
+	puts("\nLinux/PPC load: ");
+	timer = 0;
+	cp = cmd_line;
+	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+	while ( *cp ) putc(*cp++);
+	while (timer++ < 5*1000) {
+		if (tstc()) {
+			while ((ch = getc()) != '\n' && ch != '\r') {
+				if (ch == '\b') {
+					if (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
+				} else {
+					*cp++ = ch;
+					putc(ch);
+				}
+			}
+			break;  /* Exit 'timer' loop */
+		}
+		udelay(1000);  /* 1 msec */
+	}
+	*cp = 0;
+	puts("\n");
+
+	/* mappings on early boot can only handle 16M */
+	if ( (int)(cmd_line[0]) > (16<<20))
+		puts("cmd_line located > 16M\n");
+	if ( (int)hold_residual > (16<<20))
+		puts("hold_residual located > 16M\n");
+	if ( initrd_start > (16<<20))
+		puts("initrd_start located > 16M\n");
+
+	puts("Uncompressing Linux...");
+	
+	gunzip(0, 0x400000, zimage_start, &zimage_size);
+	puts("done.\n");
+	
+	{
+		struct bi_record *rec;
+	    
+		rec = (struct bi_record *)PAGE_ALIGN(zimage_size);
+	    
+		rec->tag = BI_FIRST;
+		rec->size = sizeof(struct bi_record);
+		rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+		rec->tag = BI_BOOTLOADER_ID;
+		memcpy( (void *)rec->data, "prepboot", 9);
+		rec->size = sizeof(struct bi_record) + 8 + 1;
+		rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	    
+		rec->tag = BI_MACHTYPE;
+		rec->data[0] = _MACH_prep;
+		rec->data[1] = 1;
+		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+		rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	    
+		rec->tag = BI_CMD_LINE;
+		memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
+		rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
+		rec = (struct bi_record *)((ulong)rec + rec->size);
+		
+		rec->tag = BI_LAST;
+		rec->size = sizeof(struct bi_record);
+		rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	}
+	puts("Now booting the kernel\n");
+	return (unsigned long)hold_residual;
+}
+
+/*
+ * PCI/ISA I/O support
+ */
+
+volatile unsigned char *ISA_io  = (unsigned char *)0x80000000;
+volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
+
+void
+outb(int port, char val)
+{
+	/* Ensure I/O operations complete */
+	__asm__ volatile("eieio");
+	ISA_io[port] = val;
+}
+
+unsigned char
+inb(int port)
+{
+	/* Ensure I/O operations complete */
+	__asm__ volatile("eieio");
+	return (ISA_io[port]);
+}
+
+unsigned long
+local_to_PCI(unsigned long addr)
+{
+	return ((addr & 0x7FFFFFFF) | 0x80000000);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/of1275.c linux/arch/ppc/boot/prep/of1275.c
--- v2.4.4/linux/arch/ppc/boot/prep/of1275.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/of1275.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,430 @@
+/*
+ * BK Id: SCCS/s.of1275.c 1.6 05/18/01 15:16:42 cort
+ */
+/* Open Firmware Client Interface */
+
+
+#include "of1275.h"
+
+
+static int (*of_server)(void *) = (int(*)(void*))-1;
+
+void
+of_init(void *handler)
+{
+	of_server = (int(*)(void*))handler;
+}
+
+
+/* 6.3.2.1 Client interface */
+
+
+int
+of_test(const char *name, int *missing)
+{
+	int result;
+	static of_test_service s;
+	s.service = "test";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.name = name;
+	result = of_server(&s);
+	*missing = s.missing;
+	return result;
+}
+
+
+/* 6.3.2.2 Device tree */
+
+
+int
+of_peer(int phandle, int *sibling_phandle)
+{
+	int result;
+	static of_peer_service s;
+	s.service = "peer";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	result = of_server(&s);
+	*sibling_phandle = s.sibling_phandle;
+	return result;
+}
+
+int
+of_child(int phandle, int *child_phandle)
+{
+	int result;
+	static of_child_service s;
+	s.service = "child";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	result = of_server(&s);
+	*child_phandle = s.child_phandle;
+	return result;
+}
+
+int
+of_parent(int phandle, int *parent_phandle)
+{
+	int result;
+	static of_parent_service s;
+	s.service = "parent";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	result = of_server(&s);
+	*parent_phandle = s.parent_phandle;
+	return result;
+}
+
+int
+of_instance_to_package(int ihandle, int *phandle)
+{
+	int result;
+	static of_instance_to_package_service s;
+	s.service = "instance-to-package";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.ihandle = ihandle;
+	result = of_server(&s);
+	*phandle = s.phandle;
+	return result;
+}
+
+int
+of_getproplen(int phandle, const char *name, int *proplen)
+{
+	int result;
+	static of_getproplen_service s;
+	s.service = "getproplen";
+	s.n_args = 2;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	s.name = name;
+	result = of_server(&s);
+	*proplen = s.proplen;
+	return result;
+}
+
+int
+of_getprop(int phandle, const char *name, void *buf, int buflen, int *size)
+{
+	int result;
+	static of_getprop_service s;
+	s.service = "getprop";
+	s.n_args = 4;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	s.name = name;
+	s.buf = buf;
+	s.buflen = buflen;
+	result = of_server(&s);
+	*size = s.size;
+	return result;
+}
+
+int
+of_nextprop(int phandle, const char *previous, void *buf, int *flag)
+{
+	int result;
+	static of_nextprop_service s;
+	s.service = "nextprop";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	s.previous = previous;
+	s.buf = buf;
+	result = of_server(&s);
+	*flag = s.flag;
+	return result;
+}
+
+int
+of_setprop(int phandle, const char *name, void *buf, int len, int *size)
+{
+	int result;
+	static of_setprop_service s;
+	s.service = "setprop";
+	s.n_args = 4;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	s.name = name;
+	s.buf = buf;
+	s.len = len;
+	result = of_server(&s);
+	*size = s.size;
+	return result;
+}
+
+int
+of_canon(const char *device_specifier, void *buf, int buflen, int *length)
+{
+	int result;
+	static of_canon_service s;
+	s.service = "canon";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.device_specifier = device_specifier;
+	s.buf = buf;
+	s.buflen = buflen;
+	result = of_server(&s);
+	*length = s.length;
+	return result;
+}
+
+int
+of_finddevice(const char *device_specifier, int *phandle)
+{
+	int result;
+	static of_finddevice_service s;
+	s.service = "finddevice";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.device_specifier = device_specifier;
+	result = of_server(&s);
+	*phandle = s.phandle;
+	return result;
+}
+
+int
+of_instance_to_path(int ihandle, void *buf, int buflen, int *length)
+{
+	int result;
+	static of_instance_to_path_service s;
+	s.service = "instance-to-path";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.ihandle = ihandle;
+	s.buf = buf;
+	s.buflen = buflen;
+	result = of_server(&s);
+	*length = s.length;
+	return result;
+}
+
+int
+of_package_to_path(int phandle, void *buf, int buflen, int *length)
+{
+	int result;
+	static of_package_to_path_service s;
+	s.service = "package-to-path";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.phandle = phandle;
+	s.buf = buf;
+	s.buflen = buflen;
+	result = of_server(&s);
+	*length = s.length;
+	return result;
+}
+
+/* int of_call_method(const char *method, int ihandle, ...); */
+
+
+/* 6.3.2.3 Device I/O */
+
+
+int
+of_open(const char *device_specifier, int *ihandle)
+{
+	int result;
+	static of_open_service s;
+	s.service = "open";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.device_specifier = device_specifier;
+	result = of_server(&s);
+	*ihandle = s.ihandle;
+	return result;
+}
+
+int
+of_close(int ihandle)
+{
+	int result;
+	static of_close_service s;
+	s.service = "close";
+	s.n_args = 1;
+	s.n_returns = 0;
+	s.ihandle = ihandle;
+	result = of_server(&s);
+	return result;
+}
+
+int
+of_read(int ihandle, void *addr, int len, int *actual)
+{
+	int result;
+	static of_read_service s;
+	s.service = "read";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.ihandle = ihandle;
+	s.addr = addr;
+	s.len = len;
+	result = of_server(&s);
+	*actual = s.actual;
+	return result;
+}
+
+int
+of_write(int ihandle, void *addr, int len, int *actual)
+{
+	int result;
+	static of_write_service s;
+	s.service = "write";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.ihandle = ihandle;
+	s.addr = addr;
+	s.len = len;
+	result = of_server(&s);
+	*actual = s.actual;
+	return result;
+}
+
+int
+of_seek(int ihandle, int pos_hi, int pos_lo, int *status)
+{
+	int result;
+	static of_seek_service s;
+	s.service = "seek";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.ihandle = ihandle;
+	s.pos_hi = pos_hi;
+	s.pos_lo = pos_lo;
+	result = of_server(&s);
+	*status = s.status;
+	return result;
+}
+
+
+/* 6.3.2.4 Memory */
+
+
+int
+of_claim(void *virt, int size, int align, void **baseaddr)
+{
+	int result;
+	static of_claim_service s;
+	s.service = "claim";
+	s.n_args = 3;
+	s.n_returns = 1;
+	s.virt = virt;
+	s.size = size;
+	s.align = align;
+	result = of_server(&s);
+	*baseaddr = s.baseaddr;
+	return result;
+}
+
+int
+of_release(void *virt, int size)
+{
+	int result;
+	static of_release_service s;
+	s.service = "release";
+	s.n_args = 2;
+	s.n_returns = 0;
+	s.virt = virt;
+	s.size = size;
+	result = of_server(&s);
+	return result;
+}
+
+
+/* 6.3.2.5 Control transfer */
+
+
+int
+of_boot(const char *bootspec)
+{
+	int result;
+	static of_boot_service s;
+	s.service = "boot";
+	s.n_args = 1;
+	s.n_returns = 0;
+	s.bootspec = bootspec;
+	result = of_server(&s);
+	return result;
+}
+
+int
+of_enter(void)
+{
+	int result;
+	static of_enter_service s;
+	s.service = "enter";
+	s.n_args = 0;
+	s.n_returns = 0;
+	result = of_server(&s);
+	return result;
+}
+
+int
+of_exit(void)
+{
+	int result;
+	static of_exit_service s;
+	s.service = "exit";
+	s.n_args = 0;
+	s.n_returns = 0;
+	result = of_server(&s);
+	return result;
+}
+
+/* int of_chain(void *virt, int size, void *entry, void *args, int len); */
+
+
+/* 6.3.2.6 User interface */
+
+
+/* int of_interpret(const char *arg, ...); */
+
+int
+of_set_callback(void *newfunc, void **oldfunc)
+{
+	int result;
+	static of_set_callback_service s;
+	s.service = "set-callback";
+	s.n_args = 1;
+	s.n_returns = 1;
+	s.newfunc = newfunc;
+	result = of_server(&s);
+	*oldfunc = s.oldfunc;
+	return result;
+}
+
+int
+of_set_symbol_lookup(void *sym_to_value, void *value_to_sym)
+{
+	int result;
+	static of_set_symbol_lookup_service s;
+	s.service = "set-symbol-lookup";
+	s.n_args = 2;
+	s.n_returns = 0;
+	s.sym_to_value = sym_to_value;
+	s.value_to_sym = s.value_to_sym;
+	result = of_server(&s);
+	return result;
+}
+
+
+/* 6.3.2.7 Time */
+
+
+int
+of_milliseconds(int *ms)
+{
+	int result;
+	static of_milliseconds_service s;
+	s.service = "milliseconds";
+	s.n_args = 0;
+	s.n_returns = 1;
+	result = of_server(&s);
+	*ms = s.ms;
+	return result;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/of1275.h linux/arch/ppc/boot/prep/of1275.h
--- v2.4.4/linux/arch/ppc/boot/prep/of1275.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/of1275.h	Thu May 24 15:02:07 2001
@@ -0,0 +1,424 @@
+/*
+ * BK Id: SCCS/s.of1275.h 1.6 05/18/01 15:16:42 cort
+ */
+/* 6.3.2.1 Client interface */
+
+
+typedef struct _of_test_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *name;
+	/*out*/
+	int missing;
+} of_test_service;
+
+int of_test(const char *name, int *missing);
+
+
+/* 6.3.2.2 Device tree */
+
+
+typedef struct _of_peer_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	/*out*/
+	int sibling_phandle;
+} of_peer_service;
+
+int of_peer(int phandle, int *sibling_phandle);
+
+
+typedef struct _of_child_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	/*out*/
+	int child_phandle;
+} of_child_service;
+
+int of_child(int phandle, int *child_phandle);
+
+
+typedef struct _of_parent_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	/*out*/
+	int parent_phandle;
+} of_parent_service;
+
+int of_child(int phandle, int *parent_phandle);
+
+
+typedef struct _of_instance_to_package_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int ihandle;
+	/*out*/
+	int phandle;
+} of_instance_to_package_service;
+
+int of_instance_to_package(int ihandle, int *phandle);
+
+
+typedef struct _of_getproplen_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	const char *name;
+	/*out*/
+	int proplen;
+} of_getproplen_service;
+
+int of_getproplen(int phandle, const char *name, int *proplen);
+
+
+typedef struct _of_getprop_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	const char *name;
+	void *buf;
+	int buflen;
+	/*out*/
+	int size;
+} of_getprop_service;
+
+int of_getprop(int phandle, const char *name, void *buf, int buflen,
+	       int *size);
+
+
+typedef struct _of_nextprop_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	const char *previous;
+	void *buf;
+	/*out*/
+	int flag;
+} of_nextprop_service;
+
+int of_nextprop(int phandle, const char *previous, void *buf, int *flag);
+
+
+typedef struct _of_setprop_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	const char *name;
+	void *buf;
+	int len;
+	/*out*/
+	int size;
+} of_setprop_service;
+
+int of_setprop(int phandle, const char *name, void *buf, int len, int *size);
+
+
+typedef struct _of_canon_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *device_specifier;
+	void *buf;
+	int buflen;
+	/*out*/
+	int length;
+} of_canon_service;
+
+int of_canon(const char *device_specifier, void *buf, int buflen, int *length);
+
+
+typedef struct _of_finddevice_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *device_specifier;
+	/*out*/
+	int phandle;
+} of_finddevice_service;
+
+int of_finddevice(const char *device_specifier, int *phandle);
+
+
+typedef struct _of_instance_to_path_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int ihandle;
+	void *buf;
+	int buflen;
+	/*out*/
+	int length;
+} of_instance_to_path_service;
+
+int of_instance_to_path(int ihandle, void *buf, int buflen, int *length);
+
+
+typedef struct _of_package_to_path_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int phandle;
+	void *buf;
+	int buflen;
+	/*out*/
+	int length;
+} of_package_to_path_service;
+
+int of_package_to_path(int phandle, void *buf, int buflen, int *length);
+
+
+typedef struct _of_call_method_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *method;
+	int ihandle;
+	/*...*/
+	int args[0]; 
+} of_call_method_service;
+
+int of_call_method(const char *method, int ihandle, ...);
+
+
+/* 6.3.2.3 Device I/O */
+
+
+typedef struct _of_open_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *device_specifier;
+	/*out*/
+	int ihandle;
+} of_open_service;
+
+int of_open(const char *device_specifier,
+	    int *ihandle);
+
+
+typedef struct _of_close_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int ihandle;
+	/*out*/
+} of_close_service;
+
+int of_close(int ihandle);
+
+
+typedef struct _of_read_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int ihandle;
+	void *addr;
+	int len;
+	/*out*/
+	int actual;
+} of_read_service;
+
+int of_read(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of_write_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int ihandle;
+	void *addr;
+	int len;
+	/*out*/
+	int actual;
+} of_write_service;
+
+int of_write(int ihandle, void *addr, int len, int *actual);
+
+
+typedef struct _of_seek_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	int ihandle;
+	int pos_hi;
+	int pos_lo;
+	/*out*/
+	int status;
+} of_seek_service;
+
+int of_seek(int ihandle, int pos_hi, int pos_lo, int *status);
+
+
+/* 6.3.2.4 Memory */
+
+
+typedef struct _of_claim_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	void *virt;
+	int size;
+	int align;
+	/*out*/
+	void *baseaddr;
+} of_claim_service;
+
+int of_claim(void *virt, int size, int align, void **baseaddr);
+
+
+typedef struct _of_release_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	void *virt;
+	int size;
+	int align;
+	/*out*/
+} of_release_service;
+
+int of_release(void *virt, int size);
+
+
+/* 6.3.2.5 Control transfer */
+
+
+typedef struct _of_boot_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *bootspec;
+	/*out*/
+} of_boot_service;
+
+int of_boot(const char *bootspec);
+
+
+typedef struct _of_enter_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	/*out*/
+} of_enter_service;
+
+int of_enter(void);
+
+
+typedef struct _of_exit_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	/*out*/
+} of_exit_service;
+
+int of_exit(void);
+
+
+typedef struct _of_chain_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	void *virt;
+	int size;
+	void *entry;
+	void *args;
+	int len;
+	/*out*/
+} of_chain_service;
+
+int of_chain(void *virt, int size, void *entry, void *args, int len);
+
+
+/* 6.3.2.6 User interface */
+
+
+typedef struct _of_interpret_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	const char *cmd;
+	int args[0];
+	/*...*/
+	/*out*/
+	/*...*/
+} of_interpret_service;
+
+int of_interpret(const char *arg, ...);
+
+
+typedef struct _of_set_callback_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	void *newfunc;
+	/*out*/
+	void *oldfunc;
+} of_set_callback_service;
+
+int of_set_callback(void *newfunc, void **oldfunc);
+
+
+typedef struct _of_set_symbol_lookup_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	void *sym_to_value;
+	void *value_to_sym;
+	/*out*/
+} of_set_symbol_lookup_service;
+
+int of_set_symbol_lookup(void *sym_to_value, void *value_to_sym);
+
+
+/* 6.3.2.7 Time */
+
+
+typedef struct _of_milliseconds_service {
+	const char *service;
+	int n_args;
+	int n_returns;
+	/*in*/
+	/*out*/
+	int ms;
+} of_milliseconds_service;
+
+int of_milliseconds(int *ms);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/prep/vreset.c linux/arch/ppc/boot/prep/vreset.c
--- v2.4.4/linux/arch/ppc/boot/prep/vreset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/prep/vreset.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,863 @@
+/*
+ * BK Id: SCCS/s.vreset.c 1.9 05/18/01 06:20:29 patch
+ */
+/*
+ * vreset.c
+ *
+ * Initialize the VGA control registers to 80x25 text mode.
+ *
+ * Adapted from a program by:
+ *                                      Steve Sellgren
+ *                                      San Francisco Indigo Company
+ *                                      sfindigo!sellgren@uunet.uu.net
+ *
+ * Original concept by:
+ *                                      Gary Thomas <gdt@linuxppc.org>
+ * Adapted for Moto boxes by:
+ *                                      Pat Kane & Mark Scott, 1996
+ * Adapted for IBM portables by:
+ *                                      Takeshi Ishimoto
+ * Multi-console support:
+ *                                      Terje Malmedal <terje.malmedal@usit.uio.no>
+ */
+
+#include "iso_font.h"
+
+extern char *vidmem;
+extern int lines, cols;
+extern void udelay(long x);
+extern void outb(int port, char val);
+extern unsigned char inb(int port);
+struct VaRegs;
+
+/*
+ * VGA Register  
+ */
+struct VgaRegs
+{
+	unsigned short io_port;
+	unsigned char  io_index;
+	unsigned char  io_value;
+};
+
+void unlockVideo(int slot);
+void setTextRegs(struct VgaRegs *svp);
+void setTextCLUT(int shift);
+void clearVideoMemory();
+void loadFont(unsigned char *ISA_mem);
+
+static void mdelay(int ms)
+{
+	for (; ms > 0; --ms)
+		udelay(1000);
+}
+
+/*
+ * Default console text mode registers  used to reset
+ * graphics adapter.
+ */
+#define NREGS 54
+#define ENDMK  0xFFFF  /* End marker */
+
+#define S3Vendor        0x5333
+#define CirrusVendor    0x1013
+#define DiamondVendor   0x100E
+#define MatroxVendor    0x102B
+#define ParadiseVendor  0x101C
+
+struct VgaRegs GenVgaTextRegs[NREGS+1] = {
+/*      port    index   value  */
+  /* SR Regs */
+        0x3c4,  0x1,    0x0,
+        0x3c4,  0x2,    0x3,
+        0x3c4,  0x3,    0x0,
+        0x3c4,  0x4,    0x2,
+   /* CR Regs */
+        0x3d4,  0x0,    0x5f,
+        0x3d4,  0x1,    0x4f,
+        0x3d4,  0x2,    0x50,
+        0x3d4,  0x3,    0x82,
+        0x3d4,  0x4,    0x55,
+        0x3d4,  0x5,    0x81,
+        0x3d4,  0x6,    0xbf,
+        0x3d4,  0x7,    0x1f,
+        0x3d4,  0x8,    0x00,
+        0x3d4,  0x9,    0x4f,
+        0x3d4,  0xa,    0x0d,
+        0x3d4,  0xb,    0x0e,
+        0x3d4,  0xc,    0x00,
+        0x3d4,  0xd,    0x00,
+        0x3d4,  0xe,    0x00,
+        0x3d4,  0xf,    0x00,
+        0x3d4,  0x10,   0x9c,
+        0x3d4,  0x11,   0x8e,
+        0x3d4,  0x12,   0x8f,
+        0x3d4,  0x13,   0x28,
+        0x3d4,  0x14,   0x1f,
+        0x3d4,  0x15,   0x96,
+        0x3d4,  0x16,   0xb9,
+        0x3d4,  0x17,   0xa3,
+   /* GR Regs */
+        0x3ce,  0x0,    0x0,
+        0x3ce,  0x1,    0x0,
+        0x3ce,  0x2,    0x0,
+        0x3ce,  0x3,    0x0,
+        0x3ce,  0x4,    0x0,
+        0x3ce,  0x5,    0x10,
+        0x3ce,  0x6,    0xe,
+        0x3ce,  0x7,    0x0,
+        0x3ce,  0x8,    0xff,
+        ENDMK
+};
+
+struct VgaRegs S3TextRegs[NREGS+1] = {
+/*	port	index	value  */
+  /* SR Regs */
+	0x3c4,	0x1,	0x0,
+	0x3c4,	0x2,	0x3,
+	0x3c4,	0x3,	0x0,
+	0x3c4,	0x4,	0x2,
+   /* CR Regs */
+	0x3d4,	0x0,	0x5f,
+	0x3d4,	0x1,	0x4f,
+	0x3d4,	0x2,	0x50,
+	0x3d4,	0x3,	0x82,
+	0x3d4,	0x4,	0x55,
+	0x3d4,	0x5,	0x81,
+	0x3d4,	0x6,	0xbf,
+	0x3d4,	0x7,	0x1f,
+	0x3d4,	0x8,	0x00,
+	0x3d4,	0x9,	0x4f,
+	0x3d4,	0xa,	0x0d,
+	0x3d4,	0xb,	0x0e,
+	0x3d4,	0xc,	0x00,
+	0x3d4,	0xd,	0x00,
+	0x3d4,	0xe,	0x00,
+	0x3d4,	0xf,	0x00,
+	0x3d4,	0x10,	0x9c,
+	0x3d4,	0x11,	0x8e,
+	0x3d4,	0x12,	0x8f,
+	0x3d4,	0x13,	0x28,
+	0x3d4,	0x14,	0x1f,
+	0x3d4,	0x15,	0x96,
+	0x3d4,	0x16,	0xb9,
+	0x3d4,	0x17,	0xa3,
+   /* GR Regs */
+	0x3ce,	0x0,	0x0,
+	0x3ce,	0x1,	0x0,
+	0x3ce,	0x2,	0x0,
+	0x3ce,	0x3,	0x0,
+	0x3ce,	0x4,	0x0,
+	0x3ce,	0x5,	0x10,
+	0x3ce,	0x6,	0xe,
+	0x3ce,	0x7,	0x0,
+	0x3ce,	0x8,	0xff,
+        ENDMK
+};
+
+struct RGBColors
+{
+  unsigned char r, g, b;
+};
+
+/*
+ * Default console text mode color table.
+ * These values were obtained by booting Linux with
+ * text mode firmware & then dumping the registers.  
+ */
+struct RGBColors TextCLUT[256] = 
+{
+  /*	red	green	blue  */
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x2a,
+	0x0,	0x2a,	0x0,
+	0x0,	0x2a,	0x2a,
+	0x2a,	0x0,	0x0,
+	0x2a,	0x0,	0x2a,
+	0x2a,	0x2a,	0x0,
+	0x2a,	0x2a,	0x2a,
+	0x0,	0x0,	0x15,
+	0x0,	0x0,	0x3f,
+	0x0,	0x2a,	0x15,
+	0x0,	0x2a,	0x3f,
+	0x2a,	0x0,	0x15,
+	0x2a,	0x0,	0x3f,
+	0x2a,	0x2a,	0x15,
+	0x2a,	0x2a,	0x3f,
+	0x0,	0x15,	0x0,
+	0x0,	0x15,	0x2a,
+	0x0,	0x3f,	0x0,
+	0x0,	0x3f,	0x2a,
+	0x2a,	0x15,	0x0,
+	0x2a,	0x15,	0x2a,
+	0x2a,	0x3f,	0x0,
+	0x2a,	0x3f,	0x2a,
+	0x0,	0x15,	0x15,
+	0x0,	0x15,	0x3f,
+	0x0,	0x3f,	0x15,
+	0x0,	0x3f,	0x3f,
+	0x2a,	0x15,	0x15,
+	0x2a,	0x15,	0x3f,
+	0x2a,	0x3f,	0x15,
+	0x2a,	0x3f,	0x3f,
+	0x15,	0x0,	0x0,
+	0x15,	0x0,	0x2a,
+	0x15,	0x2a,	0x0,
+	0x15,	0x2a,	0x2a,
+	0x3f,	0x0,	0x0,
+	0x3f,	0x0,	0x2a,
+	0x3f,	0x2a,	0x0,
+	0x3f,	0x2a,	0x2a,
+	0x15,	0x0,	0x15,
+	0x15,	0x0,	0x3f,
+	0x15,	0x2a,	0x15,
+	0x15,	0x2a,	0x3f,
+	0x3f,	0x0,	0x15,
+	0x3f,	0x0,	0x3f,
+	0x3f,	0x2a,	0x15,
+	0x3f,	0x2a,	0x3f,
+	0x15,	0x15,	0x0,
+	0x15,	0x15,	0x2a,
+	0x15,	0x3f,	0x0,
+	0x15,	0x3f,	0x2a,
+	0x3f,	0x15,	0x0,
+	0x3f,	0x15,	0x2a,
+	0x3f,	0x3f,	0x0,
+	0x3f,	0x3f,	0x2a,
+	0x15,	0x15,	0x15,
+	0x15,	0x15,	0x3f,
+	0x15,	0x3f,	0x15,
+	0x15,	0x3f,	0x3f,
+	0x3f,	0x15,	0x15,
+	0x3f,	0x15,	0x3f,
+	0x3f,	0x3f,	0x15,
+	0x3f,	0x3f,	0x3f,
+	0x39,	0xc,	0x5,
+	0x15,	0x2c,	0xf,
+	0x26,	0x10,	0x3d,
+	0x29,	0x29,	0x38,
+	0x4,	0x1a,	0xe,
+	0x2,	0x1e,	0x3a,
+	0x3c,	0x25,	0x33,
+	0x3c,	0xc,	0x2c,
+	0x3f,	0x3,	0x2b,
+	0x1c,	0x9,	0x13,
+	0x25,	0x2a,	0x35,
+	0x1e,	0xa,	0x38,
+	0x24,	0x8,	0x3,
+	0x3,	0xe,	0x36,
+	0xc,	0x6,	0x2a,
+	0x26,	0x3,	0x32,
+	0x5,	0x2f,	0x33,
+	0x3c,	0x35,	0x2f,
+	0x2d,	0x26,	0x3e,
+	0xd,	0xa,	0x10,
+	0x25,	0x3c,	0x11,
+	0xd,	0x4,	0x2e,
+	0x5,	0x19,	0x3e,
+	0xc,	0x13,	0x34,
+	0x2b,	0x6,	0x24,
+	0x4,	0x3,	0xd,
+	0x2f,	0x3c,	0xc,
+	0x2a,	0x37,	0x1f,
+	0xf,	0x12,	0x38,
+	0x38,	0xe,	0x2a,
+	0x12,	0x2f,	0x19,
+	0x29,	0x2e,	0x31,
+	0x25,	0x13,	0x3e,
+	0x33,	0x3e,	0x33,
+	0x1d,	0x2c,	0x25,
+	0x15,	0x15,	0x5,
+	0x32,	0x25,	0x39,
+	0x1a,	0x7,	0x1f,
+	0x13,	0xe,	0x1d,
+	0x36,	0x17,	0x34,
+	0xf,	0x15,	0x23,
+	0x2,	0x35,	0xd,
+	0x15,	0x3f,	0xc,
+	0x14,	0x2f,	0xf,
+	0x19,	0x21,	0x3e,
+	0x27,	0x11,	0x2f,
+	0x38,	0x3f,	0x3c,
+	0x36,	0x2d,	0x15,
+	0x16,	0x17,	0x2,
+	0x1,	0xa,	0x3d,
+	0x1b,	0x11,	0x3f,
+	0x21,	0x3c,	0xd,
+	0x1a,	0x39,	0x3d,
+	0x8,	0xe,	0xe,
+	0x22,	0x21,	0x23,
+	0x1e,	0x30,	0x5,
+	0x1f,	0x22,	0x3d,
+	0x1e,	0x2f,	0xa,
+	0x0,	0x1c,	0xe,
+	0x0,	0x1c,	0x15,
+	0x0,	0x1c,	0x1c,
+	0x0,	0x15,	0x1c,
+	0x0,	0xe,	0x1c,
+	0x0,	0x7,	0x1c,
+	0xe,	0xe,	0x1c,
+	0x11,	0xe,	0x1c,
+	0x15,	0xe,	0x1c,
+	0x18,	0xe,	0x1c,
+	0x1c,	0xe,	0x1c,
+	0x1c,	0xe,	0x18,
+	0x1c,	0xe,	0x15,
+	0x1c,	0xe,	0x11,
+	0x1c,	0xe,	0xe,
+	0x1c,	0x11,	0xe,
+	0x1c,	0x15,	0xe,
+	0x1c,	0x18,	0xe,
+	0x1c,	0x1c,	0xe,
+	0x18,	0x1c,	0xe,
+	0x15,	0x1c,	0xe,
+	0x11,	0x1c,	0xe,
+	0xe,	0x1c,	0xe,
+	0xe,	0x1c,	0x11,
+	0xe,	0x1c,	0x15,
+	0xe,	0x1c,	0x18,
+	0xe,	0x1c,	0x1c,
+	0xe,	0x18,	0x1c,
+	0xe,	0x15,	0x1c,
+	0xe,	0x11,	0x1c,
+	0x14,	0x14,	0x1c,
+	0x16,	0x14,	0x1c,
+	0x18,	0x14,	0x1c,
+	0x1a,	0x14,	0x1c,
+	0x1c,	0x14,	0x1c,
+	0x1c,	0x14,	0x1a,
+	0x1c,	0x14,	0x18,
+	0x1c,	0x14,	0x16,
+	0x1c,	0x14,	0x14,
+	0x1c,	0x16,	0x14,
+	0x1c,	0x18,	0x14,
+	0x1c,	0x1a,	0x14,
+	0x1c,	0x1c,	0x14,
+	0x1a,	0x1c,	0x14,
+	0x18,	0x1c,	0x14,
+	0x16,	0x1c,	0x14,
+	0x14,	0x1c,	0x14,
+	0x14,	0x1c,	0x16,
+	0x14,	0x1c,	0x18,
+	0x14,	0x1c,	0x1a,
+	0x14,	0x1c,	0x1c,
+	0x14,	0x1a,	0x1c,
+	0x14,	0x18,	0x1c,
+	0x14,	0x16,	0x1c,
+	0x0,	0x0,	0x10,
+	0x4,	0x0,	0x10,
+	0x8,	0x0,	0x10,
+	0xc,	0x0,	0x10,
+	0x10,	0x0,	0x10,
+	0x10,	0x0,	0xc,
+	0x10,	0x0,	0x8,
+	0x10,	0x0,	0x4,
+	0x10,	0x0,	0x0,
+	0x10,	0x4,	0x0,
+	0x10,	0x8,	0x0,
+	0x10,	0xc,	0x0,
+	0x10,	0x10,	0x0,
+	0xc,	0x10,	0x0,
+	0x8,	0x10,	0x0,
+	0x4,	0x10,	0x0,
+	0x0,	0x10,	0x0,
+	0x0,	0x10,	0x4,
+	0x0,	0x10,	0x8,
+	0x0,	0x10,	0xc,
+	0x0,	0x10,	0x10,
+	0x0,	0xc,	0x10,
+	0x0,	0x8,	0x10,
+	0x0,	0x4,	0x10,
+	0x8,	0x8,	0x10,
+	0xa,	0x8,	0x10,
+	0xc,	0x8,	0x10,
+	0xe,	0x8,	0x10,
+	0x10,	0x8,	0x10,
+	0x10,	0x8,	0xe,
+	0x10,	0x8,	0xc,
+	0x10,	0x8,	0xa,
+	0x10,	0x8,	0x8,
+	0x10,	0xa,	0x8,
+	0x10,	0xc,	0x8,
+	0x10,	0xe,	0x8,
+	0x10,	0x10,	0x8,
+	0xe,	0x10,	0x8,
+	0xc,	0x10,	0x8,
+	0xa,	0x10,	0x8,
+	0x8,	0x10,	0x8,
+	0x8,	0x10,	0xa,
+	0x8,	0x10,	0xc,
+	0x8,	0x10,	0xe,
+	0x8,	0x10,	0x10,
+	0x8,	0xe,	0x10,
+	0x8,	0xc,	0x10,
+	0x8,	0xa,	0x10,
+	0xb,	0xb,	0x10,
+	0xc,	0xb,	0x10,
+	0xd,	0xb,	0x10,
+	0xf,	0xb,	0x10,
+	0x10,	0xb,	0x10,
+	0x10,	0xb,	0xf,
+	0x10,	0xb,	0xd,
+	0x10,	0xb,	0xc,
+	0x10,	0xb,	0xb,
+	0x10,	0xc,	0xb,
+	0x10,	0xd,	0xb,
+	0x10,	0xf,	0xb,
+	0x10,	0x10,	0xb,
+	0xf,	0x10,	0xb,
+	0xd,	0x10,	0xb,
+	0xc,	0x10,	0xb,
+	0xb,	0x10,	0xb,
+	0xb,	0x10,	0xc,
+	0xb,	0x10,	0xd,
+	0xb,	0x10,	0xf,
+	0xb,	0x10,	0x10,
+	0xb,	0xf,	0x10,
+	0xb,	0xd,	0x10,
+	0xb,	0xc,	0x10,
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x0,
+	0x0,	0x0,	0x0
+};
+
+unsigned char AC[21] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 
+    0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 
+    0x0C, 0x00, 0x0F, 0x08, 0x00};
+
+static int scanPCI(int start_slt);
+static int PCIVendor(int);
+#ifdef DEBUG
+static void printslots(void);
+#endif
+extern void puthex(unsigned long);
+extern void puts(const char *);
+static void unlockS3(void);
+
+static void inline
+outw(int port, unsigned short val)
+{
+	outb(port, val >> 8);
+	outb(port+1, val);
+}
+ 
+#define PPC_601 1
+
+int
+vga_init(unsigned char *ISA_mem)
+{
+	int slot;
+	struct VgaRegs *VgaTextRegs;
+#if 0
+	if ((_get_PVR()>>16) == PPC_601) {
+		return(old_vga_init(ISA_mem));
+	}
+#endif
+	
+	/* See if VGA already in TEXT mode - exit if so! */
+	outb(0x3CE, 0x06);
+	if ((inb(0x3CF) & 0x01) == 0){
+		puts("VGA already in text mode\n");
+		return 0;
+	}
+
+	/* If no VGA responding in text mode, then we have some work to do...
+	 */
+	slot = -1;
+	while((slot = scanPCI(slot)) > -1) { /* find video card in use  */
+		unlockVideo(slot);           /* enable I/O to card      */
+		VgaTextRegs = GenVgaTextRegs;
+	
+		switch (PCIVendor(slot)) {
+		default:
+			break;
+		case(S3Vendor):
+			unlockS3();
+			VgaTextRegs = S3TextRegs;
+			break;
+	
+		case(CirrusVendor):
+			outw(0x3C4, 0x0612);       /* unlock ext regs */
+			outw(0x3C4, 0x0700);       /* reset ext sequence mode */
+			break;
+	
+		case(ParadiseVendor):                 /* IBM Portable 850 */
+			outw(0x3ce, 0x0f05);      /* unlock pardise registers */
+			outw(0x3c4, 0x0648);
+			outw(0x3d4, 0x2985);
+			outw(0x3d4, 0x34a6);
+			outb(0x3ce, 0x0b);       /* disable linear addressing */
+			outb(0x3cf, inb(0x3cf) & ~0x30);
+			outw(0x3c4, 0x1400);
+			outb(0x3ce, 0x0e);       /* disable 256 color mode */
+			outb(0x3cf, inb(0x3cf) & ~0x01);
+			outb(0xd00, 0xff);       /* enable auto-centering */
+			if (!(inb(0xd01) & 0x03)) {
+				outb(0x3d4, 0x33);
+				outb(0x3d5, inb(0x3d5) & ~0x90);
+				outb(0x3d4, 0x32);
+				outb(0x3d5, inb(0x3d5) | 0x04);
+				outw(0x3d4, 0x0250);
+				outw(0x3d4, 0x07ba);
+				outw(0x3d4, 0x0900);
+				outw(0x3d4, 0x15e7);
+				outw(0x3d4, 0x2a95);
+			}
+			outw(0x3d4, 0x34a0);
+			break;
+	
+	#if 0 /* Untested - probably doesn't work */
+		case(MatroxVendor):
+		case(DiamondVendor):
+			puts("VGA Chip Vendor ID: ");
+			puthex(PCIVendor(slot));
+			puts("\n");
+			mdelay(1000);
+	#endif
+		};
+	
+		outw(0x3C4, 0x0120);           /* disable video              */
+		setTextRegs(VgaTextRegs);      /* initial register setup     */
+		setTextCLUT(0);                /* load color lookup table    */
+		loadFont(ISA_mem);             /* load font                  */
+		setTextRegs(VgaTextRegs);      /* reload registers           */
+		outw(0x3C4, 0x0100);           /* re-enable video            */
+		clearVideoMemory();
+	
+		if (PCIVendor(slot) == S3Vendor) {
+			outb(0x3c2, 0x63);                  /* MISC */
+		} /* endif */
+	
+	#ifdef DEBUG
+		printslots();
+		mdelay(5000);
+	#endif
+	
+		mdelay(1000);	/* give time for the video monitor to come up */
+        }
+	return (1);  /* 'CRT' I/O supported */
+}
+
+/*
+ * Write to VGA Attribute registers.  
+ */
+void
+writeAttr(unsigned char index, unsigned char data, unsigned char videoOn)
+{
+	unsigned char v;
+	v = inb(0x3da);   /* reset attr. address toggle */
+	if (videoOn)
+		outb(0x3c0, (index & 0x1F) | 0x20);
+	else
+		outb(0x3c0, (index & 0x1F));
+	outb(0x3c0, data);
+}
+
+void
+setTextRegs(struct VgaRegs *svp)
+{
+	int i;
+
+	/*
+	 *  saved settings
+	 */ 
+	while( svp->io_port != ENDMK ) {
+		outb(svp->io_port,   svp->io_index);
+		outb(svp->io_port+1, svp->io_value);
+		svp++; 
+	}
+
+	outb(0x3c2, 0x67);  /* MISC */
+	outb(0x3c6, 0xff);  /* MASK */
+
+	for ( i = 0; i < 0x10; i++)
+		writeAttr(i, AC[i], 0);  /* pallete */ 
+	writeAttr(0x10, 0x0c, 0);    /* text mode */
+	writeAttr(0x11, 0x00, 0);    /* overscan color (border) */
+	writeAttr(0x12, 0x0f, 0);    /* plane enable */
+	writeAttr(0x13, 0x08, 0);    /* pixel panning */
+	writeAttr(0x14, 0x00, 1);    /* color select; video on  */
+}
+
+void
+setTextCLUT(int shift)
+{
+	int i;
+
+	outb(0x3C6, 0xFF); 
+	i = inb(0x3C7);
+	outb(0x3C8, 0); 
+	i = inb(0x3C7);
+
+	for ( i = 0; i < 256; i++) {
+		outb(0x3C9, TextCLUT[i].r << shift);
+		outb(0x3C9, TextCLUT[i].g << shift);
+		outb(0x3C9, TextCLUT[i].b << shift);
+	}
+}
+
+void
+loadFont(unsigned char *ISA_mem)
+{
+	int i, j;
+	unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
+    
+	outb(0x3C2, 0x67);
+	/* 
+	 * Load font 
+	 */
+	i = inb(0x3DA);  /* Reset Attr toggle */
+
+	outb(0x3C0,0x30); 
+	outb(0x3C0, 0x01);      /* graphics mode */
+
+	outw(0x3C4, 0x0001);    /* reset sequencer */
+	outw(0x3C4, 0x0204);    /* write to plane 2 */
+	outw(0x3C4, 0x0406);    /* enable plane graphics */
+	outw(0x3C4, 0x0003);    /* reset sequencer */
+	outw(0x3CE, 0x0402);    /* read plane 2 */
+	outw(0x3CE, 0x0500);    /* write mode 0, read mode 0 */
+	outw(0x3CE, 0x0605);    /* set graphics mode */
+
+	for (i = 0;  i < sizeof(font);  i += 16) {
+		for (j = 0;  j < 16;  j++) {
+			__asm__ volatile("eieio");
+			font_page[(2*i)+j] = font[i+j];
+		}
+	}
+}
+
+static void
+unlockS3(void)
+{
+        int s3_device_id;
+	outw(0x3d4, 0x3848);
+	outw(0x3d4, 0x39a5);
+	outb(0x3d4, 0x2d);
+	s3_device_id = inb(0x3d5) << 8;
+	outb(0x3d4, 0x2e);
+	s3_device_id |= inb(0x3d5);
+
+	if (s3_device_id != 0x8812) {
+		/* From the S3 manual */
+		outb(0x46E8, 0x10);  /* Put into setup mode */
+		outb(0x3C3, 0x10);
+		outb(0x102, 0x01);   /* Enable registers */
+		outb(0x46E8, 0x08);  /* Enable video */
+		outb(0x3C3, 0x08);
+		outb(0x4AE8, 0x00);
+
+#if 0
+		outb(0x42E8, 0x80);  /* Reset graphics engine? */
+#endif
+
+		outb(0x3D4, 0x38);  /* Unlock all registers */
+		outb(0x3D5, 0x48);
+		outb(0x3D4, 0x39);
+		outb(0x3D5, 0xA5);
+		outb(0x3D4, 0x40);
+		outb(0x3D5, inb(0x3D5)|0x01);
+		outb(0x3D4, 0x33);
+		outb(0x3D5, inb(0x3D5)&~0x52);
+		outb(0x3D4, 0x35);
+		outb(0x3D5, inb(0x3D5)&~0x30);
+		outb(0x3D4, 0x3A);
+		outb(0x3D5, 0x00);
+		outb(0x3D4, 0x53);
+		outb(0x3D5, 0x00);
+		outb(0x3D4, 0x31);
+		outb(0x3D5, inb(0x3D5)&~0x4B);
+		outb(0x3D4, 0x58);
+
+		outb(0x3D5, 0);
+
+		outb(0x3D4, 0x54);
+		outb(0x3D5, 0x38);
+		outb(0x3D4, 0x60);
+		outb(0x3D5, 0x07);
+		outb(0x3D4, 0x61);
+		outb(0x3D5, 0x80);
+		outb(0x3D4, 0x62);
+		outb(0x3D5, 0xA1);
+		outb(0x3D4, 0x69);  /* High order bits for cursor address */
+		outb(0x3D5, 0);
+
+		outb(0x3D4, 0x32);
+		outb(0x3D5, inb(0x3D5)&~0x10);
+	} else {
+                outw(0x3c4, 0x0806);            /* IBM Portable 860 */
+                outw(0x3c4, 0x1041);
+                outw(0x3c4, 0x1128);
+                outw(0x3d4, 0x4000);
+                outw(0x3d4, 0x3100);
+                outw(0x3d4, 0x3a05);
+                outw(0x3d4, 0x6688);
+                outw(0x3d4, 0x5800);            /* disable linear addressing */
+                outw(0x3d4, 0x4500);            /* disable H/W cursor */
+                outw(0x3c4, 0x5410);            /* enable auto-centering */
+                outw(0x3c4, 0x561f);
+                outw(0x3c4, 0x1b80);            /* lock DCLK selection */
+                outw(0x3d4, 0x3900);            /* lock S3 registers */
+                outw(0x3d4, 0x3800);
+	} /* endif */
+}
+
+/*
+ * cursor() sets an offset (0-1999) into the 80x25 text area   
+ */
+void
+cursor(int x, int y)
+{
+	int pos = (y*cols)+x;
+	outb(0x3D4, 14);
+	outb(0x3D5, pos >> 8);
+	outb(0x3D4, 15);
+	outb(0x3D5, pos);
+}
+
+void
+clearVideoMemory()
+{
+	int i, j;
+	for (i = 0;  i < lines;  i++) {
+		for (j = 0;  j < cols;  j++) {
+			vidmem[((i*cols)+j)*2] = 0x20;	/* fill with space character */
+			vidmem[((i*cols)+j)*2+1] = 0x07;  /* set bg & fg attributes */
+		}
+	}
+}
+
+/* ============ */
+
+
+#define NSLOTS 8
+#define NPCIREGS  5
+
+
+/* 
+ should use devfunc number/indirect method to be totally safe on 
+ all machines, this works for now on 3 slot Moto boxes 
+*/
+
+struct PCI_ConfigInfo {
+  unsigned long * config_addr;
+  unsigned long regs[NPCIREGS];  
+} PCI_slots [NSLOTS] = {
+
+    { (unsigned long *)0x80808000, 0xDEADBEEF },   /* onboard */
+    { (unsigned long *)0x80800800, 0xDEADBEEF },   /* onboard */
+    { (unsigned long *)0x80801000, 0xDEADBEEF },   /* onboard */
+    { (unsigned long *)0x80802000, 0xDEADBEEF },   /* onboard */
+    { (unsigned long *)0x80804000, 0xDEADBEEF },   /* onboard */
+    { (unsigned long *)0x80810000, 0xDEADBEEF },   /* slot A/1 */
+    { (unsigned long *)0x80820000, 0xDEADBEEF },   /* slot B/2 */
+    { (unsigned long *)0x80840000, 0xDEADBEEF }    /* slot C/3 */
+};
+
+
+
+/*
+ * The following code modifies the PCI Command register
+ * to enable memory and I/O accesses.    
+ */ 
+void
+unlockVideo(int slot)        
+{
+       volatile unsigned char * ppci;
+
+        ppci =  (unsigned char * )PCI_slots[slot].config_addr;
+	ppci[4] = 0x0003;         /* enable memory and I/O accesses */
+	ppci[0x10] = 0x00000;     /* turn off memory mapping */
+	ppci[0x11] = 0x00000;     /* mem_base = 0 */
+	ppci[0x12] = 0x00000;
+	ppci[0x13] = 0x00000;
+	__asm__ volatile("eieio");
+
+	outb(0x3d4, 0x11);
+	outb(0x3d5, 0x0e);   /* unlock CR0-CR7 */
+}
+
+long
+SwapBytes(long lv)   /* turn little endian into big indian long */
+{
+    long t;
+    t  = (lv&0x000000FF) << 24;
+    t |= (lv&0x0000FF00) << 8;
+    t |= (lv&0x00FF0000) >> 8;
+    t |= (lv&0xFF000000) >> 24;
+    return(t);
+}
+
+
+#define DEVID   0
+#define CMD     1
+#define CLASS   2
+#define MEMBASE 4
+
+int
+scanPCI(int start_slt)
+{
+	int slt, r;
+	struct PCI_ConfigInfo *pslot;
+	int theSlot = -1;
+	int highVgaSlot = 0;
+
+	for ( slt = start_slt + 1; slt < NSLOTS; slt++) {
+		pslot = &PCI_slots[slt];
+		for ( r = 0; r < NPCIREGS; r++) {
+			pslot->regs[r] = SwapBytes ( pslot->config_addr[r] );
+		}
+		/* card in slot ? */
+		if ( pslot->regs[DEVID] != 0xFFFFFFFF ) {     
+			/* VGA ? */
+			if ( ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) || 
+			     ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x00010000)) {
+				highVgaSlot = slt;
+				/* did firmware enable it ? */
+				if ( (pslot->regs[CMD] & 0x03) ) { 
+					theSlot = slt;
+					break;
+				}
+			}
+		}
+	}
+
+	return ( theSlot );
+}
+
+/* return Vendor ID of card in the slot */
+static
+int PCIVendor(int slotnum) {
+ struct PCI_ConfigInfo *pslot;
+
+ pslot = &PCI_slots[slotnum];
+
+return (pslot->regs[DEVID] & 0xFFFF);
+}
+
+#ifdef DEBUG
+static
+void printslots(void) 
+{
+	int i;
+#if 0
+	struct PCI_ConfigInfo *pslot;
+#endif
+	for(i=0; i < NSLOTS; i++) {
+#if 0
+		pslot = &PCI_slots[i];
+		printf("Slot: %d, Addr: %x, Vendor: %08x, Class: %08x\n",
+		       i, pslot->config_addr, pslot->regs[0], pslot->regs[2]);
+#else
+		puts("PCI Slot number: "); puthex(i);
+		puts(" Vendor ID: "); 
+		puthex(PCIVendor(i)); puts("\n");
+#endif
+	}
+}
+#endif /* DEBUG */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/size linux/arch/ppc/boot/size
--- v2.4.4/linux/arch/ppc/boot/size	Wed Sep 30 10:14:16 1998
+++ linux/arch/ppc/boot/size	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux | awk '{print $3}'`
-echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/tree/Makefile linux/arch/ppc/boot/tree/Makefile
--- v2.4.4/linux/arch/ppc/boot/tree/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/tree/Makefile	Thu May 24 15:02:07 2001
@@ -0,0 +1,65 @@
+# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch
+#
+#
+#    Module name: Makefile
+#
+#    Description:
+#      Makefile for the IBM "tree" evaluation board Linux kernel
+#      boot loaders.
+#
+#
+#    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+# 
+#    PPC-405 modification
+#    	Copyright 2000-2001 MontaVista Software Inc.
+#    	Author: MontaVista Software, Inc.
+#          	frank_rowand@mvista.com or source@mvista.com
+#  	   	debbie_chu@mvista.com
+# 
+
+HOSTCFLAGS = -O -I$(TOPDIR)/include
+
+CC      = $(CROSS_COMPILE)gcc
+LD      = $(CROSS_COMPILE)ld
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CROSS_COMPILE)objdump
+
+GZIP	= gzip -vf9
+RM	= rm -f
+MKEVIMG	= ../utils/mkevimg -l
+MKIRIMG	= ../utils/mkirimg
+LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic
+
+OBJS	= ../common/crt0.o main.o misc.o irSect.o ../common/string.o \
+		../common/misc-common.o
+LIBS	= ../lib/zlib.a
+
+treeboot: $(OBJS) $(LIBS) ld.script
+	$(LD) -o $@ $(LD_ARGS) $(OBJS) $(LIBS)
+
+zImage:	vmlinux.img
+
+zImage.initrd: vmlinux.initrd.img
+
+treeboot.image: treeboot
+	$(OBJCOPY) --add-section=image=../images/vmlinux.gz treeboot $@
+
+treeboot.initrd: treeboot.image ramdisk.image.gz
+	$(OBJCOPY) --add-section=initrd=ramdisk.image.gz treeboot.image $@
+
+vmlinux.img: treeboot.image
+	$(OBJDUMP) --syms treeboot.image | grep irSectStart > irSectStart.txt
+	$(MKIRIMG) treeboot.image treeboot.image.out irSectStart.txt
+	$(MKEVIMG) treeboot.image.out ../images/vmlinux.tree.img
+	$(RM) treeboot.image treeboot.image.out irSectStart.txt
+
+vmlinux.initrd.img: treeboot.initrd
+	$(OBJDUMP) --all-headers treeboot.initrd | grep irSectStart > irSectStart.txt
+	$(MKIRIMG) treeboot.initrd treeboot.initrd.out irSectStart.txt
+	$(MKEVIMG) treeboot.initrd.out ../images/vmlinux.tree.initrd.img
+	$(RM) treeboot.initrd treeboot.initrd.out irSectStart.txt
+
+clean:
+	rm -f treeboot treeboot.image treeboot.initrd irSectStart.txt vmlinux.*
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/tree/irSect.c linux/arch/ppc/boot/tree/irSect.c
--- v2.4.4/linux/arch/ppc/boot/tree/irSect.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/tree/irSect.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,39 @@
+/*
+ * BK Id: SCCS/s.irSect.c 1.6 05/18/01 15:17:22 cort
+ */
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: irSect.c
+ *
+ *    Description:
+ *      Defines variables to hold the absolute starting address and size
+ *      of the Linux kernel "image" and the initial RAM disk "initrd"
+ *      sections within the boot loader.
+ *
+ */
+
+#include "irSect.h"
+
+
+/*
+ * The order of globals below must not change. If more globals are added,
+ * you must change the script 'mkirimg' accordingly.
+ *
+ */
+
+/* 
+ * irSectStart must be at beginning of file 
+ */
+unsigned int irSectStart = 0xdeadbeaf;
+
+unsigned int imageSect_start	= 0;
+unsigned int imageSect_size	= 0;
+unsigned int initrdSect_start	= 0;
+unsigned int initrdSect_size	= 0;
+
+/* 
+ * irSectEnd must be at end of file 
+ */
+unsigned int irSectEnd   = 0xdeadbeaf;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/tree/irSect.h linux/arch/ppc/boot/tree/irSect.h
--- v2.4.4/linux/arch/ppc/boot/tree/irSect.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/tree/irSect.h	Thu May 24 15:02:07 2001
@@ -0,0 +1,35 @@
+/*
+ * BK Id: SCCS/s.irSect.h 1.6 05/18/01 15:17:22 cort
+ */
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: irSect.h
+ *    
+ *    Description:
+ *      Defines variables to hold the absolute starting address and size
+ *      of the Linux kernel "image" and the initial RAM disk "initrd"   
+ *      sections within the boot loader.
+ *      
+ */
+
+#ifndef __IRSECT_H__
+#define __IRSECT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned int imageSect_start;
+extern unsigned int imageSect_size;
+
+extern unsigned int initrdSect_start;
+extern unsigned int initrdSect_size;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IRSECT_H__ */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/tree/ld.script linux/arch/ppc/boot/tree/ld.script
--- v2.4.4/linux/arch/ppc/boot/tree/ld.script	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/tree/ld.script	Thu May 24 15:02:07 2001
@@ -0,0 +1,68 @@
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	} =0
+  .plt : { *(.plt) }
+  .text      :
+  {
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    *(.got1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+  _etext = .;
+  PROVIDE (etext = .);
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.got.plt) *(.got)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/tree/main.c linux/arch/ppc/boot/tree/main.c
--- v2.4.4/linux/arch/ppc/boot/tree/main.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/tree/main.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,248 @@
+/*
+ * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch
+ */
+/*
+ *    Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
+ *      Initial Power Macintosh COFF version.
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *      Modifications for an ELF-based IBM evaluation board version.
+ *    Copyright 2000-2001 MontaVista Software Inc.
+ *	PPC405GP modifications
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *
+ *    Module name: main.c
+ *
+ *    Description:
+ *      This module does most of the real work for the boot loader. It
+ *      checks the variables holding the absolute start address and size
+ *      of the Linux kernel "image" and initial RAM disk "initrd" sections
+ *      and if they are present, moves them to their "proper" locations.
+ *
+ *      For the Linux kernel, "proper" is physical address 0x00000000.
+ *      For the RAM disk, "proper" is the image's size below the top
+ *      of physical memory. The Linux kernel may be in either raw
+ *      binary form or compressed with GNU zip (aka gzip).
+ *
+ *    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/ppc4xx.h>
+
+#include "nonstdio.h"
+#include "irSect.h"
+#if defined(CONFIG_SERIAL_CONSOLE)
+#include "ns16550.h"
+#endif /* CONFIG_SERIAL_CONSOLE */
+
+
+/* Preprocessor Defines */
+
+/*
+ * Location of the IBM boot ROM function pointer address for retrieving
+ * the board information structure.
+ */
+
+#define	BOARD_INFO_VECTOR	0xFFFE0B50
+
+/* 
+ * Warning: the board_info doesn't contain valid data until get_board_info() 
+ * 	    gets called in start().
+ */
+#define RAM_SIZE        board_info.bi_memsize 
+
+#define	RAM_PBASE	0x00000000
+#define	RAM_PEND	(RAM_PBASE + RAM_SIZE)
+
+#define	RAM_VBASE	0xC0000000
+#define	RAM_VEND	(RAM_VBASE + RAM_SIZE)
+
+#define	RAM_START	RAM_PBASE
+#define	RAM_END		RAM_PEND
+#define	RAM_FREE	(imageSect_start + imageSect_size + initrdSect_size)
+
+#define	PROG_START	RAM_START
+
+
+/* Function Macros */
+
+#define	ALIGN_UP(x, align)	(((x) + ((align) - 1)) & ~((align) - 1))
+
+#define stringify(s)    tostring(s)
+#define tostring(s)     #s
+
+#define mtdcr(rn, v)    asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v))
+#define mfdcr(rn)       ({unsigned int rval; \
+                        asm volatile("mfdcr %0," stringify(rn) \
+                                     : "=r" (rval)); rval;})
+#define DCRN_MALCR      0x180   /* MAL Configuration                          */
+#define   MALCR_SR      0x80000000      /* Software Reset                     */
+
+/* Global Variables */
+
+/* Needed by zalloc and zfree for allocating memory */
+
+char *avail_ram;	/* Indicates start of RAM available for heap */
+char *end_avail;	/* Indicates end of RAM available for heap */
+
+bd_t	board_info;
+
+/*
+ * XXX - Until either the IBM boot ROM provides a way of passing arguments to
+ *       the program it launches or until I/O is working in the boot loader,
+ *       this is a good spot to pass in command line arguments to the kernel
+ *       (e.g. console=tty0).
+ */
+
+
+/*
+** The bootrom may change bootrom_cmdline to point to a buffer in the
+** bootrom.
+*/
+char *bootrom_cmdline = "";
+char treeboot_bootrom_cmdline[512];
+
+#ifdef CONFIG_CMDLINE
+char *cmdline = CONFIG_CMDLINE;
+#else
+char *cmdline = "";
+#endif
+
+/* Function Prototypes */
+
+extern void *zalloc(void *x, unsigned items, unsigned size);
+
+/* serial I/O functions.
+ * These should have generic names, although this is similar to 16550....
+ */
+static volatile unsigned char *uart0_lsr = (unsigned char *)0xef600305;
+static volatile unsigned char *uart0_xcvr = (unsigned char *)0xef600300;
+
+void
+serial_putc(void *unused, unsigned char c)
+{
+ while ((*uart0_lsr & LSR_THRE) == 0);
+ *uart0_xcvr = c;
+}
+
+unsigned char
+serial_getc(void *unused)
+{
+ while ((*uart0_lsr & LSR_DR) == 0);
+ return (*uart0_xcvr);
+}
+
+int
+serial_tstc(void *unused)
+{
+ return ((*uart0_lsr & LSR_DR) != 0);
+}
+
+
+void start(void)
+{
+    void *options;
+    int ns, oh, i;
+    unsigned long sa, len;
+    void *dst;
+    unsigned char *im;
+    unsigned long initrd_start, initrd_size;
+    bd_t *(*get_board_info)(void) = 
+	    (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
+    bd_t *bip = NULL;
+    volatile unsigned long *em0mr0 = (long *)0xEF600800;    /* ftr fixup */
+
+
+
+#if defined(CONFIG_WALNUT)
+    /* turn off ethernet */
+    /* This is to fix a problem with early walnut bootrom. */
+
+    mtdcr(DCRN_MALCR, MALCR_SR);                /* 1st reset MAL */
+
+    while (mfdcr(DCRN_MALCR) & MALCR_SR) {};    /* wait for the reset */
+
+    *em0mr0 = 0x20000000;                       /* then reset EMAC */
+#endif
+
+
+#if 0
+    /* ftr revisit - remove printf()s */
+
+    printf("\n\nbootrom_cmdline = >%s<\n\n", bootrom_cmdline);
+    if (*bootrom_cmdline != '\0') {
+	printf("bootrom_cmdline != NULL, copying it into cmdline\n\n");
+	*treeboot_bootrom_cmdline = '\0';
+	strcat(treeboot_bootrom_cmdline, bootrom_cmdline);
+	cmdline = treeboot_bootrom_cmdline;
+    }
+#endif
+
+
+    if ((bip = get_board_info()) != NULL)
+	    memcpy(&board_info, bip, sizeof(bd_t));
+
+    /* Init RAM disk (initrd) section */
+
+    if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) {
+        initrd_start = (RAM_END - initrd_size) & ~0xFFF;
+
+	_printk("Initial RAM disk at 0x%08x (%u bytes)\n",
+	       initrd_start, initrd_size);
+
+	memcpy((char *)initrd_start,
+	       (char *)(initrdSect_start),
+	       initrdSect_size);
+
+	end_avail = (char *)initrd_start;
+    } else {
+	initrd_start = initrd_size = 0;
+	end_avail = (char *)RAM_END;
+    }
+
+    /* Linux kernel image section */
+	
+    im = (unsigned char *)(imageSect_start);
+    len = imageSect_size;
+    dst = (void *)PROG_START;
+
+    /* Check for the gzip archive magic numbers */
+
+    if (im[0] == 0x1f && im[1] == 0x8b) {
+
+        /* The gunzip routine needs everything nice and aligned */
+
+	void *cp = (void *)ALIGN_UP(RAM_FREE, 8);
+	avail_ram = (void *)(cp + ALIGN_UP(len, 8));	/* used by zalloc() */
+	memcpy(cp, im, len);
+
+	/* I'm not sure what the 0x200000 parameter is for, but it works. */
+	/* It tells gzip the end of the area you wish to reserve, and it
+	 * can use data past that point....unfortunately, this value
+	 * isn't big enough (luck ran out).  -- Dan
+	 */
+
+	gunzip(dst, 0x400000, cp, (int *)&len);
+    } else {
+	memmove(dst, im, len);
+    }
+
+
+    flush_cache(dst, len);
+
+    sa = (unsigned long)dst;
+
+    (*(void (*)())sa)(&board_info,
+		      initrd_start,
+		      initrd_start + initrd_size,
+		      cmdline,
+		      cmdline + strlen(cmdline));
+
+    pause();
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/tree/misc.S linux/arch/ppc/boot/tree/misc.S
--- v2.4.4/linux/arch/ppc/boot/tree/misc.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/tree/misc.S	Thu May 24 15:02:07 2001
@@ -0,0 +1,43 @@
+/*
+ * BK Id: SCCS/s.misc.S 1.7 05/18/01 06:20:29 patch
+ */
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 "../../kernel/ppc_asm.tmpl"
+
+	.text
+
+/*
+ * Flush the dcache and invalidate the icache for a range of addresses.
+ *
+ * flush_cache(addr, len)
+ */
+	.global	flush_cache
+flush_cache:
+	mfpvr	r5			# Get processor version register
+	extrwi	r5,r5,16,0		# Get the version bits
+	cmpwi	cr0,r5,0x0020		# Is this a 403-based processor?
+	beq	1f			# Yes, it is
+	li	r5,32			# It is not a 403, set to 32 bytes
+	addi	r4,r4,32-1		# len += line_size - 1
+	srwi.	r4,r4,5			# Convert from bytes to lines
+	b	2f
+1:	li	r5,16			# It is a 403, set to 16 bytes
+	addi	r4,r4,16-1		# len += line_size - 1
+	srwi.	r4,r4,4			# Convert from bytes to lines
+2:	mtctr	r4			# Set-up the counter register
+	beqlr				# If it is 0, we are done
+3:	dcbf	r0,r3			# Flush and invalidate the data line
+	icbi	r0,r3			# Invalidate the instruction line
+	add	r3,r3,r5		# Move to the next line
+	bdnz	3b			# Are we done yet?
+	sync
+	isync
+	blr				# Return to the caller
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/Makefile linux/arch/ppc/boot/utils/Makefile
--- v2.4.4/linux/arch/ppc/boot/utils/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/Makefile	Thu May 24 15:02:07 2001
@@ -0,0 +1,19 @@
+#
+# arch/ppc/boot/utils/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+
+HOSTCFLAGS += -I$(TOPDIR)/arch/$(ARCH)/boot/include
+
+# Simple programs with 1 file and no extra CFLAGS
+UTILS = addnote hack-coff mkprep mksimage mknote piggyback mkpmon mkbugboot
+
+$(UTILS):
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $@.c
+
+clean:
+	rm -f $(UTILS)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/addnote.c linux/arch/ppc/boot/utils/addnote.c
--- v2.4.4/linux/arch/ppc/boot/utils/addnote.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/addnote.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,177 @@
+/*
+ * BK Id: SCCS/s.addnote.c 1.7 05/18/01 15:17:23 cort
+ */
+/*
+ * Program to hack in a PT_NOTE program header entry in an ELF file.
+ * This is needed for OF on RS/6000s to load an image correctly.
+ * Note that OF needs a program header entry for the note, not an
+ * ELF section.
+ *
+ * Copyright 2000 Paul Mackerras.
+ *
+ * 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.
+ *
+ * Usage: addnote zImage
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+char arch[] = "PowerPC";
+
+#define N_DESCR	6
+unsigned int descr[N_DESCR] = {
+#if 1
+	/* values for IBM RS/6000 machines */
+	0xffffffff,		/* real-mode = true */
+	0x00c00000,		/* real-base, i.e. where we expect OF to be */
+	0xffffffff,		/* real-size */
+	0xffffffff,		/* virt-base */
+	0xffffffff,		/* virt-size */
+	0x4000,			/* load-base */
+#else
+	/* values for longtrail CHRP */
+	0,			/* real-mode = false */
+	0xffffffff,		/* real-base */
+	0xffffffff,		/* real-size */
+	0xffffffff,		/* virt-base */
+	0xffffffff,		/* virt-size */
+	0x00600000,		/* load-base */
+#endif
+};
+
+unsigned char buf[512];
+
+#define GET_16BE(off)	((buf[off] << 8) + (buf[(off)+1]))
+#define GET_32BE(off)	((GET_16BE(off) << 16) + GET_16BE((off)+2))
+
+#define PUT_16BE(off, v)	(buf[off] = ((v) >> 8) & 0xff, \
+				 buf[(off) + 1] = (v) & 0xff)
+#define PUT_32BE(off, v)	(PUT_16BE((off), (v) >> 16), \
+				 PUT_16BE((off) + 2, (v)))
+
+/* Structure of an ELF file */
+#define E_IDENT		0	/* ELF header */
+#define	E_PHOFF		28
+#define E_PHENTSIZE	42
+#define E_PHNUM		44
+#define E_HSIZE		52	/* size of ELF header */
+
+#define EI_MAGIC	0	/* offsets in E_IDENT area */
+#define EI_CLASS	4
+#define EI_DATA		5
+
+#define PH_TYPE		0	/* ELF program header */
+#define PH_OFFSET	4
+#define PH_FILESZ	16
+#define PH_HSIZE	32	/* size of program header */
+
+#define PT_NOTE		4	/* Program header type = note */
+
+#define ELFCLASS32	1
+#define ELFDATA2MSB	2
+
+unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
+
+int main(int ac, char **av)
+{
+	int fd, n, i;
+	int ph, ps, np;
+	int nnote, ns;
+
+	if (ac != 2) {
+		fprintf(stderr, "Usage: %s elf-file\n", av[0]);
+		exit(1);
+	}
+	fd = open(av[1], O_RDWR);
+	if (fd < 0) {
+		perror(av[1]);
+		exit(1);
+	}
+
+	nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+
+	n = read(fd, buf, sizeof(buf));
+	if (n < 0) {
+		perror("read");
+		exit(1);
+	}
+
+	if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
+		goto notelf;
+
+	if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
+	    || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
+		fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
+			av[1]);
+		exit(1);
+	}
+
+	ph = GET_32BE(E_PHOFF);
+	ps = GET_16BE(E_PHENTSIZE);
+	np = GET_16BE(E_PHNUM);
+	if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
+		goto notelf;
+	if (ph + (np + 1) * ps + nnote > n)
+		goto nospace;
+
+	for (i = 0; i < np; ++i) {
+		if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
+			fprintf(stderr, "%s already has a note entry\n",
+				av[1]);
+			exit(0);
+		}
+		ph += ps;
+	}
+
+	/* XXX check that the area we want to use is all zeroes */
+	for (i = 0; i < ps + nnote; ++i)
+		if (buf[ph + i] != 0)
+			goto nospace;
+
+	/* fill in the program header entry */
+	ns = ph + ps;
+	PUT_32BE(ph + PH_TYPE, PT_NOTE);
+	PUT_32BE(ph + PH_OFFSET, ns);
+	PUT_32BE(ph + PH_FILESZ, nnote);
+
+	/* fill in the note area we point to */
+	/* XXX we should probably make this a proper section */
+	PUT_32BE(ns, strlen(arch) + 1);
+	PUT_32BE(ns + 4, N_DESCR * 4);
+	PUT_32BE(ns + 8, 0x1275);
+	strcpy(&buf[ns + 12], arch);
+	ns += 12 + strlen(arch) + 1;
+	for (i = 0; i < N_DESCR; ++i)
+		PUT_32BE(ns + i * 4, descr[i]);
+
+	/* Update the number of program headers */
+	PUT_16BE(E_PHNUM, np + 1);
+
+	/* write back */
+	lseek(fd, (long) 0, SEEK_SET);
+	i = write(fd, buf, n);
+	if (i < 0) {
+		perror("write");
+		exit(1);
+	}
+	if (i < n) {
+		fprintf(stderr, "%s: write truncated\n", av[1]);
+		exit(1);
+	}
+
+	exit(0);
+
+ notelf:
+	fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+	exit(1);
+
+ nospace:
+	fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
+		av[0]);
+	exit(1);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/elf.pl linux/arch/ppc/boot/utils/elf.pl
--- v2.4.4/linux/arch/ppc/boot/utils/elf.pl	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/elf.pl	Thu May 24 15:02:07 2001
@@ -0,0 +1,33 @@
+#
+# ELF header field numbers
+#
+
+$e_ident	=  0;	# Identification bytes / magic number
+$e_type		=  1;	# ELF file type
+$e_machine	=  2;	# Target machine type
+$e_version	=  3;	# File version
+$e_entry	=  4;	# Start address
+$e_phoff	=  5;	# Program header file offset
+$e_shoff	=  6;	# Section header file offset
+$e_flags	=  7;	# File flags
+$e_ehsize	=  8;	# Size of ELF header
+$e_phentsize	=  9;	# Size of program header
+$e_phnum	= 10;	# Number of program header entries
+$e_shentsize	= 11;	# Size of section header
+$e_shnum	= 12;	# Number of section header entries
+$e_shstrndx	= 13;	# Section header table string index
+
+#
+# Section header field numbers
+#
+
+$sh_name	=  0;	# Section name
+$sh_type	=  1;	# Section header type
+$sh_flags	=  2;	# Section header flags
+$sh_addr	=  3;	# Virtual address
+$sh_offset	=  4;	# File offset
+$sh_size	=  5;	# Section size
+$sh_link	=  6;	# Miscellaneous info
+$sh_info	=  7;	# More miscellaneous info
+$sh_addralign	=  8;	# Memory alignment
+$sh_entsize	=  9;	# Entry size if this is a table
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/hack-coff.c linux/arch/ppc/boot/utils/hack-coff.c
--- v2.4.4/linux/arch/ppc/boot/utils/hack-coff.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/hack-coff.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,85 @@
+/*
+ * BK Id: SCCS/s.hack-coff.c 1.8 05/18/01 06:20:29 patch
+ */
+/*
+ * hack-coff.c - hack the header of an xcoff file to fill in
+ * a few fields needed by the Open Firmware xcoff loader on
+ * Power Macs but not initialized by objcopy.
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "rs6000.h"
+
+#define AOUT_MAGIC	0x010b
+
+#define get_16be(x)	((((unsigned char *)(x))[0] << 8) \
+			 + ((unsigned char *)(x))[1])
+#define put_16be(x, v)	(((unsigned char *)(x))[0] = (v) >> 8, \
+			 ((unsigned char *)(x))[1] = (v) & 0xff)
+#define get_32be(x)	((((unsigned char *)(x))[0] << 24) \
+			 + (((unsigned char *)(x))[1] << 16) \
+			 + (((unsigned char *)(x))[2] << 8) \
+			 + ((unsigned char *)(x))[3])
+
+int
+main(int ac, char **av)
+{
+    int fd;
+    int i, nsect;
+    int aoutsz;
+    struct external_filehdr fhdr;
+    AOUTHDR aout;
+    struct external_scnhdr shdr;
+
+    if (ac != 2) {
+	fprintf(stderr, "Usage: hack-coff coff-file\n");
+	exit(1);
+    }
+    if ((fd = open(av[1], 2)) == -1) {
+	perror(av[2]);
+	exit(1);
+    }
+    if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
+	goto readerr;
+    i = get_16be(fhdr.f_magic);
+    if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
+	fprintf(stderr, "%s: not an xcoff file\n", av[1]);
+	exit(1);
+    }
+    aoutsz = get_16be(fhdr.f_opthdr);
+    if (read(fd, &aout, aoutsz) != aoutsz)
+	goto readerr;
+    nsect = get_16be(fhdr.f_nscns);
+    for (i = 0; i < nsect; ++i) {
+	if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+	    goto readerr;
+	if (strcmp(shdr.s_name, ".text") == 0) {
+	    put_16be(aout.o_snentry, i+1);
+	    put_16be(aout.o_sntext, i+1);
+	} else if (strcmp(shdr.s_name, ".data") == 0) {
+	    put_16be(aout.o_sndata, i+1);
+	} else if (strcmp(shdr.s_name, ".bss") == 0) {
+	    put_16be(aout.o_snbss, i+1);
+	}
+    }
+    put_16be(aout.magic, AOUT_MAGIC);
+    if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
+	|| write(fd, &aout, aoutsz) != aoutsz) {
+	fprintf(stderr, "%s: write error\n", av[1]);
+	exit(1);
+    }
+    close(fd);
+    exit(0);
+
+readerr:
+    fprintf(stderr, "%s: read error or file too short\n", av[1]);
+    exit(1);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/mkevimg linux/arch/ppc/boot/utils/mkevimg
--- v2.4.4/linux/arch/ppc/boot/utils/mkevimg	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/mkevimg	Thu May 24 15:02:07 2001
@@ -0,0 +1,437 @@
+#!/usr/bin/perl
+
+#
+#    Copyright (c) 1998-1999 TiVo, Inc.
+#    All rights reserved.
+#
+#    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+#      Major syntactic and usability rework.
+#
+#    Module name: mkevimg
+#
+#    Description:
+#      Converts an ELF output file from the linker into the format used by
+#      the IBM evaluation board ROM Monitor to load programs from a host
+#      onto the evaluation board. The ELF file must be an otherwise execut-
+#      able file (with the text and data addresses bound at link time) and
+#      have space reserved after the entry point for the load information
+#      block:
+#
+#      typedef struct boot_block {
+#        unsigned long magic;	        0x0052504F
+#	 unsigned long dest;	        Target address of the image
+#	 unsigned long num_512blocks;   Size, rounded-up, in 512 byte blocks
+#	 unsigned long debug_flag;      Run the debugger or image after load
+#        unsigned long entry_point;	The image address to jump to after load
+#	 unsigned long reserved[3];
+#      } boot_block_t;
+#
+#   
+
+use File::Basename;
+use Getopt::Std;
+
+#
+# usage()
+#
+# Description:
+#   This routine prints out the proper command line usage for this program
+#
+# Input(s):
+#   status - Flag determining what usage information will be printed and what
+#            the exit status of the program will be after the information is
+#            printed.
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   This subroutine does not return.
+#
+
+sub usage {
+  my($status);
+  $status = $_[0];
+
+  printf("Usage: %s [-hlvV] <ELF input file> <Evaluation board output file>\n",
+	$program);
+
+  if ($status != 0) {
+    printf("Try `%s -h' for more information.\n", $program);
+  }
+
+  if ($status != 1) {
+    print("  -h         Print out this message and exit.\n");
+    print("  -l         Linux mode; if present, copy 'image' and 'initrd' sections.\n");
+    print("  -v         Verbose. Print out lots of ELF information.\n");
+    print("  -V         Print out version information and exit.\n");
+  }
+
+  exit($status);
+}
+
+#
+# version()
+#
+# Description:
+#   This routine prints out program version information
+#
+# Input(s):
+#   N/A
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   This subroutine does not return.
+#
+
+sub version {
+  print("mkevimg Version 1.1.0\n");
+  print("Copyright (c) 1998-1999 TiVo, Inc.\n");
+  print("Copyright (c) 1999 Grant Erickson <grant\@lcse.umn.edu>\n");
+
+  exit (0);
+}
+
+#
+# file_check()
+#
+# Description:
+#   This routine checks an input file to ensure that it exists, is a
+#   regular file, and is readable.
+#
+# Input(s):
+#   file - Input file to be checked.
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   0 if the file exists, is a regular file, and is readable, otherwise -1.
+#
+
+sub file_check {
+  my($file);
+  $file = $_[0];
+
+  if (!(-e $file)) {
+    printf("The file \"%s\" does not exist.\n", $file);
+    return (-1);
+  } elsif (!(-f $file)) {
+    printf("The file \"%s\" is not a regular file.\n", $file);
+    return (-1);
+  } elsif (!(-r $file)) {
+    printf("The file \"%s\" is not readable.\n", $file);
+    return (-1);
+  }
+
+  return (0);
+}
+
+#
+# decode_options()
+#
+# Description:
+#   This routine steps through the command-line arguments, parsing out
+#   recognzied options.
+#
+# Input(s):
+#   N/A
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   N/A
+#
+
+sub decode_options {
+
+  if (!getopts("hlvV")) {
+    usage(1);
+  }
+
+  if ($opt_h) {
+    usage(0);
+  }
+
+  if ($opt_l) {
+    $linux = 1;
+  }
+
+  if ($opt_V) {
+    version();
+    exit (0);
+  }
+
+  if ($opt_v) {
+    $verbose = 1;
+  }
+
+  if (!($ifile = shift(@ARGV))) {
+    usage(1);
+  }
+
+  if (!($ofile = shift(@ARGV))) {
+    usage (1);
+  }
+
+  if (file_check($ifile)) {
+    exit(1);
+  }
+
+}
+
+#
+# ELF file and section header field numbers
+#
+
+require '../utils/elf.pl';
+
+#
+# Main program body
+#
+
+{
+  $program = basename($0);
+
+  decode_options();
+
+  open(ELF, "<$ifile") || die "Cannot open input file";
+
+  $ifilesize = (-s $ifile);
+
+  if ($verbose) {
+    print("Output file: $ofile\n");
+    print("Input file: $ifile, $ifilesize bytes.\n");
+  }
+
+  if (read(ELF, $ibuf, $ifilesize) != $ifilesize) {
+    print("Failed to read input file!\n");
+    exit(1);
+  }
+
+  # 
+  # Parse ELF header
+  #
+
+  @eh = unpack("a16n2N5n6", $ibuf);
+
+  #
+  # Make sure this is actually a PowerPC ELF file.
+  #
+
+  if (substr($eh[$e_ident], 0, 4) ne "\177ELF") {
+    printf("The file \"%s\" is not an ELF file.\n", $ifile);
+    exit (1);
+  } elsif ($eh[$e_machine] != 20) {
+    printf("The file \"%s\" is not a PowerPC ELF file.\n", $ifile);
+    exit (1);
+  }
+
+  if ($verbose) {
+    print("File header:\n");
+    printf("  Identifier:            %s\n",	$eh[$e_ident]);
+    printf("  Type:                  %d\n",	$eh[$e_type]);
+    printf("  Machine:               %d\n",	$eh[$e_machine]);
+    printf("  Version:               %d\n",	$eh[$e_version]);
+    printf("  Entry point:           0x%08x\n", $eh[$e_entry]);
+    printf("  Program header offset: 0x%x\n",	$eh[$e_phoff]);
+    printf("  Section header offset: 0x%x\n",	$eh[$e_shoff]);
+    printf("  Flags:                 0x%08x\n", $eh[$e_flags]);
+    printf("  Header size:           %d\n", $eh[$e_ehsize]);
+    printf("  Program entry size:    %d\n", $eh[$e_phentsize]);
+    printf("  Program table entries: %d\n", $eh[$e_phnum]);
+    printf("  Section header size:   %d\n", $eh[$e_shentsize]);
+    printf("  Section table entries: %d\n", $eh[$e_shnum]);
+    printf("  String table section:  %d\n", $eh[$e_shstrndx]);
+  }
+
+  #
+  # Find the section header for the string table.
+  #
+
+  $strtable_section_offset =  $eh[$e_shoff] +
+    $eh[$e_shstrndx] * $eh[$e_shentsize];
+
+  if ($verbose) {
+    printf("String table section header offset: 0x%x\n",
+	   $strtable_section_offset);
+  }
+  
+  #
+  # Find the start of the string table.
+  #
+
+  @strh = unpack("N10", substr($ibuf, $strtable_section_offset, 
+			       $eh[$e_shentsize]));
+
+  if ($verbose) {
+    printf("Section name strings start at: 0x%x, %d bytes.\n",
+	   $strh[$sh_offset], $strh[$sh_size]);
+  }
+
+  $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
+
+  # Grab each section header and find '.text' and '.bss' sections in
+  # particular.
+
+  if ($verbose) {
+  print("Section headers:\n");
+  print("Idx  Name                      Size      Address   File off  Algn\n");
+  print("---  ------------------------  --------  --------  --------  ----\n");
+  }
+
+  $off = $eh[$e_shoff];
+
+  for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
+    @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
+
+    # Take the first section name from the array returned by split.
+
+    ($name) = split(/\000/, substr($names, $sh[$sh_name]));
+    
+    if ($verbose) {
+      printf("%3d  %-24s  %8x  %08x  %08x  %4d\n", 
+	     $i, $name, $sh[$sh_size], $sh[$sh_addr], 
+	     $sh[$sh_offset], $sh[$sh_addralign]);
+    }
+
+    # Attempt to find the .text and .bss sections
+
+    if ($name =~ /^\.bss$/) {
+      ($bss_addr, $bss_offset, $bss_size) =
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+    } elsif ($name =~ /^\.text$/) {
+      ($text_addr, $text_offset, $text_size) = 
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+    } elsif ($linux && ($name =~ /^\image$/)) {
+      $image_found = 1;
+
+      ($image_addr, $image_offset, $image_size) = 
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+    } elsif ($linux && ($name =~ /^\initrd$/)) {
+      $initrd_found = 1;
+
+      ($initrd_addr, $initrd_offset, $initrd_size) = 
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+    }
+  }
+
+  printf("Text section   - Address: 0x%08x, Size: 0x%08x\n",
+	 $text_addr, $text_size);
+  printf("Bss  section   - Address: 0x%08x, Size: 0x%08x\n",
+	 $bss_addr, $bss_size);
+
+  if ($linux) {
+    if ($image_found) {
+      printf("Image section  - Address: 0x%08x, Size: 0x%08x\n",
+	     $image_addr, $image_size);
+    }
+
+    if ($initrd_found) {
+      printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n",
+	     $initrd_addr, $initrd_size);
+    }
+  }
+
+  #
+  # Open output file
+  #
+
+  open(BOOT, ">$ofile") || die "Cannot open output file";
+
+  #
+  # Compute image size
+  #
+
+  $output_size = $bss_offset - $text_offset + $bss_size;
+
+  if ($linux && $image_found) {
+    $output_size += $image_size;
+  }
+
+  if ($linux && $initrd_found) {
+    $output_size += $initrd_size;
+  }
+
+  $num_blocks = $output_size / 512 + 1;
+
+  #
+  # Write IBM PowerPC evaluation board boot_block_t header
+  #
+
+  $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0,
+		 $text_addr, 0, 0, 0);
+
+  $bytes = length($header);
+  
+  if (($resid = syswrite(BOOT, $header, $bytes)) != $bytes) {
+    die("Could not write boot image header to output file.");
+  }
+
+  printf("Entry point = 0x%08x\n", $text_addr);
+  printf("Image size  = 0x%08x (%d bytes) (%d blocks).\n", 
+	 $output_size, $output_size, $num_blocks);
+
+  #
+  # Write image starting after ELF and program headers and 
+  # continuing to beginning of bss
+  #
+
+  $bytes = $bss_offset - $text_offset + $bss_size;
+
+  if (($resid = syswrite(BOOT, $ibuf, $bytes, $text_offset)) != $bytes) {
+    die("Could not write boot image to output file.\n");
+  }
+
+  #
+  # If configured, write out the image and initrd sections as well
+  #
+
+  if ($linux) {
+    if ($image_found) {
+      $bytes = $image_size;
+      if (($resid = syswrite(BOOT, $ibuf, $bytes, $image_offset)) != $bytes) {
+	die("Could not write boot image to output file.\n");
+      }
+    }
+
+    if ($initrd_found) {
+      $bytes = $initrd_size;
+      if (($resid = syswrite(BOOT, $ibuf, $bytes, $initrd_offset)) != $bytes) {
+	die("Could not write boot image to output file.\n");
+      }
+    }
+  }
+
+  #
+  # Pad to a multiple of 512 bytes
+  #
+
+  $pad_size = 512 - (length($header) + $output_size) % 512;
+
+  if ($verbose) {
+    print("Padding boot image by an additional $pad_size bytes.\n");
+  }
+
+  $pad_string = pack(("H8","deadbeef") x 128);
+
+  syswrite(BOOT, $pad_string, $pad_size) or
+    die "Could not pad boot image in output file.\n";
+
+  #
+  # Clean-up and leave
+  #
+
+  close(BOOT);
+
+  print("\nBoot image file \"$ofile\" built successfully.\n\n");
+
+  exit(0);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/mkirimg linux/arch/ppc/boot/utils/mkirimg
--- v2.4.4/linux/arch/ppc/boot/utils/mkirimg	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/mkirimg	Thu May 24 15:02:07 2001
@@ -0,0 +1,367 @@
+#!/usr/bin/perl
+#
+#    Copyright (c) 1998-1999 TiVo, Inc.
+#      Original ELF parsing code.
+#
+#    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+#      Original code from 'mkevimg'.
+#
+#    Module name: mkirimg
+#
+#    Description:
+#      Reads an ELF file and assigns global variables 'imageSect_start',
+#      'imageSect_size', 'initrdSect_start', and 'initrdSect_size' from
+#      the "image" and "initrd" section header information. It then
+#      rewrites the input ELF file with assigned globals to an output
+#      file.
+#
+#      An input file, "irSectStart.txt" has the memory address of
+#      'irSectStart'. The irSectStart memory address is used to find
+#      the global variables in the ".data" section of the ELF file.
+#      The 'irSectStart' and the above global variables are defined
+#      in "irSect.c".
+#
+#
+
+use File::Basename;
+use Getopt::Std;
+
+#
+# usage()
+#
+# Description:
+#   This routine prints out the proper command line usage for this program
+#
+# Input(s):
+#   status - Flag determining what usage information will be printed and what
+#            the exit status of the program will be after the information is
+#            printed.
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   This subroutine does not return.
+#
+
+sub usage {
+  my($status);
+  $status = $_[0];
+
+  printf("Usage: %s [-hvV] <ELF input file> <Evaluation board output file> <irSectStart.txt file>\n",
+	 $program);
+
+  if ($status != 0) {
+    printf("Try `%s -h' for more information.\n", $program);
+  }
+
+  if ($status != 1) {
+    print("  -h             Print out this message and exit.\n");
+    print("  -v             Verbose. Print out lots of ELF information.\n");
+    print("  -V             Print out version information and exit.\n");
+  }
+
+  exit($status);
+}
+
+#
+# version()
+#
+# Description:
+#   This routine prints out program version information
+#
+# Input(s):
+#   N/A
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   This subroutine does not return.
+#
+
+sub version {
+  print("mkirimg Version 1.1.0\n");
+  print("Copyright (c) 1998-1999 TiVo, Inc.\n");
+  print("Copyright (c) 1999 Grant Erickson <grant\@lcse.umn.edu>\n");
+
+  exit (0);
+}
+
+#
+# file_check()
+#
+# Description:
+#   This routine checks an input file to ensure that it exists, is a
+#   regular file, and is readable.
+#
+# Input(s):
+#   file - Input file to be checked.
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   0 if the file exists, is a regular file, and is readable, otherwise -1.
+#
+
+sub file_check {
+  my($file);
+  $file = $_[0];
+
+  if (!(-e $file)) {
+     printf("The file \"%s\" does not exist.\n", $file);
+     return (-1);
+  } elsif (!(-f $file)) {
+     printf("The file \"%s\" is not a regular file.\n", $file);
+     return (-1);
+  } elsif (!(-r $file)) {
+     printf("The file \"%s\" is not readable.\n", $file);
+     return (-1);
+  }
+
+  return (0);
+}
+
+#
+# decode_options()
+#
+# Description:
+#   This routine steps through the command-line arguments, parsing out
+#   recognzied options.
+#
+# Input(s):
+#   N/A
+#
+# Output(s):
+#   N/A
+#
+# Returns:
+#   N/A
+#
+
+sub decode_options {
+
+  if (!getopts("hvV")) {
+      usage(1);
+  }
+
+  if ($opt_h) {
+      usage(0);
+  }
+
+  if ($opt_V) {
+      version();
+      exit (0);
+  }
+
+  if ($opt_v) {
+      $verbose = 1;
+  }
+
+  if (!($ElfFile = shift(@ARGV))) {
+      usage(1);
+  }
+
+  if (!($OutputFile = shift(@ARGV))) {
+      usage (1);
+  }
+
+  if (!($IrFile = shift(@ARGV))) {
+      usage (1);
+  }
+
+  if (file_check($ElfFile)) {
+      exit(1);
+  }
+
+  if (file_check($IrFile)) {
+      exit(1);
+  }
+}
+
+#
+# ELF file and section header field numbers
+#
+
+require '../utils/elf.pl';
+
+#
+# Main program body
+#
+
+{
+  $program = basename($0);
+  decode_options();
+
+  open(ELF, "<$ElfFile") || die "Cannot open input file";
+  open(OUTPUT, ">$OutputFile") || die "Cannot open output file";
+  open(IR, "$IrFile") || die "Cannot open input file";
+
+  $ElfFilesize = (-s $ElfFile);
+
+  if (read(ELF, $ibuf, $ElfFilesize) != $ElfFilesize) {
+    print("Failed to read ELF input file!\n");
+    exit(1);
+  }
+
+  if (read(IR, $irbuf, 8) != 8) {
+      print("Failed to read Ir input file!\n");
+      exit(1);
+  }
+
+  #
+  # Parse ELF header
+  #
+
+  @eh = unpack("a16n2N5n6", $ibuf);
+
+  #
+  # Make sure this is actually a PowerPC ELF file.
+  #
+
+  if (substr($eh[$e_ident], 0, 4) ne "\177ELF") {
+      printf("The file \"%s\" is not an ELF file.\n", $ElfFile);
+      exit (1);
+  } elsif ($eh[$e_machine] != 20) {
+      printf("The file \"%s\" is not a PowerPC ELF file.\n", $ElfFile);
+      exit (1);
+  }
+
+  #
+  # Find the section header for the string table.
+  #
+
+  $strtable_section_offset =  $eh[$e_shoff] +
+
+  $eh[$e_shstrndx] * $eh[$e_shentsize];
+
+  if ($verbose) {
+     printf("String table section header offset: 0x%x\n",
+     $strtable_section_offset);
+  }
+
+  #
+  # Find the start of the string table.
+  #
+
+  @strh = unpack("N10", substr($ibuf, $strtable_section_offset,
+			       $eh[$e_shentsize]));
+
+  if ($verbose) {
+     printf("Section name strings start at: 0x%x, %d bytes.\n",
+     $strh[$sh_offset], $strh[$sh_size]);
+  }
+
+  $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
+
+  # Grab each section header and find '.data', 'image', and 
+  # 'initrd' sections in particular.
+
+  $off = $eh[$e_shoff];
+  $imageFound = 0;
+  $initrdFound = 0;
+  
+  for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
+    @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
+
+    # Take the first section name from the array returned by split.
+
+    ($name) = split(/\000/, substr($names, $sh[$sh_name]));
+
+    # Attempt to find the .data, image, and initrd sections
+
+    if ($name =~ /^\image$/) {
+      ($image_addr, $image_offset, $image_size) =
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+      $imageFound = 1;
+
+    } elsif ($name =~ /^\initrd$/) {
+      ($initrd_addr, $initrd_offset, $initrd_size) =
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+      $initrdFound = 1;
+
+    } elsif ($name =~ /^\.data$/) {
+      ($data_addr, $data_offset, $data_size) =
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+    } elsif ($name =~ /^\.bss$/) {
+      ($bss_addr, $bss_offset, $bss_size) =
+	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
+
+    }
+   }
+
+  if ($verbose) {
+    printf("Data section   - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
+	   $data_addr, $data_size, $data_offset);
+    printf("Bss  section   - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
+	 $bss_addr, $bss_size, $bss_offset);
+   }
+
+  if ($verbose) {
+    if ($imageFound) {
+      printf("Image section  - Address: 0x%08x, Size: 0x%08x\n",
+	     $image_addr, $image_size);
+    } else {
+      printf("Image section not found in file: $ElfFile\n");
+    }
+
+    if ($initrdFound) {
+      printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n",
+	     $initrd_addr, $initrd_size);
+    } else {
+      printf("Initrd section not found in file: $ElfFile\n");
+    }
+  }
+
+  # get file offset of irSectStart
+
+  $irSectStartoffset = hex ($irbuf);
+
+  if ($verbose) {
+    printf("irSectStartOffset Address: 0x%08x\n", $irSectStartoffset);
+  }
+
+  # get the offset of global variables 
+
+  $initialOffset = ($irSectStartoffset - $data_addr) + $data_offset + 4;
+
+  # write modified values to OUTPUT file
+
+  syswrite(OUTPUT, $ibuf, $initialOffset);
+
+  if ($imageFound) {
+    $testN = pack ("N2", $bss_addr + $bss_size, $image_size);
+    syswrite(OUTPUT, $testN, length($testN));
+    printf("Updated symbol \"imageSect_start\" to 0x%08x\n",
+	   $bss_addr + $bss_size);
+    printf("Updated symbol \"imageSect_size\" to 0x%08x\n", $image_size);
+  } else {
+    syswrite(OUTPUT, $ibuf, 8, $initialOffset);
+  }
+
+  if ($initrdFound) {
+    $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
+    syswrite(OUTPUT, $testN, length($testN));
+    printf("Updated symbol \"initrdSect_start\" to 0x%08x\n",
+	   $bss_addr + $bss_size + $image_size);
+    printf("Updated symbol \"initrdSect_size\" to 0x%08x\n", $initrd_size);
+  } else {
+    syswrite(OUTPUT, $ibuf,8, $initialOffset + 8);
+  }
+
+  syswrite(OUTPUT, $ibuf, $ElfFilesize - ($initialOffset + 16),
+	   $initialOffset + 16);
+
+  #
+  # Clean-up and leave
+  #
+
+  close (ELF);
+  close (OUTPUT);
+  close (IR);
+
+  exit (0);
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/mknote.c linux/arch/ppc/boot/utils/mknote.c
--- v2.4.4/linux/arch/ppc/boot/utils/mknote.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/mknote.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,46 @@
+/*
+ * BK Id: SCCS/s.mknote.c 1.7 05/18/01 15:17:23 cort
+ */
+/*
+ * Copyright (C) Cort Dougan 1999.
+ *
+ * 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.
+ *
+ * Generate a note section as per the CHRP specification.
+ *
+ */
+
+#include <stdio.h>
+
+#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
+
+int main(void)
+{
+/* header */
+	/* namesz */
+	PL(strlen("PowerPC")+1);
+	/* descrsz */
+	PL(6*4);
+	/* type */
+	PL(0x1275);
+	/* name */
+	printf("PowerPC"); printf("%c", 0);
+	
+/* descriptor */
+	/* real-mode */
+	PL(0xffffffff);
+	/* real-base */
+	PL(0x00c00000);
+	/* real-size */
+	PL(0xffffffff);
+	/* virt-base */
+	PL(0xffffffff);
+	/* virt-size */
+	PL(0xffffffff);
+	/* load-base */
+	PL(0x4000);
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/mkprep.c linux/arch/ppc/boot/utils/mkprep.c
--- v2.4.4/linux/arch/ppc/boot/utils/mkprep.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/mkprep.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,292 @@
+/*
+ * BK Id: SCCS/s.mkprep.c 1.7 05/18/01 06:20:29 patch
+ */
+/*
+ * Makes a prep bootable image which can be dd'd onto
+ * a disk device to make a bootdisk.  Will take
+ * as input a elf executable, strip off the header
+ * and write out a boot image as:
+ * 1) default - strips elf header
+ *      suitable as a network boot image
+ * 2) -pbp - strips elf header and writes out prep boot partition image
+ *      cat or dd onto disk for booting
+ * 3) -asm - strips elf header and writes out as asm data
+ *      useful for generating data for a compressed image
+ *                  -- Cort
+ *
+ * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define cpu_to_le32(x) le32_to_cpu((x))
+unsigned long le32_to_cpu(unsigned long x)
+{
+     	return (((x & 0x000000ffU) << 24) |
+		((x & 0x0000ff00U) <<  8) |
+		((x & 0x00ff0000U) >>  8) |
+		((x & 0xff000000U) >> 24));
+}
+
+
+#define cpu_to_le16(x) le16_to_cpu((x))
+unsigned short le16_to_cpu(unsigned short x)
+{
+	return (((x & 0x00ff) << 8) |
+		((x & 0xff00) >> 8));
+}
+
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+#define cpu_to_be16(x) (x)
+#define be16_to_cpu(x) (x)
+
+/* size of read buffer */
+#define SIZE 0x1000
+
+
+typedef unsigned long dword_t;
+typedef unsigned short word_t;
+typedef unsigned char byte_t;
+typedef byte_t block_t[512];
+typedef byte_t page_t[4096];
+
+
+/*
+ * Partition table entry
+ *  - from the PReP spec
+ */
+typedef struct partition_entry {
+  byte_t	boot_indicator;
+  byte_t	starting_head;
+  byte_t	starting_sector;
+  byte_t	starting_cylinder;
+
+  byte_t	system_indicator;
+  byte_t	ending_head;
+  byte_t	ending_sector;
+  byte_t	ending_cylinder;
+
+  dword_t	beginning_sector;
+  dword_t	number_of_sectors;
+} partition_entry_t;
+
+#define BootActive	0x80
+#define SystemPrep	0x41
+
+void copy_image(int , int);
+void write_prep_partition(int , int );
+void write_asm_data( int in, int out );
+
+unsigned int elfhdr_size = 65536;
+
+int main(int argc, char *argv[])
+{
+  int in_fd, out_fd;
+  int argptr = 1;
+  unsigned int prep = 0;
+  unsigned int asmoutput = 0;
+
+  if ( (argc < 3) || (argc > 4) )
+  {
+    fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]);
+    exit(-1);
+  }
+
+  /* needs to handle args more elegantly -- but this is a small/simple program */
+  
+  /* check for -pbp */
+  if ( !strcmp( argv[argptr], "-pbp" ) )
+  {
+    prep = 1;
+    argptr++;
+  }
+  
+  /* check for -asm */
+  if ( !strcmp( argv[argptr], "-asm" ) )
+  {
+    asmoutput = 1;
+    argptr++;
+  }
+
+  /* input file */
+  if ( !strcmp( argv[argptr], "-" ) )
+    in_fd = 0;			/* stdin */
+  else
+    if ((in_fd = open( argv[argptr] , 0)) < 0)
+      exit(-1);
+  argptr++;
+
+  /* output file */
+  if ( !strcmp( argv[argptr], "-" ) )
+    out_fd = 1;			/* stdout */
+  else
+    if ((out_fd = creat( argv[argptr] , 0755)) < 0)
+      exit(-1);
+  argptr++;
+
+  /* skip elf header in input file */
+  /*if ( !prep )*/
+  lseek(in_fd, elfhdr_size, SEEK_SET);
+  
+  /* write prep partition if necessary */
+  if ( prep )
+	  write_prep_partition( in_fd, out_fd );
+
+  /* write input image to bootimage */
+  if ( asmoutput )
+	  write_asm_data( in_fd, out_fd );
+  else
+	  copy_image(in_fd, out_fd);
+  
+  return 0;
+}
+
+void write_prep_partition(int in, int out)
+{
+  unsigned char block[512];
+  partition_entry_t *pe = (partition_entry_t *)&block[0x1BE];
+  dword_t *entry  = (dword_t *)&block[0];
+  dword_t *length = (dword_t *)&block[sizeof(long)];
+  struct stat info;
+  
+  if (fstat(in, &info) < 0)
+  {
+    fprintf(stderr,"info failed\n");
+    exit(-1);
+  }
+  
+  bzero( block, sizeof block );
+ 
+  /* set entry point and boot image size skipping over elf header */
+#ifdef __i386__
+  *entry = 0x400/*+65536*/;
+  *length = info.st_size-elfhdr_size+0x400;
+#else
+  *entry = cpu_to_le32(0x400/*+65536*/);
+  *length = cpu_to_le32(info.st_size-elfhdr_size+0x400);
+#endif /* __i386__ */
+
+  /* sets magic number for msdos partition (used by linux) */
+  block[510] = 0x55;
+  block[511] = 0xAA;
+  
+  /*
+   * Build a "PReP" partition table entry in the boot record
+   *  - "PReP" may only look at the system_indicator
+   */
+  pe->boot_indicator   = BootActive;
+  pe->system_indicator = SystemPrep;
+  /*
+   * The first block of the diskette is used by this "boot record" which
+   * actually contains the partition table. (The first block of the
+   * partition contains the boot image, but I digress...)  We'll set up
+   * one partition on the diskette and it shall contain the rest of the
+   * diskette.
+   */
+  pe->starting_head     = 0;	/* zero-based			     */
+  pe->starting_sector   = 2;	/* one-based			     */
+  pe->starting_cylinder = 0;	/* zero-based			     */
+  pe->ending_head       = 1;	/* assumes two heads		     */
+  pe->ending_sector     = 18;	/* assumes 18 sectors/track	     */
+  pe->ending_cylinder   = 79;	/* assumes 80 cylinders/diskette     */
+
+  /*
+   * The "PReP" software ignores the above fields and just looks at
+   * the next two.
+   *   - size of the diskette is (assumed to be)
+   *     (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
+   *   - unlike the above sector numbers, the beginning sector is zero-based!
+   */
+#if 0
+  pe->beginning_sector  = cpu_to_le32(1);
+#else
+  /* This has to be 0 on the PowerStack? */   
+#ifdef __i386__
+  pe->beginning_sector  = 0;
+#else
+  pe->beginning_sector  = cpu_to_le32(0);
+#endif /* __i386__ */
+#endif    
+
+#ifdef __i386__
+  pe->number_of_sectors = 2*18*80-1;
+#else
+  pe->number_of_sectors = cpu_to_le32(2*18*80-1);
+#endif /* __i386__ */
+
+  write( out, block, sizeof(block) );
+  write( out, entry, sizeof(*entry) );
+  write( out, length, sizeof(*length) );  
+  /* set file position to 2nd sector where image will be written */
+  lseek( out, 0x400, SEEK_SET );
+}
+
+
+
+void
+copy_image(int in, int out)
+{
+  char buf[SIZE];
+  int n;
+
+  while ( (n = read(in, buf, SIZE)) > 0 )
+    write(out, buf, n);
+}
+
+
+void
+write_asm_data( int in, int out )
+{
+  int i, cnt, pos, len;
+  unsigned int cksum, val;
+  unsigned char *lp;
+  unsigned char buf[SIZE];
+  unsigned char str[256];
+  
+  write( out, "\t.data\n\t.globl input_data\ninput_data:\n",
+	 strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) );
+  pos = 0;
+  cksum = 0;
+  while ((len = read(in, buf, sizeof(buf))) > 0)
+  {
+    cnt = 0;
+    lp = (unsigned char *)buf;
+    len = (len + 3) & ~3;  /* Round up to longwords */
+    for (i = 0;  i < len;  i += 4)
+    {
+      if (cnt == 0)
+      {
+	write( out, "\t.long\t", strlen( "\t.long\t" ) );
+      }
+      sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
+      write( out, str, strlen(str) );
+      val = *(unsigned long *)lp;
+      cksum ^= val;
+      lp += 4;
+      if (++cnt == 4)
+      {
+	cnt = 0;
+	sprintf( str, " # %x \n", pos+i-12);
+	write( out, str, strlen(str) );
+      } else
+      {
+	write( out, ",", 1 );
+      }
+    }
+    if (cnt)
+    {
+      write( out, "0\n", 2 );
+    }
+    pos += len;
+  }
+  sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
+  write( out, str, strlen(str) );
+
+  fprintf(stderr, "cksum = %x\n", cksum);
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/mksimage.c linux/arch/ppc/boot/utils/mksimage.c
--- v2.4.4/linux/arch/ppc/boot/utils/mksimage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/mksimage.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,127 @@
+/*
+ * BK Id: SCCS/s.mksimage.c 1.6 05/18/01 15:16:42 cort
+ */
+/*
+ *
+ *
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+#define SIZE 1024
+#define BLOCK_ALIGN(x)  (((x)+SIZE-1)&(~(SIZE-1)))
+
+static void
+die(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	fputc('\n', stderr);
+	exit(1);
+}
+
+static void
+usage(void)
+{
+	printf("Usage: mkbinimg <bootstrap> <kernel> <ramdisk> -o <binary>\n");
+	exit(1);
+}
+
+static int
+copy_blocks(int ifd, int ofd, unsigned long *offset, unsigned long *size)
+{
+	off_t cur;
+	int amt;
+	unsigned long len = 0;
+	char buffer[SIZE];
+
+	cur = lseek(ofd, 0, SEEK_CUR);
+
+	if (cur % SIZE) {
+		cur = BLOCK_ALIGN(cur);
+		cur = lseek(ofd, cur, SEEK_SET);
+	}
+
+	*offset = (unsigned long) cur;
+	while((amt = read(ifd, buffer, SIZE)) > 0) {
+		write(ofd, buffer, amt);
+		len += amt;
+	}
+	*size = len;
+	return 0;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+	char *kernel, *loader, *rdimage = NULL;
+	unsigned long ld_off, kern_off, rd_off;
+	unsigned long ld_size, kern_size, rd_size;
+	int fd, ofd, len;
+	char buffer[500];
+
+	if (argc < 5 && !strcmp(argv[argc-2], "-o"))
+		usage();
+
+	if (argc > 5)
+		rdimage = argv[3];
+
+	kernel = argv[2];
+	loader = argv[1];
+
+	ofd = open(argv[argc-1], (O_RDWR|O_CREAT), 0755);
+	if (ofd < 0) {
+		die("can't open %s: %s", argv[5], strerror(errno));
+	}
+
+	ld_off = kern_off = rd_off = 0;
+	ld_size = kern_size = rd_size = 0;
+	memset(buffer, 0, 500);
+	len = 0;
+
+	fd = open(loader, O_RDONLY);
+	if (fd < 0) 
+		die("can't open loader: %s", strerror(errno));
+
+	copy_blocks(fd, ofd, &ld_off, &ld_size);
+	len = sprintf(buffer, "bootloader: %x %x\n", ld_off, ld_size);
+	close(fd);
+
+	fd = open(kernel, O_RDONLY);
+	if (fd < 0)
+		die("can't open kernel: %s", strerror(errno));
+
+	copy_blocks(fd, ofd, &kern_off, &kern_size);
+	len += sprintf(buffer+len, "zimage: %x %x\n", kern_off, kern_size);
+	close(fd);
+	
+	if (rdimage) {
+		fd = open(rdimage, O_RDONLY);
+		if (fd < 0)
+			die("can't get ramdisk: %s", strerror(errno));
+		
+		copy_blocks(fd, ofd, &rd_off, &rd_size);
+		close(fd);
+	}
+
+	len += sprintf(buffer+len, "initrd: %x %x", rd_off, rd_size);
+
+	close(ofd);
+
+	printf("%s\n", buffer);
+
+	return 0;
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/offset linux/arch/ppc/boot/utils/offset
--- v2.4.4/linux/arch/ppc/boot/utils/offset	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/offset	Thu May 24 15:02:07 2001
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux| awk '{print $6}'`
+echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/piggyback.c linux/arch/ppc/boot/utils/piggyback.c
--- v2.4.4/linux/arch/ppc/boot/utils/piggyback.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/piggyback.c	Thu May 24 15:02:07 2001
@@ -0,0 +1,69 @@
+/*
+ * BK Id: SCCS/s.piggyback.c 1.7 05/18/01 15:17:23 cort
+ */
+#include <stdio.h>
+#include <unistd.h>
+
+extern long ce_exec_config[];
+
+int main(int argc, char *argv[])
+{
+	int i, cnt, pos, len;
+	unsigned int cksum, val;
+	unsigned char *lp;
+	unsigned char buf[8192];
+	if (argc != 2)
+	{
+		fprintf(stderr, "usage: %s name <in-file >out-file\n",
+			argv[0]);
+		exit(1);
+	}
+	fprintf(stdout, "#\n");
+	fprintf(stdout, "# Miscellaneous data structures:\n");
+	fprintf(stdout, "# WARNING - this file is automatically generated!\n");
+	fprintf(stdout, "#\n");
+	fprintf(stdout, "\n");
+	fprintf(stdout, "\t.data\n");
+	fprintf(stdout, "\t.globl %s_data\n", argv[1]);
+	fprintf(stdout, "%s_data:\n", argv[1]);
+	pos = 0;
+	cksum = 0;
+	while ((len = read(0, buf, sizeof(buf))) > 0)
+	{
+		cnt = 0;
+		lp = (unsigned char *)buf;
+		len = (len + 3) & ~3;  /* Round up to longwords */
+		for (i = 0;  i < len;  i += 4)
+		{
+			if (cnt == 0)
+			{
+				fprintf(stdout, "\t.long\t");
+			}
+			fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
+			val = *(unsigned long *)lp;
+			cksum ^= val;
+			lp += 4;
+			if (++cnt == 4)
+			{
+				cnt = 0;
+				fprintf(stdout, " # %x \n", pos+i-12);
+				fflush(stdout);
+			} else
+			{
+				fprintf(stdout, ",");
+			}
+		}
+		if (cnt)
+		{
+			fprintf(stdout, "0\n");
+		}
+		pos += len;
+	}
+	fprintf(stdout, "\t.globl %s_len\n", argv[1]);
+	fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos);
+	fflush(stdout);
+	fclose(stdout);
+	fprintf(stderr, "cksum = %x\n", cksum);
+	exit(0);
+}
+
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/sioffset linux/arch/ppc/boot/utils/sioffset
--- v2.4.4/linux/arch/ppc/boot/utils/sioffset	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/sioffset	Thu May 24 15:02:07 2001
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`grep $1 sImage.map | awk '{print $2}'`
+echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/sisize linux/arch/ppc/boot/utils/sisize
--- v2.4.4/linux/arch/ppc/boot/utils/sisize	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/sisize	Thu May 24 15:02:07 2001
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`grep $1 sImage.map | awk '{print $3}'`
+echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/utils/size linux/arch/ppc/boot/utils/size
--- v2.4.4/linux/arch/ppc/boot/utils/size	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/utils/size	Thu May 24 15:02:07 2001
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux | awk '{print $3}'`
+echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/boot/vreset.c linux/arch/ppc/boot/vreset.c
--- v2.4.4/linux/arch/ppc/boot/vreset.c	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/boot/vreset.c	Wed Dec 31 16:00:00 1969
@@ -1,838 +0,0 @@
-/*
- * vreset.c
- *
- * Initialize the VGA control registers to 80x25 text mode.
- *
- * Adapted from a program by:
- *                                      Steve Sellgren
- *                                      San Francisco Indigo Company
- *                                      sfindigo!sellgren@uunet.uu.net
- *
- * Original concept by:
- *                                      Gary Thomas <gdt@linuxppc.org>
- * Adapted for Moto boxes by:
- *                                      Pat Kane & Mark Scott, 1996
- * Adapted for IBM portables by:
- *                                      Takeshi Ishimoto
- * Multi-console support:
- *                                      Terje Malmedal <terje.malmedal@usit.uio.no>
- */
-
-#include "iso_font.h"
-
-extern char *vidmem;
-extern int lines, cols;
-
-static void mdelay(int ms)
-{
-	for (; ms > 0; --ms)
-		udelay(1000);
-}
-
-/*
- * VGA Register  
- */
-struct VgaRegs
-{
-	unsigned short io_port;
-	unsigned char  io_index;
-	unsigned char  io_value;
-};
-
-/*
- * Default console text mode registers  used to reset
- * graphics adapter.
- */
-#define NREGS 54
-#define ENDMK  0xFFFF  /* End marker */
-
-#define S3Vendor        0x5333
-#define CirrusVendor    0x1013
-#define DiamondVendor   0x100E
-#define MatroxVendor    0x102B
-#define ParadiseVendor  0x101C
-
-struct VgaRegs GenVgaTextRegs[NREGS+1] = {
-/*      port    index   value  */
-  /* SR Regs */
-        0x3c4,  0x1,    0x0,
-        0x3c4,  0x2,    0x3,
-        0x3c4,  0x3,    0x0,
-        0x3c4,  0x4,    0x2,
-   /* CR Regs */
-        0x3d4,  0x0,    0x5f,
-        0x3d4,  0x1,    0x4f,
-        0x3d4,  0x2,    0x50,
-        0x3d4,  0x3,    0x82,
-        0x3d4,  0x4,    0x55,
-        0x3d4,  0x5,    0x81,
-        0x3d4,  0x6,    0xbf,
-        0x3d4,  0x7,    0x1f,
-        0x3d4,  0x8,    0x00,
-        0x3d4,  0x9,    0x4f,
-        0x3d4,  0xa,    0x0d,
-        0x3d4,  0xb,    0x0e,
-        0x3d4,  0xc,    0x00,
-        0x3d4,  0xd,    0x00,
-        0x3d4,  0xe,    0x00,
-        0x3d4,  0xf,    0x00,
-        0x3d4,  0x10,   0x9c,
-        0x3d4,  0x11,   0x8e,
-        0x3d4,  0x12,   0x8f,
-        0x3d4,  0x13,   0x28,
-        0x3d4,  0x14,   0x1f,
-        0x3d4,  0x15,   0x96,
-        0x3d4,  0x16,   0xb9,
-        0x3d4,  0x17,   0xa3,
-   /* GR Regs */
-        0x3ce,  0x0,    0x0,
-        0x3ce,  0x1,    0x0,
-        0x3ce,  0x2,    0x0,
-        0x3ce,  0x3,    0x0,
-        0x3ce,  0x4,    0x0,
-        0x3ce,  0x5,    0x10,
-        0x3ce,  0x6,    0xe,
-        0x3ce,  0x7,    0x0,
-        0x3ce,  0x8,    0xff,
-        ENDMK
-};
-
-struct VgaRegs S3TextRegs[NREGS+1] = {
-/*	port	index	value  */
-  /* SR Regs */
-	0x3c4,	0x1,	0x0,
-	0x3c4,	0x2,	0x3,
-	0x3c4,	0x3,	0x0,
-	0x3c4,	0x4,	0x2,
-   /* CR Regs */
-	0x3d4,	0x0,	0x5f,
-	0x3d4,	0x1,	0x4f,
-	0x3d4,	0x2,	0x50,
-	0x3d4,	0x3,	0x82,
-	0x3d4,	0x4,	0x55,
-	0x3d4,	0x5,	0x81,
-	0x3d4,	0x6,	0xbf,
-	0x3d4,	0x7,	0x1f,
-	0x3d4,	0x8,	0x00,
-	0x3d4,	0x9,	0x4f,
-	0x3d4,	0xa,	0x0d,
-	0x3d4,	0xb,	0x0e,
-	0x3d4,	0xc,	0x00,
-	0x3d4,	0xd,	0x00,
-	0x3d4,	0xe,	0x00,
-	0x3d4,	0xf,	0x00,
-	0x3d4,	0x10,	0x9c,
-	0x3d4,	0x11,	0x8e,
-	0x3d4,	0x12,	0x8f,
-	0x3d4,	0x13,	0x28,
-	0x3d4,	0x14,	0x1f,
-	0x3d4,	0x15,	0x96,
-	0x3d4,	0x16,	0xb9,
-	0x3d4,	0x17,	0xa3,
-   /* GR Regs */
-	0x3ce,	0x0,	0x0,
-	0x3ce,	0x1,	0x0,
-	0x3ce,	0x2,	0x0,
-	0x3ce,	0x3,	0x0,
-	0x3ce,	0x4,	0x0,
-	0x3ce,	0x5,	0x10,
-	0x3ce,	0x6,	0xe,
-	0x3ce,	0x7,	0x0,
-	0x3ce,	0x8,	0xff,
-        ENDMK
-};
-
-struct RGBColors
-{
-  unsigned char r, g, b;
-};
-
-/*
- * Default console text mode color table.
- * These values were obtained by booting Linux with
- * text mode firmware & then dumping the registers.  
- */
-struct RGBColors TextCLUT[256] = 
-{
-  /*	red	green	blue  */
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x2a,
-	0x0,	0x2a,	0x0,
-	0x0,	0x2a,	0x2a,
-	0x2a,	0x0,	0x0,
-	0x2a,	0x0,	0x2a,
-	0x2a,	0x2a,	0x0,
-	0x2a,	0x2a,	0x2a,
-	0x0,	0x0,	0x15,
-	0x0,	0x0,	0x3f,
-	0x0,	0x2a,	0x15,
-	0x0,	0x2a,	0x3f,
-	0x2a,	0x0,	0x15,
-	0x2a,	0x0,	0x3f,
-	0x2a,	0x2a,	0x15,
-	0x2a,	0x2a,	0x3f,
-	0x0,	0x15,	0x0,
-	0x0,	0x15,	0x2a,
-	0x0,	0x3f,	0x0,
-	0x0,	0x3f,	0x2a,
-	0x2a,	0x15,	0x0,
-	0x2a,	0x15,	0x2a,
-	0x2a,	0x3f,	0x0,
-	0x2a,	0x3f,	0x2a,
-	0x0,	0x15,	0x15,
-	0x0,	0x15,	0x3f,
-	0x0,	0x3f,	0x15,
-	0x0,	0x3f,	0x3f,
-	0x2a,	0x15,	0x15,
-	0x2a,	0x15,	0x3f,
-	0x2a,	0x3f,	0x15,
-	0x2a,	0x3f,	0x3f,
-	0x15,	0x0,	0x0,
-	0x15,	0x0,	0x2a,
-	0x15,	0x2a,	0x0,
-	0x15,	0x2a,	0x2a,
-	0x3f,	0x0,	0x0,
-	0x3f,	0x0,	0x2a,
-	0x3f,	0x2a,	0x0,
-	0x3f,	0x2a,	0x2a,
-	0x15,	0x0,	0x15,
-	0x15,	0x0,	0x3f,
-	0x15,	0x2a,	0x15,
-	0x15,	0x2a,	0x3f,
-	0x3f,	0x0,	0x15,
-	0x3f,	0x0,	0x3f,
-	0x3f,	0x2a,	0x15,
-	0x3f,	0x2a,	0x3f,
-	0x15,	0x15,	0x0,
-	0x15,	0x15,	0x2a,
-	0x15,	0x3f,	0x0,
-	0x15,	0x3f,	0x2a,
-	0x3f,	0x15,	0x0,
-	0x3f,	0x15,	0x2a,
-	0x3f,	0x3f,	0x0,
-	0x3f,	0x3f,	0x2a,
-	0x15,	0x15,	0x15,
-	0x15,	0x15,	0x3f,
-	0x15,	0x3f,	0x15,
-	0x15,	0x3f,	0x3f,
-	0x3f,	0x15,	0x15,
-	0x3f,	0x15,	0x3f,
-	0x3f,	0x3f,	0x15,
-	0x3f,	0x3f,	0x3f,
-	0x39,	0xc,	0x5,
-	0x15,	0x2c,	0xf,
-	0x26,	0x10,	0x3d,
-	0x29,	0x29,	0x38,
-	0x4,	0x1a,	0xe,
-	0x2,	0x1e,	0x3a,
-	0x3c,	0x25,	0x33,
-	0x3c,	0xc,	0x2c,
-	0x3f,	0x3,	0x2b,
-	0x1c,	0x9,	0x13,
-	0x25,	0x2a,	0x35,
-	0x1e,	0xa,	0x38,
-	0x24,	0x8,	0x3,
-	0x3,	0xe,	0x36,
-	0xc,	0x6,	0x2a,
-	0x26,	0x3,	0x32,
-	0x5,	0x2f,	0x33,
-	0x3c,	0x35,	0x2f,
-	0x2d,	0x26,	0x3e,
-	0xd,	0xa,	0x10,
-	0x25,	0x3c,	0x11,
-	0xd,	0x4,	0x2e,
-	0x5,	0x19,	0x3e,
-	0xc,	0x13,	0x34,
-	0x2b,	0x6,	0x24,
-	0x4,	0x3,	0xd,
-	0x2f,	0x3c,	0xc,
-	0x2a,	0x37,	0x1f,
-	0xf,	0x12,	0x38,
-	0x38,	0xe,	0x2a,
-	0x12,	0x2f,	0x19,
-	0x29,	0x2e,	0x31,
-	0x25,	0x13,	0x3e,
-	0x33,	0x3e,	0x33,
-	0x1d,	0x2c,	0x25,
-	0x15,	0x15,	0x5,
-	0x32,	0x25,	0x39,
-	0x1a,	0x7,	0x1f,
-	0x13,	0xe,	0x1d,
-	0x36,	0x17,	0x34,
-	0xf,	0x15,	0x23,
-	0x2,	0x35,	0xd,
-	0x15,	0x3f,	0xc,
-	0x14,	0x2f,	0xf,
-	0x19,	0x21,	0x3e,
-	0x27,	0x11,	0x2f,
-	0x38,	0x3f,	0x3c,
-	0x36,	0x2d,	0x15,
-	0x16,	0x17,	0x2,
-	0x1,	0xa,	0x3d,
-	0x1b,	0x11,	0x3f,
-	0x21,	0x3c,	0xd,
-	0x1a,	0x39,	0x3d,
-	0x8,	0xe,	0xe,
-	0x22,	0x21,	0x23,
-	0x1e,	0x30,	0x5,
-	0x1f,	0x22,	0x3d,
-	0x1e,	0x2f,	0xa,
-	0x0,	0x1c,	0xe,
-	0x0,	0x1c,	0x15,
-	0x0,	0x1c,	0x1c,
-	0x0,	0x15,	0x1c,
-	0x0,	0xe,	0x1c,
-	0x0,	0x7,	0x1c,
-	0xe,	0xe,	0x1c,
-	0x11,	0xe,	0x1c,
-	0x15,	0xe,	0x1c,
-	0x18,	0xe,	0x1c,
-	0x1c,	0xe,	0x1c,
-	0x1c,	0xe,	0x18,
-	0x1c,	0xe,	0x15,
-	0x1c,	0xe,	0x11,
-	0x1c,	0xe,	0xe,
-	0x1c,	0x11,	0xe,
-	0x1c,	0x15,	0xe,
-	0x1c,	0x18,	0xe,
-	0x1c,	0x1c,	0xe,
-	0x18,	0x1c,	0xe,
-	0x15,	0x1c,	0xe,
-	0x11,	0x1c,	0xe,
-	0xe,	0x1c,	0xe,
-	0xe,	0x1c,	0x11,
-	0xe,	0x1c,	0x15,
-	0xe,	0x1c,	0x18,
-	0xe,	0x1c,	0x1c,
-	0xe,	0x18,	0x1c,
-	0xe,	0x15,	0x1c,
-	0xe,	0x11,	0x1c,
-	0x14,	0x14,	0x1c,
-	0x16,	0x14,	0x1c,
-	0x18,	0x14,	0x1c,
-	0x1a,	0x14,	0x1c,
-	0x1c,	0x14,	0x1c,
-	0x1c,	0x14,	0x1a,
-	0x1c,	0x14,	0x18,
-	0x1c,	0x14,	0x16,
-	0x1c,	0x14,	0x14,
-	0x1c,	0x16,	0x14,
-	0x1c,	0x18,	0x14,
-	0x1c,	0x1a,	0x14,
-	0x1c,	0x1c,	0x14,
-	0x1a,	0x1c,	0x14,
-	0x18,	0x1c,	0x14,
-	0x16,	0x1c,	0x14,
-	0x14,	0x1c,	0x14,
-	0x14,	0x1c,	0x16,
-	0x14,	0x1c,	0x18,
-	0x14,	0x1c,	0x1a,
-	0x14,	0x1c,	0x1c,
-	0x14,	0x1a,	0x1c,
-	0x14,	0x18,	0x1c,
-	0x14,	0x16,	0x1c,
-	0x0,	0x0,	0x10,
-	0x4,	0x0,	0x10,
-	0x8,	0x0,	0x10,
-	0xc,	0x0,	0x10,
-	0x10,	0x0,	0x10,
-	0x10,	0x0,	0xc,
-	0x10,	0x0,	0x8,
-	0x10,	0x0,	0x4,
-	0x10,	0x0,	0x0,
-	0x10,	0x4,	0x0,
-	0x10,	0x8,	0x0,
-	0x10,	0xc,	0x0,
-	0x10,	0x10,	0x0,
-	0xc,	0x10,	0x0,
-	0x8,	0x10,	0x0,
-	0x4,	0x10,	0x0,
-	0x0,	0x10,	0x0,
-	0x0,	0x10,	0x4,
-	0x0,	0x10,	0x8,
-	0x0,	0x10,	0xc,
-	0x0,	0x10,	0x10,
-	0x0,	0xc,	0x10,
-	0x0,	0x8,	0x10,
-	0x0,	0x4,	0x10,
-	0x8,	0x8,	0x10,
-	0xa,	0x8,	0x10,
-	0xc,	0x8,	0x10,
-	0xe,	0x8,	0x10,
-	0x10,	0x8,	0x10,
-	0x10,	0x8,	0xe,
-	0x10,	0x8,	0xc,
-	0x10,	0x8,	0xa,
-	0x10,	0x8,	0x8,
-	0x10,	0xa,	0x8,
-	0x10,	0xc,	0x8,
-	0x10,	0xe,	0x8,
-	0x10,	0x10,	0x8,
-	0xe,	0x10,	0x8,
-	0xc,	0x10,	0x8,
-	0xa,	0x10,	0x8,
-	0x8,	0x10,	0x8,
-	0x8,	0x10,	0xa,
-	0x8,	0x10,	0xc,
-	0x8,	0x10,	0xe,
-	0x8,	0x10,	0x10,
-	0x8,	0xe,	0x10,
-	0x8,	0xc,	0x10,
-	0x8,	0xa,	0x10,
-	0xb,	0xb,	0x10,
-	0xc,	0xb,	0x10,
-	0xd,	0xb,	0x10,
-	0xf,	0xb,	0x10,
-	0x10,	0xb,	0x10,
-	0x10,	0xb,	0xf,
-	0x10,	0xb,	0xd,
-	0x10,	0xb,	0xc,
-	0x10,	0xb,	0xb,
-	0x10,	0xc,	0xb,
-	0x10,	0xd,	0xb,
-	0x10,	0xf,	0xb,
-	0x10,	0x10,	0xb,
-	0xf,	0x10,	0xb,
-	0xd,	0x10,	0xb,
-	0xc,	0x10,	0xb,
-	0xb,	0x10,	0xb,
-	0xb,	0x10,	0xc,
-	0xb,	0x10,	0xd,
-	0xb,	0x10,	0xf,
-	0xb,	0x10,	0x10,
-	0xb,	0xf,	0x10,
-	0xb,	0xd,	0x10,
-	0xb,	0xc,	0x10,
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x0,
-	0x0,	0x0,	0x0
-};
-
-unsigned char AC[21] = {
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 
-    0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 
-    0x0C, 0x00, 0x0F, 0x08, 0x00};
-
-static int scanPCI(int start_slt);
-static int PCIVendor(int);
-static void printslots(void);
-extern void puthex(unsigned long);
-extern void puts(const char *);
-static void unlockS3(void);
-
-static inline
-outw(int port, unsigned short val)
-{
-	outb(port, val >> 8);
-	outb(port+1, val);
-}
- 
-#define PPC_601 1
-
-vga_init(unsigned char *ISA_mem)
-{
-	int slot;
-	struct VgaRegs *VgaTextRegs;
-#if 0
-	if ((_get_PVR()>>16) == PPC_601) {
-		return(old_vga_init(ISA_mem));
-	}
-#endif
-	
-	/* See if VGA already in TEXT mode - exit if so! */
-	outb(0x3CE, 0x06);
-	if ((inb(0x3CF) & 0x01) == 0){puts("VGA already in text mode\n"); return;}
-
-	/* If no VGA responding in text mode, then we have some work to do...
-	 */
-	slot = -1;
-	while((slot = scanPCI(slot)) > -1) { /* find video card in use  */
-		unlockVideo(slot);           /* enable I/O to card      */
-		VgaTextRegs = GenVgaTextRegs;
-	
-		switch (PCIVendor(slot)) {
-		default:
-			break;
-		case(S3Vendor):
-			unlockS3();
-			VgaTextRegs = S3TextRegs;
-			break;
-	
-		case(CirrusVendor):
-			outw(0x3C4, 0x0612);       /* unlock ext regs */
-			outw(0x3C4, 0x0700);       /* reset ext sequence mode */
-			break;
-	
-		case(ParadiseVendor):                 /* IBM Portable 850 */
-			outw(0x3ce, 0x0f05);      /* unlock pardise registers */
-			outw(0x3c4, 0x0648);
-			outw(0x3d4, 0x2985);
-			outw(0x3d4, 0x34a6);
-			outb(0x3ce, 0x0b);       /* disable linear addressing */
-			outb(0x3cf, inb(0x3cf) & ~0x30);
-			outw(0x3c4, 0x1400);
-			outb(0x3ce, 0x0e);       /* disable 256 color mode */
-			outb(0x3cf, inb(0x3cf) & ~0x01);
-			outb(0xd00, 0xff);       /* enable auto-centering */
-			if (!(inb(0xd01) & 0x03)) {
-				outb(0x3d4, 0x33);
-				outb(0x3d5, inb(0x3d5) & ~0x90);
-				outb(0x3d4, 0x32);
-				outb(0x3d5, inb(0x3d5) | 0x04);
-				outw(0x3d4, 0x0250);
-				outw(0x3d4, 0x07ba);
-				outw(0x3d4, 0x0900);
-				outw(0x3d4, 0x15e7);
-				outw(0x3d4, 0x2a95);
-			}
-			outw(0x3d4, 0x34a0);
-			break;
-	
-	#if 0 /* Untested - probably doesn't work */
-		case(MatroxVendor):
-		case(DiamondVendor):
-			puts("VGA Chip Vendor ID: ");
-			puthex(PCIVendor(slot));
-			puts("\n");
-			mdelay(1000);
-	#endif
-		};
-	
-		outw(0x3C4, 0x0120);           /* disable video              */
-		setTextRegs(VgaTextRegs);      /* initial register setup     */
-		setTextCLUT(0);                /* load color lookup table    */
-		loadFont(ISA_mem);             /* load font                  */
-		setTextRegs(VgaTextRegs);      /* reload registers           */
-		outw(0x3C4, 0x0100);           /* re-enable video            */
-		clearVideoMemory();
-	
-		if (PCIVendor(slot) == S3Vendor) {
-			outb(0x3c2, 0x63);                  /* MISC */
-		} /* endif */
-	
-	#ifdef DEBUG
-		printslots();
-		mdelay(5000);
-	#endif
-	
-		mdelay(1000);	/* give time for the video monitor to come up */
-        }
-	return (1);  /* 'CRT' I/O supported */
-}
-
-/*
- * Write to VGA Attribute registers.  
- */
-writeAttr(index, data, videoOn)
-     unsigned char index;
-     unsigned char data;
-     unsigned char videoOn;   /* video on flag */
-{
-	unsigned char v;
-	v = inb(0x3da);   /* reset attr. address toggle */
-	if (videoOn)
-		outb(0x3c0, (index & 0x1F) | 0x20);
-	else
-		outb(0x3c0, (index & 0x1F));
-	outb(0x3c0, data);
-}
-
-setTextRegs(struct VgaRegs *svp)
-{
-	int i;
-
-	/*
-	 *  saved settings
-	 */ 
-	while( svp->io_port != ENDMK ) {
-		outb(svp->io_port,   svp->io_index);
-		outb(svp->io_port+1, svp->io_value);
-		svp++; 
-	}
-
-	outb(0x3c2, 0x67);  /* MISC */
-	outb(0x3c6, 0xff);  /* MASK */
-
-	for ( i = 0; i < 0x10; i++)
-		writeAttr(i, AC[i], 0);  /* pallete */ 
-	writeAttr(0x10, 0x0c, 0);    /* text mode */
-	writeAttr(0x11, 0x00, 0);    /* overscan color (border) */
-	writeAttr(0x12, 0x0f, 0);    /* plane enable */
-	writeAttr(0x13, 0x08, 0);    /* pixel panning */
-	writeAttr(0x14, 0x00, 1);    /* color select; video on  */
-}
-
-setTextCLUT(int shift)
-{
-	int i;
-
-	outb(0x3C6, 0xFF); 
-	i = inb(0x3C7);
-	outb(0x3C8, 0); 
-	i = inb(0x3C7);
-
-	for ( i = 0; i < 256; i++) {
-		outb(0x3C9, TextCLUT[i].r << shift);
-		outb(0x3C9, TextCLUT[i].g << shift);
-		outb(0x3C9, TextCLUT[i].b << shift);
-	}
-}
-
-
-loadFont(unsigned char *ISA_mem)
-{
-	int i, j;
-	unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
-    
-	outb(0x3C2, 0x67);
-	/* 
-	 * Load font 
-	 */
-	i = inb(0x3DA);  /* Reset Attr toggle */
-
-	outb(0x3C0,0x30); 
-	outb(0x3C0, 0x01);      /* graphics mode */
-
-	outw(0x3C4, 0x0001);    /* reset sequencer */
-	outw(0x3C4, 0x0204);    /* write to plane 2 */
-	outw(0x3C4, 0x0406);    /* enable plane graphics */
-	outw(0x3C4, 0x0003);    /* reset sequencer */
-	outw(0x3CE, 0x0402);    /* read plane 2 */
-	outw(0x3CE, 0x0500);    /* write mode 0, read mode 0 */
-	outw(0x3CE, 0x0605);    /* set graphics mode */
-
-	for (i = 0;  i < sizeof(font);  i += 16) {
-		for (j = 0;  j < 16;  j++) {
-			__asm__ volatile("eieio");
-			font_page[(2*i)+j] = font[i+j];
-		}
-	}
-}
-
-static void
-unlockS3(void)
-{
-        int s3_device_id;
-	outw(0x3d4, 0x3848);
-	outw(0x3d4, 0x39a5);
-	outb(0x3d4, 0x2d);
-	s3_device_id = inb(0x3d5) << 8;
-	outb(0x3d4, 0x2e);
-	s3_device_id |= inb(0x3d5);
-
-	if (s3_device_id != 0x8812) {
-		/* From the S3 manual */
-		outb(0x46E8, 0x10);  /* Put into setup mode */
-		outb(0x3C3, 0x10);
-		outb(0x102, 0x01);   /* Enable registers */
-		outb(0x46E8, 0x08);  /* Enable video */
-		outb(0x3C3, 0x08);
-		outb(0x4AE8, 0x00);
-
-#if 0
-		outb(0x42E8, 0x80);  /* Reset graphics engine? */
-#endif
-
-		outb(0x3D4, 0x38);  /* Unlock all registers */
-		outb(0x3D5, 0x48);
-		outb(0x3D4, 0x39);
-		outb(0x3D5, 0xA5);
-		outb(0x3D4, 0x40);
-		outb(0x3D5, inb(0x3D5)|0x01);
-		outb(0x3D4, 0x33);
-		outb(0x3D5, inb(0x3D5)&~0x52);
-		outb(0x3D4, 0x35);
-		outb(0x3D5, inb(0x3D5)&~0x30);
-		outb(0x3D4, 0x3A);
-		outb(0x3D5, 0x00);
-		outb(0x3D4, 0x53);
-		outb(0x3D5, 0x00);
-		outb(0x3D4, 0x31);
-		outb(0x3D5, inb(0x3D5)&~0x4B);
-		outb(0x3D4, 0x58);
-
-		outb(0x3D5, 0);
-
-		outb(0x3D4, 0x54);
-		outb(0x3D5, 0x38);
-		outb(0x3D4, 0x60);
-		outb(0x3D5, 0x07);
-		outb(0x3D4, 0x61);
-		outb(0x3D5, 0x80);
-		outb(0x3D4, 0x62);
-		outb(0x3D5, 0xA1);
-		outb(0x3D4, 0x69);  /* High order bits for cursor address */
-		outb(0x3D5, 0);
-
-		outb(0x3D4, 0x32);
-		outb(0x3D5, inb(0x3D5)&~0x10);
-	} else {
-                outw(0x3c4, 0x0806);            /* IBM Portable 860 */
-                outw(0x3c4, 0x1041);
-                outw(0x3c4, 0x1128);
-                outw(0x3d4, 0x4000);
-                outw(0x3d4, 0x3100);
-                outw(0x3d4, 0x3a05);
-                outw(0x3d4, 0x6688);
-                outw(0x3d4, 0x5800);            /* disable linear addressing */
-                outw(0x3d4, 0x4500);            /* disable H/W cursor */
-                outw(0x3c4, 0x5410);            /* enable auto-centering */
-                outw(0x3c4, 0x561f);
-                outw(0x3c4, 0x1b80);            /* lock DCLK selection */
-                outw(0x3d4, 0x3900);            /* lock S3 registers */
-                outw(0x3d4, 0x3800);
-	} /* endif */
-}
-
-/*
- * cursor() sets an offset (0-1999) into the 80x25 text area   
- */
-void
-cursor(int x, int y)
-{
-	int pos = (y*cols)+x;
-	outb(0x3D4, 14);
-	outb(0x3D5, pos >> 8);
-	outb(0x3D4, 15);
-	outb(0x3D5, pos);
-}
-
-clearVideoMemory()
-{
-	int i, j;
-	for (i = 0;  i < lines;  i++) {
-		for (j = 0;  j < cols;  j++) {
-			vidmem[((i*cols)+j)*2] = 0x20;	/* fill with space character */
-			vidmem[((i*cols)+j)*2+1] = 0x07;  /* set bg & fg attributes */
-		}
-	}
-}
-
-/* ============ */
-
-
-#define NSLOTS 8
-#define NPCIREGS  5
-
-
-/* 
- should use devfunc number/indirect method to be totally safe on 
- all machines, this works for now on 3 slot Moto boxes 
-*/
-
-struct PCI_ConfigInfo {
-  unsigned long * config_addr;
-  unsigned long regs[NPCIREGS];  
-} PCI_slots [NSLOTS] = {
-
-    { (unsigned long *)0x80808000, 0xDEADBEEF },   /* onboard */
-    { (unsigned long *)0x80800800, 0xDEADBEEF },   /* onboard */
-    { (unsigned long *)0x80801000, 0xDEADBEEF },   /* onboard */
-    { (unsigned long *)0x80802000, 0xDEADBEEF },   /* onboard */
-    { (unsigned long *)0x80804000, 0xDEADBEEF },   /* onboard */
-    { (unsigned long *)0x80810000, 0xDEADBEEF },   /* slot A/1 */
-    { (unsigned long *)0x80820000, 0xDEADBEEF },   /* slot B/2 */
-    { (unsigned long *)0x80840000, 0xDEADBEEF }    /* slot C/3 */
-};
-
-
-
-/*
- * The following code modifies the PCI Command register
- * to enable memory and I/O accesses.    
- */ 
-unlockVideo(slot)        
-{
-       volatile unsigned char * ppci;
-
-        ppci =  (unsigned char * )PCI_slots[slot].config_addr;
-	ppci[4] = 0x0003;         /* enable memory and I/O accesses */
-	ppci[0x10] = 0x00000;     /* turn off memory mapping */
-	ppci[0x11] = 0x00000;     /* mem_base = 0 */
-	ppci[0x12] = 0x00000;
-	ppci[0x13] = 0x00000;
-	__asm__ volatile("eieio");
-
-	outb(0x3d4, 0x11);
-	outb(0x3d5, 0x0e);   /* unlock CR0-CR7 */
-}
-
-long
-SwapBytes(long lv)   /* turn little endian into big indian long */
-{
-    long t;
-    t  = (lv&0x000000FF) << 24;
-    t |= (lv&0x0000FF00) << 8;
-    t |= (lv&0x00FF0000) >> 8;
-    t |= (lv&0xFF000000) >> 24;
-    return(t);
-}
-
-
-#define DEVID   0
-#define CMD     1
-#define CLASS   2
-#define MEMBASE 4
-
-int
-scanPCI(int start_slt)
-{
-	int slt, r;
-	struct PCI_ConfigInfo *pslot;
-	int theSlot = -1;
-	int highVgaSlot = 0;
-
-	for ( slt = start_slt + 1; slt < NSLOTS; slt++) {
-		pslot = &PCI_slots[slt];
-		for ( r = 0; r < NPCIREGS; r++) {
-			pslot->regs[r] = SwapBytes ( pslot->config_addr[r] );
-		}
-		/* card in slot ? */
-		if ( pslot->regs[DEVID] != 0xFFFFFFFF ) {     
-			/* VGA ? */
-			if ( ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) || 
-			     ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x00010000)) {
-				highVgaSlot = slt;
-				/* did firmware enable it ? */
-				if ( (pslot->regs[CMD] & 0x03) ) { 
-					theSlot = slt;
-					break;
-				}
-			}
-		}
-	}
-
-	return ( theSlot );
-}
-
-/* return Vendor ID of card in the slot */
-static
-int PCIVendor(int slotnum) {
- struct PCI_ConfigInfo *pslot;
-
- pslot = &PCI_slots[slotnum];
-
-return (pslot->regs[DEVID] & 0xFFFF);
-}
-
-static
-void printslots(void) 
-{
-	int i;
-	struct PCI_ConfigInfo *pslot;
-	for(i=0; i < NSLOTS; i++) {
-#if 0
-		pslot = &PCI_slots[i];
-		printf("Slot: %d, Addr: %x, Vendor: %08x, Class: %08x\n",
-		       i, pslot->config_addr, pslot->regs[0], pslot->regs[2]);
-#else
-		puts("PCI Slot number: "); puthex(i);
-		puts(" Vendor ID: "); 
-		puthex(PCIVendor(i)); puts("\n");
-#endif
-	}
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.4.4/linux/arch/ppc/chrpboot/Makefile	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/chrpboot/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,101 +0,0 @@
-# Makefile for making ELF bootable images for booting on CHRP
-# using Open Firmware.
-#
-# Geert Uytterhoeven	September 1997
-#
-# Based on coffboot by Paul Mackerras
-
-ifeq ($(CONFIG_PPC64BRIDGE),y)
-MSIZE=.64
-AFLAGS += -Wa,-mppc64bridge
-else
-MSIZE=
-endif
-
-.c.o:
-	$(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
-.S.o:
-	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
-
-CFLAGS	= $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS
-LD_ARGS = -Ttext 0x00400000
-
-OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o
-LIBS = $(TOPDIR)/lib/lib.a
-
-ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.chrp.smp$(MSIZE)
-else
-TFTPIMAGE=/tftpboot/zImage.chrp$(MSIZE)
-endif
-
-all:	$(TOPDIR)/zImage
-
-#
-# Only build anything here if we're configured for ALL_PPC
-# -- cort
-#
-ifeq ($(CONFIG_ALL_PPC),y)
-znetboot: zImage
-	cp zImage $(TFTPIMAGE)
-
-znetboot.initrd: zImage.initrd
-	cp zImage.initrd $(TFTPIMAGE)
-
-floppy: zImage
-	mcopy zImage a:zImage
-
-piggyback: piggyback.c
-	$(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
-
-addnote: addnote.c
-	$(HOSTCC) $(HOSTCFLAGS) -o addnote addnote.c
-
-image.o: piggyback ../coffboot/vmlinux.gz
-	./piggyback image < ../coffboot/vmlinux.gz | $(AS) -o image.o
-
-sysmap.o: piggyback ../../../System.map
-	./piggyback sysmap < ../../../System.map | $(AS) -o sysmap.o
-
-initrd.o: ramdisk.image.gz piggyback
-	./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o
-
-zImage: $(OBJS) no_initrd.o addnote
-	$(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
-	cp $@ $@.rs6k
-	./addnote $@.rs6k
-
-zImage.initrd: $(OBJS) initrd.o addnote
-	$(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
-	cp $@ $@.rs6k
-	./addnote $@.rs6k
-
-else
-znetboot:
-
-znetboot.initrd:
-
-floppy:
-
-zImage:
-
-zImage.initrd:
-
-endif
-
-# just here to match coffboot/Makefile
-vmlinux.coff:
-
-vmlinux.coff.initrd:
-
-
-clean:
-	rm -f piggyback note addnote $(OBJS) zImage
-	rm -f zImage.rs6k zImage.initrd zImage.initrd.rs6k
-
-fastdep:
-	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
-
-dep:
-	$(CPP) $(CPPFLAGS) -M *.S *.c > .depend
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/addnote.c linux/arch/ppc/chrpboot/addnote.c
--- v2.4.4/linux/arch/ppc/chrpboot/addnote.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/chrpboot/addnote.c	Wed Dec 31 16:00:00 1969
@@ -1,174 +0,0 @@
-/*
- * Program to hack in a PT_NOTE program header entry in an ELF file.
- * This is needed for OF on RS/6000s to load an image correctly.
- * Note that OF needs a program header entry for the note, not an
- * ELF section.
- *
- * Copyright 2000 Paul Mackerras.
- *
- * 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.
- *
- * Usage: addnote zImage
- */
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-char arch[] = "PowerPC";
-
-#define N_DESCR	6
-unsigned int descr[N_DESCR] = {
-#if 1
-	/* values for IBM RS/6000 machines */
-	0xffffffff,		/* real-mode = true */
-	0x00c00000,		/* real-base, i.e. where we expect OF to be */
-	0xffffffff,		/* real-size */
-	0xffffffff,		/* virt-base */
-	0xffffffff,		/* virt-size */
-	0x4000,			/* load-base */
-#else
-	/* values for longtrail CHRP */
-	0,			/* real-mode = false */
-	0xffffffff,		/* real-base */
-	0xffffffff,		/* real-size */
-	0xffffffff,		/* virt-base */
-	0xffffffff,		/* virt-size */
-	0x00600000,		/* load-base */
-#endif
-};
-
-unsigned char buf[512];
-
-#define GET_16BE(off)	((buf[off] << 8) + (buf[(off)+1]))
-#define GET_32BE(off)	((GET_16BE(off) << 16) + GET_16BE((off)+2))
-
-#define PUT_16BE(off, v)	(buf[off] = ((v) >> 8) & 0xff, \
-				 buf[(off) + 1] = (v) & 0xff)
-#define PUT_32BE(off, v)	(PUT_16BE((off), (v) >> 16), \
-				 PUT_16BE((off) + 2, (v)))
-
-/* Structure of an ELF file */
-#define E_IDENT		0	/* ELF header */
-#define	E_PHOFF		28
-#define E_PHENTSIZE	42
-#define E_PHNUM		44
-#define E_HSIZE		52	/* size of ELF header */
-
-#define EI_MAGIC	0	/* offsets in E_IDENT area */
-#define EI_CLASS	4
-#define EI_DATA		5
-
-#define PH_TYPE		0	/* ELF program header */
-#define PH_OFFSET	4
-#define PH_FILESZ	16
-#define PH_HSIZE	32	/* size of program header */
-
-#define PT_NOTE		4	/* Program header type = note */
-
-#define ELFCLASS32	1
-#define ELFDATA2MSB	2
-
-unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
-
-int main(int ac, char **av)
-{
-	int fd, n, i;
-	int ph, ps, np;
-	int nnote, ns;
-
-	if (ac != 2) {
-		fprintf(stderr, "Usage: %s elf-file\n", av[0]);
-		exit(1);
-	}
-	fd = open(av[1], O_RDWR);
-	if (fd < 0) {
-		perror(av[1]);
-		exit(1);
-	}
-
-	nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
-
-	n = read(fd, buf, sizeof(buf));
-	if (n < 0) {
-		perror("read");
-		exit(1);
-	}
-
-	if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
-		goto notelf;
-
-	if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
-	    || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
-		fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
-			av[1]);
-		exit(1);
-	}
-
-	ph = GET_32BE(E_PHOFF);
-	ps = GET_16BE(E_PHENTSIZE);
-	np = GET_16BE(E_PHNUM);
-	if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
-		goto notelf;
-	if (ph + (np + 1) * ps + nnote > n)
-		goto nospace;
-
-	for (i = 0; i < np; ++i) {
-		if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
-			fprintf(stderr, "%s already has a note entry\n",
-				av[1]);
-			exit(0);
-		}
-		ph += ps;
-	}
-
-	/* XXX check that the area we want to use is all zeroes */
-	for (i = 0; i < ps + nnote; ++i)
-		if (buf[ph + i] != 0)
-			goto nospace;
-
-	/* fill in the program header entry */
-	ns = ph + ps;
-	PUT_32BE(ph + PH_TYPE, PT_NOTE);
-	PUT_32BE(ph + PH_OFFSET, ns);
-	PUT_32BE(ph + PH_FILESZ, nnote);
-
-	/* fill in the note area we point to */
-	/* XXX we should probably make this a proper section */
-	PUT_32BE(ns, strlen(arch) + 1);
-	PUT_32BE(ns + 4, N_DESCR * 4);
-	PUT_32BE(ns + 8, 0x1275);
-	strcpy(&buf[ns + 12], arch);
-	ns += 12 + strlen(arch) + 1;
-	for (i = 0; i < N_DESCR; ++i)
-		PUT_32BE(ns + i * 4, descr[i]);
-
-	/* Update the number of program headers */
-	PUT_16BE(E_PHNUM, np + 1);
-
-	/* write back */
-	lseek(fd, (long) 0, SEEK_SET);
-	i = write(fd, buf, n);
-	if (i < 0) {
-		perror("write");
-		exit(1);
-	}
-	if (i < n) {
-		fprintf(stderr, "%s: write truncated\n", av[1]);
-		exit(1);
-	}
-
-	exit(0);
-
- notelf:
-	fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
-	exit(1);
-
- nospace:
-	fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
-		av[0]);
-	exit(1);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/crt0.S linux/arch/ppc/chrpboot/crt0.S
--- v2.4.4/linux/arch/ppc/chrpboot/crt0.S	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/chrpboot/crt0.S	Wed Dec 31 16:00:00 1969
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-	.text
-	.globl	_start
-_start:
-	lis	9,_start@h
-	lis	8,_etext@ha
-	addi	8,8,_etext@l
-1:	dcbf	0,9
-	icbi	0,9
-	addi	9,9,0x20
-	cmplwi	0,9,8
-	blt	1b
-	b	start
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- v2.4.4/linux/arch/ppc/chrpboot/main.c	Mon Jun 19 17:59:35 2000
+++ linux/arch/ppc/chrpboot/main.c	Wed Dec 31 16:00:00 1969
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 "../coffboot/nonstdio.h"
-#include "../coffboot/zlib.h"
-#include <asm/bootinfo.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-
-extern void *finddevice(const char *);
-extern int getprop(void *, const char *, void *, int);
-void gunzip(void *, int, unsigned char *, int *);
-
-#define RAM_START	0x00000000
-#define RAM_END		(64<<20)
-
-#define BOOT_START	((unsigned long)_start)
-#define BOOT_END	((unsigned long)(_end + 0xFFF) & ~0xFFF)
-
-#define RAM_FREE	((unsigned long)(_end+0x1000)&~0xFFF)
-#define PROG_START	0x00010000
-
-char *avail_ram;
-char *end_avail;
-
-extern char _end[];
-extern char image_data[];
-extern int image_len;
-extern char initrd_data[];
-extern int initrd_len;
-extern char sysmap_data[];
-extern int sysmap_len;
-
-static char scratch[1024<<10];	/* 1MB of scratch space for gunzip */
-
-chrpboot(int a1, int a2, void *prom)
-{
-    int ns, oh, i;
-    unsigned sa, len;
-    void *dst;
-    unsigned char *im;
-    unsigned initrd_start, initrd_size;
-    extern char _start;
-    
-    printf("chrpboot starting: loaded at 0x%x\n\r", &_start);
-
-    if (initrd_len) {
-	initrd_size = initrd_len;
-	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
-	a1 = initrd_start;
-	a2 = initrd_size;
-	claim(initrd_start, RAM_END - initrd_start, 0);
-	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r",
-	       initrd_start, initrd_data, initrd_size);
-	memcpy((char *)initrd_start, initrd_data, initrd_size);
-    }
-
-    im = image_data;
-    len = image_len;
-    /* claim 4MB starting at PROG_START */
-    claim(PROG_START, (4<<20) - PROG_START, 0);
-    dst = (void *) PROG_START;
-    if (im[0] == 0x1f && im[1] == 0x8b) {
-	avail_ram = scratch;
-	end_avail = scratch + sizeof(scratch);
-	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
-	gunzip(dst, 0x400000, im, &len);
-	printf("done %u bytes\n\r", len);
-    } else {
-	memmove(dst, im, len);
-    }
-
-    flush_cache(dst, len);
-    
-    sa = (unsigned long)PROG_START;
-    printf("start address = 0x%x\n\r", sa);
-
-    {
-	    struct bi_record *rec;
-	    
-	    rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20));
-
-	    rec->tag = BI_FIRST;
-	    rec->size = sizeof(struct bi_record);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	    rec->tag = BI_BOOTLOADER_ID;
-	    sprintf( (char *)rec->data, "chrpboot");
-	    rec->size = sizeof(struct bi_record) + strlen("chrpboot") + 1;
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	    rec->tag = BI_MACHTYPE;
-	    rec->data[0] = _MACH_chrp;
-	    rec->data[1] = 1;
-	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-#if 0
-	    rec->tag = BI_SYSMAP;
-	    rec->data[0] = (unsigned long)sysmap_data;
-	    rec->data[1] = sysmap_len;
-	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-#endif
-	    rec->tag = BI_LAST;
-	    rec->size = sizeof(struct bi_record);
-	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-    }
-    (*(void (*)())sa)(a1, a2, prom);
-
-    printf("returned?\n\r");
-
-    pause();
-}
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-    void *p = avail_ram;
-
-    size *= items;
-    size = (size + 7) & -8;
-    avail_ram += size;
-    if (avail_ram > end_avail) {
-	printf("oops... out of memory\n\r");
-	pause();
-    }
-    return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-    nb = (nb + 7) & -8;
-    if (addr == (avail_ram - nb)) {
-	avail_ram -= nb;
-    }
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n\r");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n\r");
-	exit();
-    }
-
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n\r", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d msg: %s\n\r", r, s.msg);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/misc.S linux/arch/ppc/chrpboot/misc.S
--- v2.4.4/linux/arch/ppc/chrpboot/misc.S	Tue Apr 14 17:33:57 1998
+++ linux/arch/ppc/chrpboot/misc.S	Wed Dec 31 16:00:00 1969
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-	.text
-
-/*
- * Use the BAT0 registers to map the 1st 8MB of RAM to 0x90000000.
- */
-	.globl	setup_bats
-setup_bats:
-	mfpvr	3
-	rlwinm	3,3,16,16,31		/* r3 = 1 for 601, 4 for 604 */
-	cmpi	0,3,1
-	lis	4,0x9000
-	bne	4f
-	ori	4,4,4			/* set up BAT registers for 601 */
-	li	5,0x7f
-	b	5f
-4:	ori	4,4,0xff		/* set up BAT registers for 604 */
-	li	5,2
-	mtdbatu	3,4
-	mtdbatl	3,5
-5:	mtibatu	3,4
-	mtibatl	3,5
-	isync
-	blr
-
-/*
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
-	.global	flush_cache
-flush_cache:
-	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
-	rlwinm.	4,4,27,5,31
-	mtctr	4
-	beqlr
-1:	dcbf	0,3
-	icbi	0,3
-	addi	3,3,0x20
-	bdnz	1b
-	sync
-	isync
-	blr
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/mknote.c linux/arch/ppc/chrpboot/mknote.c
--- v2.4.4/linux/arch/ppc/chrpboot/mknote.c	Mon Jun  7 12:11:51 1999
+++ linux/arch/ppc/chrpboot/mknote.c	Wed Dec 31 16:00:00 1969
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) Cort Dougan 1999.
- *
- * 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.
- *
- * Generate a note section as per the CHRP specification.
- *
- */
-
-#include <stdio.h>
-
-#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
-
-int main(void)
-{
-/* header */
-	/* namesz */
-	PL(strlen("PowerPC")+1);
-	/* descrsz */
-	PL(6*4);
-	/* type */
-	PL(0x1275);
-	/* name */
-	printf("PowerPC"); printf("%c", 0);
-	
-/* descriptor */
-	/* real-mode */
-	PL(0xffffffff);
-	/* real-base */
-	PL(0x00c00000);
-	/* real-size */
-	PL(0xffffffff);
-	/* virt-base */
-	PL(0xffffffff);
-	/* virt-size */
-	PL(0xffffffff);
-	/* load-base */
-	PL(0x4000);
-	return 0;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/no_initrd.c linux/arch/ppc/chrpboot/no_initrd.c
--- v2.4.4/linux/arch/ppc/chrpboot/no_initrd.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/chrpboot/no_initrd.c	Wed Dec 31 16:00:00 1969
@@ -1,2 +0,0 @@
-char initrd_data[1];
-int initrd_len = 0;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/piggyback.c linux/arch/ppc/chrpboot/piggyback.c
--- v2.4.4/linux/arch/ppc/chrpboot/piggyback.c	Tue Feb 22 22:27:43 2000
+++ linux/arch/ppc/chrpboot/piggyback.c	Wed Dec 31 16:00:00 1969
@@ -1,66 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-
-extern long ce_exec_config[];
-
-int main(int argc, char *argv[])
-{
-	int i, cnt, pos, len;
-	unsigned int cksum, val;
-	unsigned char *lp;
-	unsigned char buf[8192];
-	if (argc != 2)
-	{
-		fprintf(stderr, "usage: %s name <in-file >out-file\n",
-			argv[0]);
-		exit(1);
-	}
-	fprintf(stdout, "#\n");
-	fprintf(stdout, "# Miscellaneous data structures:\n");
-	fprintf(stdout, "# WARNING - this file is automatically generated!\n");
-	fprintf(stdout, "#\n");
-	fprintf(stdout, "\n");
-	fprintf(stdout, "\t.data\n");
-	fprintf(stdout, "\t.globl %s_data\n", argv[1]);
-	fprintf(stdout, "%s_data:\n", argv[1]);
-	pos = 0;
-	cksum = 0;
-	while ((len = read(0, buf, sizeof(buf))) > 0)
-	{
-		cnt = 0;
-		lp = (unsigned char *)buf;
-		len = (len + 3) & ~3;  /* Round up to longwords */
-		for (i = 0;  i < len;  i += 4)
-		{
-			if (cnt == 0)
-			{
-				fprintf(stdout, "\t.long\t");
-			}
-			fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
-			val = *(unsigned long *)lp;
-			cksum ^= val;
-			lp += 4;
-			if (++cnt == 4)
-			{
-				cnt = 0;
-				fprintf(stdout, " # %x \n", pos+i-12);
-				fflush(stdout);
-			} else
-			{
-				fprintf(stdout, ",");
-			}
-		}
-		if (cnt)
-		{
-			fprintf(stdout, "0\n");
-		}
-		pos += len;
-	}
-	fprintf(stdout, "\t.globl %s_len\n", argv[1]);
-	fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos);
-	fflush(stdout);
-	fclose(stdout);
-	fprintf(stderr, "cksum = %x\n", cksum);
-	exit(0);
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/chrpboot/start.c linux/arch/ppc/chrpboot/start.c
--- v2.4.4/linux/arch/ppc/chrpboot/start.c	Mon Jun 19 17:59:35 2000
+++ linux/arch/ppc/chrpboot/start.c	Wed Dec 31 16:00:00 1969
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 <stdarg.h>
-
-int (*prom)();
-
-void *chosen_handle;
-void *stdin;
-void *stdout;
-void *stderr;
-
-void exit(void);
-void *finddevice(const char *name);
-int getprop(void *phandle, const char *name, void *buf, int buflen);
-
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
-    prom = (int (*)()) promptr;
-    chosen_handle = finddevice("/chosen");
-    if (chosen_handle == (void *) -1)
-	exit();
-    if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
-	exit();
-    stderr = stdout;
-    if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
-	exit();
-
-    chrpboot(a1, a2, promptr);
-    for (;;)
-	exit();
-}
-
-int
-write(void *handle, void *ptr, int nb)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	void *ihandle;
-	void *addr;
-	int len;
-	int actual;
-    } args;
-
-    args.service = "write";
-    args.nargs = 3;
-    args.nret = 1;
-    args.ihandle = handle;
-    args.addr = ptr;
-    args.len = nb;
-    args.actual = -1;
-    (*prom)(&args);
-    return args.actual;
-}
-
-int
-read(void *handle, void *ptr, int nb)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	void *ihandle;
-	void *addr;
-	int len;
-	int actual;
-    } args;
-
-    args.service = "read";
-    args.nargs = 3;
-    args.nret = 1;
-    args.ihandle = handle;
-    args.addr = ptr;
-    args.len = nb;
-    args.actual = -1;
-    (*prom)(&args);
-    return args.actual;
-}
-
-void
-exit()
-{
-    struct prom_args {
-	char *service;
-    } args;
-
-    for (;;) {
-	args.service = "exit";
-	(*prom)(&args);
-    }
-}
-
-void
-pause()
-{
-    struct prom_args {
-	char *service;
-    } args;
-
-    args.service = "enter";
-    (*prom)(&args);
-}
-
-void *
-finddevice(const char *name)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	const char *devspec;
-	void *phandle;
-    } args;
-
-    args.service = "finddevice";
-    args.nargs = 1;
-    args.nret = 1;
-    args.devspec = name;
-    args.phandle = (void *) -1;
-    (*prom)(&args);
-    return args.phandle;
-}
-
-void *
-claim(unsigned int virt, unsigned int size, unsigned int align)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	unsigned int virt;
-	unsigned int size;
-	unsigned int align;
-	void *ret;
-    } args;
-
-    args.service = "claim";
-    args.nargs = 3;
-    args.nret = 1;
-    args.virt = virt;
-    args.size = size;
-    args.align = align;
-    (*prom)(&args);
-    return args.ret;
-}
-
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	void *phandle;
-	const char *name;
-	void *buf;
-	int buflen;
-	int size;
-    } args;
-
-    args.service = "getprop";
-    args.nargs = 4;
-    args.nret = 1;
-    args.phandle = phandle;
-    args.name = name;
-    args.buf = buf;
-    args.buflen = buflen;
-    args.size = -1;
-    (*prom)(&args);
-    return args.size;
-}
-
-int
-putc(int c, void *f)
-{
-    char ch = c;
-
-    if (c == '\n')
-	putc('\r', f);
-    return write(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
-    return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
-    int n = strlen(str);
-
-    return write(f, str, n) == n? 0: -1;
-}
-
-int
-readchar()
-{
-    char ch;
-
-    for (;;) {
-	switch (read(stdin, &ch, 1)) {
-	case 1:
-	    return ch;
-	case -1:
-	    printk("read(stdin) returned -1\r\n");
-	    return -1;
-	}
-    }
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar()
-{
-    int c;
-
-    if (lineleft == 0) {
-	lineptr = line;
-	for (;;) {
-	    c = readchar();
-	    if (c == -1 || c == 4)
-		break;
-	    if (c == '\r' || c == '\n') {
-		*lineptr++ = '\n';
-		putchar('\n');
-		break;
-	    }
-	    switch (c) {
-	    case 0177:
-	    case '\b':
-		if (lineptr > line) {
-		    putchar('\b');
-		    putchar(' ');
-		    putchar('\b');
-		    --lineptr;
-		}
-		break;
-	    case 'U' & 0x1F:
-		while (lineptr > line) {
-		    putchar('\b');
-		    putchar(' ');
-		    putchar('\b');
-		    --lineptr;
-		}
-		break;
-	    default:
-		if (lineptr >= &line[sizeof(line) - 1])
-		    putchar('\a');
-		else {
-		    putchar(c);
-		    *lineptr++ = c;
-		}
-	    }
-	}
-	lineleft = lineptr - line;
-	lineptr = line;
-    }
-    if (lineleft == 0)
-	return -1;
-    --lineleft;
-    return *lineptr++;
-}
-
-extern int vsprintf(char *buf, const char *fmt, va_list args);
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	write(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	write(stdout, sprint_buf, n);
-	return n;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.4.4/linux/arch/ppc/coffboot/Makefile	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/coffboot/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,131 +0,0 @@
-# Makefile for making XCOFF bootable images for booting on PowerMacs
-# using Open Firmware.
-#
-# Paul Mackerras	January 1997
-
-HOSTCFLAGS = -O -I$(TOPDIR)/include
-
-CFLAGS	= $(CPPFLAGS) -O -fno-builtin
-OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
-COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic
-CHRP_LD_ARGS = -Ttext 0x01000000
-
-COFFOBJS = coffcrt0.o start.o coffmain.o misc.o string.o zlib.o image.o
-CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o
-LIBS = $(TOPDIR)/lib/lib.a
-
-ifeq ($(CONFIG_PPC64BRIDGE),y)
-MSIZE=.64
-else
-MSIZE=
-endif
-
-ifeq ($(CONFIG_SMP),y)
-TFTPIMAGE=/tftpboot/zImage.pmac.smp$(MSIZE)
-else
-TFTPIMAGE=/tftpboot/zImage.pmac$(MSIZE)
-endif
-
-ifeq ($(CONFIG_ALL_PPC),y)
-chrpmain.o: chrpmain.c
-	$(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c
-
-hack-coff: hack-coff.c
-	$(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c
-
-znetboot: vmlinux.coff vmlinux.elf zImage
-	cp vmlinux.coff $(TFTPIMAGE)
-	cp vmlinux.elf $(TFTPIMAGE).elf
-
-znetboot.initrd: vmlinux.coff.initrd vmlinux.elf.initrd
-	cp vmlinux.coff.initrd $(TFTPIMAGE)
-	cp vmlinux.elf.initrd $(TFTPIMAGE).elf
-
-floppy: zImage
-#	mount -t hfs /dev/fd0 /mnt
-#	cp vmlinux.coff /mnt
-#	umount /mnt
-
-miboot.image: dummy.o vmlinux.gz
-	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz dummy.o $@
-
-miboot.image.initrd: miboot.image ramdisk.image.gz
-	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz miboot.image $@
-
-coffboot: $(COFFOBJS) no_initrd.o ld.script
-	$(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) no_initrd.o $(LIBS)
-
-coffboot.initrd: $(COFFOBJS) initrd.o ld.script
-	$(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) initrd.o $(LIBS)
-
-piggyback: piggyback.c
-	$(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
-
-mknote: mknote.c
-	$(HOSTCC) $(HOSTCFLAGS) -o mknote mknote.c
-
-image.o: piggyback vmlinux.gz
-	./piggyback image < vmlinux.gz | $(AS) -o image.o
-
-initrd.o: ramdisk.image.gz piggyback
-	./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o
-
-vmlinux.coff: coffboot hack-coff
-	$(OBJCOPY) $(OBJCOPY_ARGS) coffboot $@
-	./hack-coff $@
-	ln -sf vmlinux.coff zImage
-
-vmlinux.coff.initrd: coffboot.initrd hack-coff
-	$(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd $@
-	./hack-coff $@
-
-vmlinux.elf: $(CHRPOBJS) no_initrd.o mknote
-	$(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) no_initrd.o $(LIBS)
-	./mknote > note
-	$(OBJCOPY) $@ $@ --add-section=.note=note \
-		--add-section=sysmap=../../../System.map -R .comment
-	$(CC) $(CFLAGS) chrpmain.c -c -o chrpmain.o \
-		-DSYSMAP_OFFSET=`sh ../boot/offset $(OBJDUMP) $@ sysmap` \
-		-DSYSMAP_SIZE=`sh ../boot/size $(OBJDUMP) $@ sysmap`
-	$(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) no_initrd.o $(LIBS)
-	$(OBJCOPY) $@ $@ --add-section=.note=note \
-		--add-section=sysmap=../../../System.map -R .comment
-
-vmlinux.elf.initrd: $(CHRPOBJS) initrd.o mknote
-	$(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) initrd.o $(LIBS)
-	./mknote > note
-	$(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
-
-zImage: vmlinux.coff vmlinux.elf miboot.image
-
-zImage.initrd: vmlinux.coff.initrd vmlinux.elf.initrd miboot.image.initrd
-
-else
-znetboot: vmlinux.gz
-
-znetboot.initrd: vmlinux.gz
-
-coffboot: vmlinux.gz
-
-zImage: vmlinux.gz
-
-zImage.initrd: vmlinux.gz
-
-vmlinux.coff: vmlinux.gz
-
-vmlinux.coff.initrd: vmlinux.gz
-
-floppy: vmlinux.gz
-
-endif
-
-vmlinux.gz: $(TOPDIR)/vmlinux
-	$(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux
-	gzip -vf9 vmlinux
-
-clean:
-	rm -f hack-coff coffboot zImage vmlinux.coff vmlinux.gz
-	rm -f mknote piggyback vmlinux.elf note
-	rm -f miboot.image miboot.image.initrd
-
-fastdep:
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/chrpmain.c linux/arch/ppc/coffboot/chrpmain.c
--- v2.4.4/linux/arch/ppc/coffboot/chrpmain.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/coffboot/chrpmain.c	Wed Dec 31 16:00:00 1969
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 "nonstdio.h"
-#include "zlib.h"
-#include <asm/bootinfo.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-
-extern void *finddevice(const char *);
-extern int getprop(void *, const char *, void *, int);
-void make_bi_recs(unsigned long);
-void gunzip(void *, int, unsigned char *, int *);
-void stop_imac_ethernet(void);
-void stop_imac_usb(void);
-
-#define get_16be(x)	(*(unsigned short *)(x))
-#define get_32be(x)	(*(unsigned *)(x))
-
-#define RAM_END		(16 << 20)
-
-#define PROG_START	0x00010000
-#define PROG_SIZE	0x003f0000
-
-#define SCRATCH_SIZE	(128 << 10)
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-unsigned int heap_use;
-unsigned int heap_max;
-
-extern char _end[];
-extern char image_data[];
-extern int image_len;
-extern char initrd_data[];
-extern int initrd_len;
-
-
-boot(int a1, int a2, void *prom)
-{
-    int ns, oh, i;
-    unsigned sa, len;
-    void *dst;
-    unsigned char *im;
-    unsigned initrd_start, initrd_size;
-    extern char _start;
-    
-    printf("chrpboot starting: loaded at 0x%x\n", &_start);
-    if (initrd_len) {
-	initrd_size = initrd_len;
-	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
-	a1 = initrd_start;
-	a2 = initrd_size;
-	claim(initrd_start, RAM_END - initrd_start, 0);
-	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n", initrd_start,
-	       initrd_data,initrd_size);
-	memcpy((char *)initrd_start, initrd_data, initrd_size);
-    }
-    im = image_data;
-    len = image_len;
-    /* claim 3MB starting at PROG_START */
-    claim(PROG_START, PROG_SIZE, 0);
-    dst = (void *) PROG_START;
-    if (im[0] == 0x1f && im[1] == 0x8b) {
-	/* claim some memory for scratch space */
-	avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
-	begin_avail = avail_high = avail_ram;
-	end_avail = avail_ram + SCRATCH_SIZE;
-	printf("heap at 0x%x\n", avail_ram);
-	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
-	gunzip(dst, PROG_SIZE, im, &len);
-	printf("done %u bytes\n", len);
-	printf("%u bytes of heap consumed, max in use %u\n",
-	       avail_high - begin_avail, heap_max);
-    } else {
-	memmove(dst, im, len);
-    }
-
-    flush_cache(dst, len);
-    make_bi_recs((unsigned long) dst + len);
-
-    sa = (unsigned long)PROG_START;
-    printf("start address = 0x%x\n", sa);
-
-    (*(void (*)())sa)(a1, a2, prom);
-
-    printf("returned?\n");
-
-    pause();
-}
-
-void make_bi_recs(unsigned long addr)
-{
-	struct bi_record *rec;
-	rec = (struct bi_record *)_ALIGN((unsigned long)addr+(1<<20)-1,(1<<20));
-	    
-	rec->tag = BI_FIRST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	rec->tag = BI_BOOTLOADER_ID;
-	sprintf( (char *)rec->data, "coffboot");
-	rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1;
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	rec->tag = BI_MACHTYPE;
-	rec->data[0] = _MACH_Pmac;
-	rec->data[1] = 1;
-	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	
-#ifdef SYSMAP_OFFSET
-	rec->tag = BI_SYSMAP;
-	rec->data[0] = SYSMAP_OFFSET;
-	rec->data[1] = SYSMAP_SIZE;
-	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-#endif /* SYSMAP_OFFSET */
-	
-	rec->tag = BI_LAST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-}
-
-#if 0
-#define eieio()	asm volatile("eieio");
-
-void stop_imac_ethernet(void)
-{
-    void *macio, *enet;
-    unsigned int macio_addr[5], enet_reg[6];
-    int len;
-    volatile unsigned int *dbdma;
-
-    macio = finddevice("/pci/mac-io");
-    enet = finddevice("/pci/mac-io/ethernet");
-    if (macio == NULL || enet == NULL)
-	return;
-    len = getprop(macio, "assigned-addresses", macio_addr, sizeof(macio_addr));
-    if (len != sizeof(macio_addr))
-	return;
-    len = getprop(enet, "reg", enet_reg, sizeof(enet_reg));
-    if (len != sizeof(enet_reg))
-	return;
-    printf("macio base %x, dma at %x & %x\n",
-	   macio_addr[2], enet_reg[2], enet_reg[4]);
-
-    /* hope this is mapped... */
-    dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[2]);
-    *dbdma = 0x80;	/* clear the RUN bit */
-    eieio();
-    dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[4]);
-    *dbdma = 0x80;	/* clear the RUN bit */
-    eieio();
-}
-
-void stop_imac_usb(void)
-{
-    void *usb;
-    unsigned int usb_addr[5];
-    int len;
-    volatile unsigned int *usb_ctrl;
-
-    usb = finddevice("/pci/usb");
-    if (usb == NULL)
-	return;
-    len = getprop(usb, "assigned-addresses", usb_addr, sizeof(usb_addr));
-    if (len != sizeof(usb_addr))
-	return;
-    printf("usb base %x\n", usb_addr[2]);
-
-    usb_ctrl = (volatile unsigned int *) (usb_addr[2] + 8);
-    *usb_ctrl = 0x01000000;	/* cpu_to_le32(1) */
-    eieio();
-}
-#endif
-
-struct memchunk {
-    unsigned int size;
-    struct memchunk *next;
-};
-
-static struct memchunk *freechunks;
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-    void *p;
-    struct memchunk **mpp, *mp;
-
-    size *= items;
-    size = (size + 7) & -8;
-    heap_use += size;
-    if (heap_use > heap_max)
-	heap_max = heap_use;
-    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
-	if (mp->size == size) {
-	    *mpp = mp->next;
-	    return mp;
-	}
-    }
-    p = avail_ram;
-    avail_ram += size;
-    if (avail_ram > avail_high)
-	avail_high = avail_ram;
-    if (avail_ram > end_avail) {
-	printf("oops... out of memory\n");
-	pause();
-    }
-    return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-    struct memchunk *mp = addr;
-
-    nb = (nb + 7) & -8;
-    heap_use -= nb;
-    if (avail_ram == addr + nb) {
-	avail_ram = addr;
-	return;
-    }
-    mp->size = nb;
-    mp->next = freechunks;
-    freechunks = mp;
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n");
-	exit();
-    }
-
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d msg: %s\n", r, s.msg);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/coffcrt0.S linux/arch/ppc/coffboot/coffcrt0.S
--- v2.4.4/linux/arch/ppc/coffboot/coffcrt0.S	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/coffboot/coffcrt0.S	Wed Dec 31 16:00:00 1969
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-	.text
-	.globl	_start
-_start:
-	.long	__start,0,0
-
-	.globl	__start
-__start:
-	lis	9,_start@h
-	lis	8,_etext@ha
-	addi	8,8,_etext@l
-1:	dcbf	0,9
-	icbi	0,9
-	addi	9,9,0x20
-	cmplwi	0,9,8
-	blt	1b
-	b	start
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/coffmain.c linux/arch/ppc/coffboot/coffmain.c
--- v2.4.4/linux/arch/ppc/coffboot/coffmain.c	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/coffboot/coffmain.c	Wed Dec 31 16:00:00 1969
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 "nonstdio.h"
-#include "zlib.h"
-#include <asm/bootinfo.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-
-extern void *finddevice(const char *);
-extern int getprop(void *, const char *, void *, int);
-extern char *claim(unsigned, unsigned, unsigned);
-void make_bi_recs(unsigned long);
-void gunzip(void *, int, unsigned char *, int *);
-
-#define get_16be(x)	(*(unsigned short *)(x))
-#define get_32be(x)	(*(unsigned *)(x))
-
-#define RAM_START	0xc0000000
-#define RAM_END		(RAM_START + 0x800000)	/* only 8M mapped with BATs */
-
-#define PROG_START	RAM_START
-#define PROG_SIZE	0x00400000
-
-#define SCRATCH_SIZE	(128 << 10)
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-unsigned int heap_use;
-unsigned int heap_max;
-
-extern char _start[], _end[];
-extern char image_data[];
-extern int image_len;
-extern char initrd_data[];
-extern int initrd_len;
-
-char heap[SCRATCH_SIZE];
-
-boot(int a1, int a2, void *prom)
-{
-    int ns, oh, i;
-    unsigned sa, len;
-    void *dst;
-    unsigned char *im;
-    unsigned initrd_start, initrd_size;
-    
-    printf("coffboot starting: loaded at 0x%x\n", _start);
-    setup_bats(RAM_START);
-    if (initrd_len) {
-	initrd_size = initrd_len;
-	initrd_start = (RAM_END - initrd_size) & ~0xFFF;
-	a1 = initrd_start;
-	a2 = initrd_size;
-	claim(initrd_start - RAM_START, RAM_END - initrd_start, 0);
-	printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n",
-	       initrd_start, initrd_data, initrd_size);
-	memcpy((char *)initrd_start, initrd_data, initrd_size);
-    }
-    im = image_data;
-    len = image_len;
-    /* claim 3MB starting at 0 */
-    claim(0, PROG_SIZE, 0);
-    dst = (void *) RAM_START;
-    if (im[0] == 0x1f && im[1] == 0x8b) {
-	/* claim some memory for scratch space */
-	begin_avail = avail_high = avail_ram = heap;
-	end_avail = heap + sizeof(heap);
-	printf("heap at 0x%x\n", avail_ram);
-	printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len);
-	gunzip(dst, PROG_SIZE, im, &len);
-	printf("done %u bytes\n", len);
-	printf("%u bytes of heap consumed, max in use %u\n",
-	       avail_high - begin_avail, heap_max);
-    } else {
-	memmove(dst, im, len);
-    }
-
-    flush_cache(dst, len);
-    make_bi_recs((unsigned long)dst + len);
-    
-    sa = (unsigned long)PROG_START;
-    printf("start address = 0x%x\n", sa);
-
-    (*(void (*)())sa)(a1, a2, prom);
-
-    printf("returned?\n");
-
-    pause();
-}
-
-void make_bi_recs(unsigned long addr)
-{
-	struct bi_record *rec;
-
-	rec = (struct bi_record *)PAGE_ALIGN(addr);
-	    
-	rec->tag = BI_FIRST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	rec->tag = BI_BOOTLOADER_ID;
-	sprintf( (char *)rec->data, "coffboot");
-	rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1;
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	rec->tag = BI_MACHTYPE;
-	rec->data[0] = _MACH_Pmac;
-	rec->data[1] = 1;
-	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
-	rec->tag = BI_LAST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-}
-
-struct memchunk {
-    unsigned int size;
-    struct memchunk *next;
-};
-
-static struct memchunk *freechunks;
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-    void *p;
-    struct memchunk **mpp, *mp;
-
-    size *= items;
-    size = (size + 7) & -8;
-    heap_use += size;
-    if (heap_use > heap_max)
-	heap_max = heap_use;
-    for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) {
-	if (mp->size == size) {
-	    *mpp = mp->next;
-	    return mp;
-	}
-    }
-    p = avail_ram;
-    avail_ram += size;
-    if (avail_ram > avail_high)
-	avail_high = avail_ram;
-    if (avail_ram > end_avail) {
-	printf("oops... out of memory\n");
-	pause();
-    }
-    return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-    struct memchunk *mp = addr;
-
-    nb = (nb + 7) & -8;
-    heap_use -= nb;
-    if (avail_ram == addr + nb) {
-	avail_ram = addr;
-	return;
-    }
-    mp->size = nb;
-    mp->next = freechunks;
-    freechunks = mp;
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n");
-	exit();
-    }
-
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d msg: %s\n", r, s.msg);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/crt0.S linux/arch/ppc/coffboot/crt0.S
--- v2.4.4/linux/arch/ppc/coffboot/crt0.S	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/coffboot/crt0.S	Wed Dec 31 16:00:00 1969
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-	.text
-	.globl	_start
-_start:
-	lis	9,_start@h
-	lis	8,_etext@ha
-	addi	8,8,_etext@l
-1:	dcbf	0,9
-	icbi	0,9
-	addi	9,9,0x20
-	cmplwi	0,9,8
-	blt	1b
-	b	start
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/dummy.c linux/arch/ppc/coffboot/dummy.c
--- v2.4.4/linux/arch/ppc/coffboot/dummy.c	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/coffboot/dummy.c	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-int main(void)
-{
-	return 0;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/hack-coff.c linux/arch/ppc/coffboot/hack-coff.c
--- v2.4.4/linux/arch/ppc/coffboot/hack-coff.c	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/hack-coff.c	Wed Dec 31 16:00:00 1969
@@ -1,79 +0,0 @@
-/*
- * hack-coff.c - hack the header of an xcoff file to fill in
- * a few fields needed by the Open Firmware xcoff loader on
- * Power Macs but not initialized by objcopy.
- *
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 <stdio.h>
-#include "rs6000.h"
-
-#define AOUT_MAGIC	0x010b
-
-#define get_16be(x)	((((unsigned char *)(x))[0] << 8) \
-			 + ((unsigned char *)(x))[1])
-#define put_16be(x, v)	(((unsigned char *)(x))[0] = (v) >> 8, \
-			 ((unsigned char *)(x))[1] = (v) & 0xff)
-#define get_32be(x)	((((unsigned char *)(x))[0] << 24) \
-			 + (((unsigned char *)(x))[1] << 16) \
-			 + (((unsigned char *)(x))[2] << 8) \
-			 + ((unsigned char *)(x))[3])
-
-main(int ac, char **av)
-{
-    int fd;
-    int i, nsect;
-    int aoutsz;
-    struct external_filehdr fhdr;
-    AOUTHDR aout;
-    struct external_scnhdr shdr;
-
-    if (ac != 2) {
-	fprintf(stderr, "Usage: hack-coff coff-file\n");
-	exit(1);
-    }
-    if ((fd = open(av[1], 2)) == -1) {
-	perror(av[2]);
-	exit(1);
-    }
-    if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
-	goto readerr;
-    i = get_16be(fhdr.f_magic);
-    if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
-	fprintf(stderr, "%s: not an xcoff file\n", av[1]);
-	exit(1);
-    }
-    aoutsz = get_16be(fhdr.f_opthdr);
-    if (read(fd, &aout, aoutsz) != aoutsz)
-	goto readerr;
-    nsect = get_16be(fhdr.f_nscns);
-    for (i = 0; i < nsect; ++i) {
-	if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
-	    goto readerr;
-	if (strcmp(shdr.s_name, ".text") == 0) {
-	    put_16be(aout.o_snentry, i+1);
-	    put_16be(aout.o_sntext, i+1);
-	} else if (strcmp(shdr.s_name, ".data") == 0) {
-	    put_16be(aout.o_sndata, i+1);
-	} else if (strcmp(shdr.s_name, ".bss") == 0) {
-	    put_16be(aout.o_snbss, i+1);
-	}
-    }
-    put_16be(aout.magic, AOUT_MAGIC);
-    if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
-	|| write(fd, &aout, aoutsz) != aoutsz) {
-	fprintf(stderr, "%s: write error\n", av[1]);
-	exit(1);
-    }
-    close(fd);
-    exit(0);
-
-readerr:
-    fprintf(stderr, "%s: read error or file too short\n", av[1]);
-    exit(1);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/ld.script linux/arch/ppc/coffboot/ld.script
--- v2.4.4/linux/arch/ppc/coffboot/ld.script	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/ld.script	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-OUTPUT_ARCH(powerpc)
-SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
-/* Do we need any of these for elf?
-   __DYNAMIC = 0;    */
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = + SIZEOF_HEADERS;
-  .interp : { *(.interp) }
-  .hash          : { *(.hash)		}
-  .dynsym        : { *(.dynsym)		}
-  .dynstr        : { *(.dynstr)		}
-  .rel.text      : { *(.rel.text)		}
-  .rela.text     : { *(.rela.text) 	}
-  .rel.data      : { *(.rel.data)		}
-  .rela.data     : { *(.rela.data) 	}
-  .rel.rodata    : { *(.rel.rodata) 	}
-  .rela.rodata   : { *(.rela.rodata) 	}
-  .rel.got       : { *(.rel.got)		}
-  .rela.got      : { *(.rela.got)		}
-  .rel.ctors     : { *(.rel.ctors)	}
-  .rela.ctors    : { *(.rela.ctors)	}
-  .rel.dtors     : { *(.rel.dtors)	}
-  .rela.dtors    : { *(.rela.dtors)	}
-  .rel.bss       : { *(.rel.bss)		}
-  .rela.bss      : { *(.rela.bss)		}
-  .rel.plt       : { *(.rel.plt)		}
-  .rela.plt      : { *(.rela.plt)		}
-  .init          : { *(.init)	} =0
-  .plt : { *(.plt) }
-  .text      :
-  {
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    *(.got1)
-  }
-  .fini      : { *(.fini)    } =0
-  .ctors     : { *(.ctors)   }
-  .dtors     : { *(.dtors)   }
-  _etext = .;
-  PROVIDE (etext = .);
-  /* Read-write section, merged into data segment: */
-  . = (. + 0x0FFF) & 0xFFFFF000;
-  .data    :
-  {
-    *(.data)
-    *(.data1)
-    *(.sdata)
-    *(.sdata2)
-    *(.got.plt) *(.got)
-    *(.dynamic)
-    CONSTRUCTORS
-  }
-  _edata  =  .;
-  PROVIDE (edata = .);
-  __bss_start = .;
-  .bss       :
-  {
-   *(.sbss) *(.scommon)
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  }
-  _end = . ;
-  PROVIDE (end = .);
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/misc.S linux/arch/ppc/coffboot/misc.S
--- v2.4.4/linux/arch/ppc/coffboot/misc.S	Sun Feb 13 10:47:01 2000
+++ linux/arch/ppc/coffboot/misc.S	Wed Dec 31 16:00:00 1969
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-	.text
-
-/*
- * Use the BAT3 registers to map the 1st 8MB of RAM to
- * the address given as the 1st argument.
- */
-	.globl	setup_bats
-setup_bats:
-	mfpvr	5
-	rlwinm	5,5,16,16,31		/* r3 = 1 for 601, 4 for 604 */
-	cmpi	0,5,1
-	li	0,0
-	bne	4f
-	mtibatl	3,0			/* invalidate BAT first */
-	ori	3,3,4			/* set up BAT registers for 601 */
-	li	4,0x7f
-	mtibatu	3,3
-	mtibatl	3,4
-	b	5f
-4:	mtdbatu	3,0			/* invalidate BATs first */
-	mtibatu	3,0
-	ori	3,3,0xff		/* set up BAT registers for 604 */
-	li	4,2
-	mtdbatl	3,4
-	mtdbatu	3,3
-	mtibatl	3,4
-	mtibatu	3,3
-5:	sync
-	isync
-	blr
-
-/*
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
-	.global	flush_cache
-flush_cache:
-	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
-	rlwinm.	4,4,27,5,31
-	mtctr	4
-	beqlr
-1:	dcbf	0,3
-	icbi	0,3
-	addi	3,3,0x20
-	bdnz	1b
-	sync
-	isync
-	blr
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/mknote.c linux/arch/ppc/coffboot/mknote.c
--- v2.4.4/linux/arch/ppc/coffboot/mknote.c	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/coffboot/mknote.c	Wed Dec 31 16:00:00 1969
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) Cort Dougan 1999.
- *
- * 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.
- *
- * Generate a note section as per the CHRP specification.
- *
- */
-
-#include <stdio.h>
-
-#define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
-
-int main(void)
-{
-/* header */
-	/* namesz */
-	PL(strlen("PowerPC")+1);
-	/* descrsz */
-	PL(6*4);
-	/* type */
-	PL(0x1275);
-	/* name */
-	printf("PowerPC"); printf("%c", 0);
-	
-/* descriptor */
-	/* real-mode */
-	PL(0xffffffff);
-	/* real-base */
-	PL(0x00c00000);
-	/* real-size */
-	PL(0xffffffff);
-	/* virt-base */
-	PL(0xffffffff);
-	/* virt-size */
-	PL(0xffffffff);
-	/* load-base */
-	PL(0x4000);
-	return 0;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/no_initrd.c linux/arch/ppc/coffboot/no_initrd.c
--- v2.4.4/linux/arch/ppc/coffboot/no_initrd.c	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/coffboot/no_initrd.c	Wed Dec 31 16:00:00 1969
@@ -1,2 +0,0 @@
-char initrd_data[1];
-int initrd_len = 0;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/nonstdio.h linux/arch/ppc/coffboot/nonstdio.h
--- v2.4.4/linux/arch/ppc/coffboot/nonstdio.h	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/nonstdio.h	Wed Dec 31 16:00:00 1969
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-typedef int	FILE;
-extern FILE *stdin, *stdout;
-#define NULL	((void *)0)
-#define EOF	(-1)
-#define fopen(n, m)	NULL
-#define fflush(f)	0
-#define fclose(f)	0
-extern char *fgets();
-
-#define perror(s)	printf("%s: no files!\n", (s))
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/piggyback.c linux/arch/ppc/coffboot/piggyback.c
--- v2.4.4/linux/arch/ppc/coffboot/piggyback.c	Tue Feb 22 22:27:43 2000
+++ linux/arch/ppc/coffboot/piggyback.c	Wed Dec 31 16:00:00 1969
@@ -1,66 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-
-extern long ce_exec_config[];
-
-int main(int argc, char *argv[])
-{
-	int i, cnt, pos, len;
-	unsigned int cksum, val;
-	unsigned char *lp;
-	unsigned char buf[8192];
-	if (argc != 2)
-	{
-		fprintf(stderr, "usage: %s name <in-file >out-file\n",
-			argv[0]);
-		exit(1);
-	}
-	fprintf(stdout, "#\n");
-	fprintf(stdout, "# Miscellaneous data structures:\n");
-	fprintf(stdout, "# WARNING - this file is automatically generated!\n");
-	fprintf(stdout, "#\n");
-	fprintf(stdout, "\n");
-	fprintf(stdout, "\t.data\n");
-	fprintf(stdout, "\t.globl %s_data\n", argv[1]);
-	fprintf(stdout, "%s_data:\n", argv[1]);
-	pos = 0;
-	cksum = 0;
-	while ((len = read(0, buf, sizeof(buf))) > 0)
-	{
-		cnt = 0;
-		lp = (unsigned char *)buf;
-		len = (len + 3) & ~3;  /* Round up to longwords */
-		for (i = 0;  i < len;  i += 4)
-		{
-			if (cnt == 0)
-			{
-				fprintf(stdout, "\t.long\t");
-			}
-			fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
-			val = *(unsigned long *)lp;
-			cksum ^= val;
-			lp += 4;
-			if (++cnt == 4)
-			{
-				cnt = 0;
-				fprintf(stdout, " # %x \n", pos+i-12);
-				fflush(stdout);
-			} else
-			{
-				fprintf(stdout, ",");
-			}
-		}
-		if (cnt)
-		{
-			fprintf(stdout, "0\n");
-		}
-		pos += len;
-	}
-	fprintf(stdout, "\t.globl %s_len\n", argv[1]);
-	fprintf(stdout, "%s_len:\t.long\t0x%x\n", argv[1], pos);
-	fflush(stdout);
-	fclose(stdout);
-	fprintf(stderr, "cksum = %x\n", cksum);
-	exit(0);
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/rs6000.h linux/arch/ppc/coffboot/rs6000.h
--- v2.4.4/linux/arch/ppc/coffboot/rs6000.h	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/rs6000.h	Wed Dec 31 16:00:00 1969
@@ -1,243 +0,0 @@
-/* IBM RS/6000 "XCOFF" file definitions for BFD.
-   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
-   FIXME: Can someone provide a transliteration of this name into ASCII?
-   Using the following chars caused a compiler warning on HIUX (so I replaced
-   them with octal escapes), and isn't useful without an understanding of what
-   character set it is.
-   Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
-   and John Gilmore of Cygnus Support.  */
-
-/********************** FILE HEADER **********************/
-
-struct external_filehdr {
-	char f_magic[2];	/* magic number			*/
-	char f_nscns[2];	/* number of sections		*/
-	char f_timdat[4];	/* time & date stamp		*/
-	char f_symptr[4];	/* file pointer to symtab	*/
-	char f_nsyms[4];	/* number of symtab entries	*/
-	char f_opthdr[2];	/* sizeof(optional hdr)		*/
-	char f_flags[2];	/* flags			*/
-};
-
-        /* IBM RS/6000 */
-#define U802WRMAGIC     0730    /* writeable text segments **chh**      */
-#define U802ROMAGIC     0735    /* readonly sharable text segments      */
-#define U802TOCMAGIC    0737    /* readonly text segments and TOC       */
-
-#define BADMAG(x)	\
-	((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
-	 (x).f_magic != U802TOCMAGIC)
-
-#define	FILHDR	struct external_filehdr
-#define	FILHSZ	20
-
-
-/********************** AOUT "OPTIONAL HEADER" **********************/
-
-
-typedef struct 
-{
-  unsigned char	magic[2];	/* type of file			*/
-  unsigned char	vstamp[2];	/* version stamp		*/
-  unsigned char	tsize[4];	/* text size in bytes, padded to FW bdry */
-  unsigned char	dsize[4];	/* initialized data "  "	*/
-  unsigned char	bsize[4];	/* uninitialized data "   "	*/
-  unsigned char	entry[4];	/* entry pt.			*/
-  unsigned char	text_start[4];	/* base of text used for this file */
-  unsigned char	data_start[4];	/* base of data used for this file */
-  unsigned char	o_toc[4];	/* address of TOC */
-  unsigned char	o_snentry[2];	/* section number of entry point */
-  unsigned char	o_sntext[2];	/* section number of .text section */
-  unsigned char	o_sndata[2];	/* section number of .data section */
-  unsigned char	o_sntoc[2];	/* section number of TOC */
-  unsigned char	o_snloader[2];	/* section number of .loader section */
-  unsigned char	o_snbss[2];	/* section number of .bss section */
-  unsigned char	o_algntext[2];	/* .text alignment */
-  unsigned char	o_algndata[2];	/* .data alignment */
-  unsigned char	o_modtype[2];	/* module type (??) */
-  unsigned char o_cputype[2];	/* cpu type */
-  unsigned char	o_maxstack[4];	/* max stack size (??) */
-  unsigned char o_maxdata[4];	/* max data size (??) */
-  unsigned char	o_resv2[12];	/* reserved */
-}
-AOUTHDR;
-
-#define AOUTSZ 72
-#define SMALL_AOUTSZ (28)
-#define AOUTHDRSZ 72
-
-#define	RS6K_AOUTHDR_OMAGIC	0x0107	/* old: text & data writeable */
-#define	RS6K_AOUTHDR_NMAGIC	0x0108	/* new: text r/o, data r/w */
-#define	RS6K_AOUTHDR_ZMAGIC	0x010B	/* paged: text r/o, both page-aligned */
-
-
-/********************** SECTION HEADER **********************/
-
-
-struct external_scnhdr {
-	char		s_name[8];	/* section name			*/
-	char		s_paddr[4];	/* physical address, aliased s_nlib */
-	char		s_vaddr[4];	/* virtual address		*/
-	char		s_size[4];	/* section size			*/
-	char		s_scnptr[4];	/* file ptr to raw data for section */
-	char		s_relptr[4];	/* file ptr to relocation	*/
-	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
-	char		s_nreloc[2];	/* number of relocation entries	*/
-	char		s_nlnno[2];	/* number of line number entries*/
-	char		s_flags[4];	/* flags			*/
-};
-
-/*
- * names of "special" sections
- */
-#define _TEXT	".text"
-#define _DATA	".data"
-#define _BSS	".bss"
-#define _PAD	".pad"
-#define _LOADER	".loader"
-
-#define	SCNHDR	struct external_scnhdr
-#define	SCNHSZ	40
-
-/* XCOFF uses a special .loader section with type STYP_LOADER.  */
-#define STYP_LOADER 0x1000
-
-/* XCOFF uses a special .debug section with type STYP_DEBUG.  */
-#define STYP_DEBUG 0x2000
-
-/* XCOFF handles line number or relocation overflow by creating
-   another section header with STYP_OVRFLO set.  */
-#define STYP_OVRFLO 0x8000
-
-/********************** LINE NUMBERS **********************/
-
-/* 1 line number entry for every "breakpointable" source line in a section.
- * Line numbers are grouped on a per function basis; first entry in a function
- * grouping will have l_lnno = 0 and in place of physical address will be the
- * symbol table index of the function name.
- */
-struct external_lineno {
-	union {
-		char l_symndx[4];	/* function name symbol index, iff l_lnno == 0*/
-		char l_paddr[4];	/* (physical) address of line number	*/
-	} l_addr;
-	char l_lnno[2];	/* line number		*/
-};
-
-
-#define	LINENO	struct external_lineno
-#define	LINESZ	6
-
-
-/********************** SYMBOLS **********************/
-
-#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
-#define E_FILNMLEN	14	/* # characters in a file name		*/
-#define E_DIMNUM	4	/* # array dimensions in auxiliary entry */
-
-struct external_syment 
-{
-  union {
-    char e_name[E_SYMNMLEN];
-    struct {
-      char e_zeroes[4];
-      char e_offset[4];
-    } e;
-  } e;
-  char e_value[4];
-  char e_scnum[2];
-  char e_type[2];
-  char e_sclass[1];
-  char e_numaux[1];
-};
-
-
-
-#define N_BTMASK	(017)
-#define N_TMASK		(060)
-#define N_BTSHFT	(4)
-#define N_TSHIFT	(2)
-  
-
-union external_auxent {
-	struct {
-		char x_tagndx[4];	/* str, un, or enum tag indx */
-		union {
-			struct {
-			    char  x_lnno[2]; /* declaration line number */
-			    char  x_size[2]; /* str/union/array size */
-			} x_lnsz;
-			char x_fsize[4];	/* size of function */
-		} x_misc;
-		union {
-			struct {		/* if ISFCN, tag, or .bb */
-			    char x_lnnoptr[4];	/* ptr to fcn line # */
-			    char x_endndx[4];	/* entry ndx past block end */
-			} x_fcn;
-			struct {		/* if ISARY, up to 4 dimen. */
-			    char x_dimen[E_DIMNUM][2];
-			} x_ary;
-		} x_fcnary;
-		char x_tvndx[2];		/* tv index */
-	} x_sym;
-
-	union {
-		char x_fname[E_FILNMLEN];
-		struct {
-			char x_zeroes[4];
-			char x_offset[4];
-		} x_n;
-	} x_file;
-
-	struct {
-		char x_scnlen[4];			/* section length */
-		char x_nreloc[2];	/* # relocation entries */
-		char x_nlinno[2];	/* # line numbers */
-	} x_scn;
-
-        struct {
-		char x_tvfill[4];	/* tv fill value */
-		char x_tvlen[2];	/* length of .tv */
-		char x_tvran[2][2];	/* tv range */
-	} x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
-
-	struct {
-		unsigned char x_scnlen[4];
-		unsigned char x_parmhash[4];
-		unsigned char x_snhash[2];
-		unsigned char x_smtyp[1];
-		unsigned char x_smclas[1];
-		unsigned char x_stab[4];
-		unsigned char x_snstab[2];
-	} x_csect;
-
-};
-
-#define	SYMENT	struct external_syment
-#define	SYMESZ	18	
-#define	AUXENT	union external_auxent
-#define	AUXESZ	18
-#define DBXMASK 0x80		/* for dbx storage mask */
-#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
-
-
-
-/********************** RELOCATION DIRECTIVES **********************/
-
-
-struct external_reloc {
-  char r_vaddr[4];
-  char r_symndx[4];
-  char r_size[1];
-  char r_type[1];
-};
-
-
-#define RELOC struct external_reloc
-#define RELSZ 10
-
-#define DEFAULT_DATA_SECTION_ALIGNMENT 4
-#define DEFAULT_BSS_SECTION_ALIGNMENT 4
-#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
-/* For new sections we havn't heard of before */
-#define DEFAULT_SECTION_ALIGNMENT 4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/start.c linux/arch/ppc/coffboot/start.c
--- v2.4.4/linux/arch/ppc/coffboot/start.c	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/coffboot/start.c	Wed Dec 31 16:00:00 1969
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 <stdarg.h>
-
-int (*prom)();
-
-void *chosen_handle;
-void *stdin;
-void *stdout;
-void *stderr;
-
-void exit(void);
-void *finddevice(const char *name);
-int getprop(void *phandle, const char *name, void *buf, int buflen);
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
-    prom = (int (*)()) promptr;
-    chosen_handle = finddevice("/chosen");
-    if (chosen_handle == (void *) -1)
-	exit();
-    if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
-	exit();
-    stderr = stdout;
-    if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
-	exit();
-
-    boot(a1, a2, promptr);
-    for (;;)
-	exit();
-}
-
-int
-write(void *handle, void *ptr, int nb)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	void *ihandle;
-	void *addr;
-	int len;
-	int actual;
-    } args;
-
-    args.service = "write";
-    args.nargs = 3;
-    args.nret = 1;
-    args.ihandle = handle;
-    args.addr = ptr;
-    args.len = nb;
-    args.actual = -1;
-    (*prom)(&args);
-    return args.actual;
-}
-
-int writestring(void *f, char *ptr, int nb)
-{
-	int w = 0, i;
-	char *ret = "\r";
-
-	for (i = 0; i < nb; ++i) {
-		if (ptr[i] == '\n') {
-			if (i > w) {
-				write(f, ptr + w, i - w);
-				w = i;
-			}
-			write(f, ret, 1);
-		}
-	}
-	if (w < nb)
-		write(f, ptr + w, nb - w);
-	return nb;
-}
-
-int
-read(void *handle, void *ptr, int nb)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	void *ihandle;
-	void *addr;
-	int len;
-	int actual;
-    } args;
-
-    args.service = "read";
-    args.nargs = 3;
-    args.nret = 1;
-    args.ihandle = handle;
-    args.addr = ptr;
-    args.len = nb;
-    args.actual = -1;
-    (*prom)(&args);
-    return args.actual;
-}
-
-void
-exit()
-{
-    struct prom_args {
-	char *service;
-    } args;
-
-    for (;;) {
-	args.service = "exit";
-	(*prom)(&args);
-    }
-}
-
-void
-pause()
-{
-    struct prom_args {
-	char *service;
-    } args;
-
-    args.service = "enter";
-    (*prom)(&args);
-}
-
-void *
-finddevice(const char *name)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	const char *devspec;
-	void *phandle;
-    } args;
-
-    args.service = "finddevice";
-    args.nargs = 1;
-    args.nret = 1;
-    args.devspec = name;
-    args.phandle = (void *) -1;
-    (*prom)(&args);
-    return args.phandle;
-}
-
-void *
-claim(unsigned int virt, unsigned int size, unsigned int align)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	unsigned int virt;
-	unsigned int size;
-	unsigned int align;
-	void *ret;
-    } args;
-
-    args.service = "claim";
-    args.nargs = 3;
-    args.nret = 1;
-    args.virt = virt;
-    args.size = size;
-    args.align = align;
-    (*prom)(&args);
-    return args.ret;
-}
-
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
-{
-    struct prom_args {
-	char *service;
-	int nargs;
-	int nret;
-	void *phandle;
-	const char *name;
-	void *buf;
-	int buflen;
-	int size;
-    } args;
-
-    args.service = "getprop";
-    args.nargs = 4;
-    args.nret = 1;
-    args.phandle = phandle;
-    args.name = name;
-    args.buf = buf;
-    args.buflen = buflen;
-    args.size = -1;
-    (*prom)(&args);
-    return args.size;
-}
-
-int
-putc(int c, void *f)
-{
-    char ch = c;
-
-    return writestring(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
-    return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
-    int n = strlen(str);
-
-    return writestring(f, str, n) == n? 0: -1;
-}
-
-int
-readchar()
-{
-    char ch;
-
-    for (;;) {
-	switch (read(stdin, &ch, 1)) {
-	case 1:
-	    return ch;
-	case -1:
-	    printk("read(stdin) returned -1\n");
-	    return -1;
-	}
-    }
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar()
-{
-    int c;
-
-    if (lineleft == 0) {
-	lineptr = line;
-	for (;;) {
-	    c = readchar();
-	    if (c == -1 || c == 4)
-		break;
-	    if (c == '\r' || c == '\n') {
-		*lineptr++ = '\n';
-		putchar('\n');
-		break;
-	    }
-	    switch (c) {
-	    case 0177:
-	    case '\b':
-		if (lineptr > line) {
-		    putchar('\b');
-		    putchar(' ');
-		    putchar('\b');
-		    --lineptr;
-		}
-		break;
-	    case 'U' & 0x1F:
-		while (lineptr > line) {
-		    putchar('\b');
-		    putchar(' ');
-		    putchar('\b');
-		    --lineptr;
-		}
-		break;
-	    default:
-		if (lineptr >= &line[sizeof(line) - 1])
-		    putchar('\a');
-		else {
-		    putchar(c);
-		    *lineptr++ = c;
-		}
-	    }
-	}
-	lineleft = lineptr - line;
-	lineptr = line;
-    }
-    if (lineleft == 0)
-	return -1;
-    --lineleft;
-    return *lineptr++;
-}
-
-extern int vsprintf(char *buf, const char *fmt, va_list args);
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	writestring(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
-	va_list args;
-	int n;
-
-	va_start(args, fmt);
-	n = vsprintf(sprint_buf, fmt, args);
-	va_end(args);
-	writestring(stdout, sprint_buf, n);
-	return n;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/string.S linux/arch/ppc/coffboot/string.S
--- v2.4.4/linux/arch/ppc/coffboot/string.S	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/string.S	Wed Dec 31 16:00:00 1969
@@ -1,206 +0,0 @@
-/*
- * String handling functions for PowerPC.
- *
- * Copyright (C) 1996 Paul Mackerras.
- *
- * 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.
- */
-#define r0	0
-#define r3	3
-#define r4	4
-#define r5	5
-#define r6	6
-#define r7	7
-#define r8	8
-
-	.globl	strcpy
-strcpy:
-	addi	r5,r3,-1
-	addi	r4,r4,-1
-1:	lbzu	r0,1(r4)
-	cmpwi	0,r0,0
-	stbu	r0,1(r5)
-	bne	1b
-	blr
-
-	.globl	strncpy
-strncpy:
-	cmpwi	0,r5,0
-	beqlr
-	mtctr	r5
-	addi	r6,r3,-1
-	addi	r4,r4,-1
-1:	lbzu	r0,1(r4)
-	cmpwi	0,r0,0
-	stbu	r0,1(r6)
-	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
-	blr
-
-	.globl	strcat
-strcat:
-	addi	r5,r3,-1
-	addi	r4,r4,-1
-1:	lbzu	r0,1(r5)
-	cmpwi	0,r0,0
-	bne	1b
-	addi	r5,r5,-1
-1:	lbzu	r0,1(r4)
-	cmpwi	0,r0,0
-	stbu	r0,1(r5)
-	bne	1b
-	blr
-
-	.globl	strcmp
-strcmp:
-	addi	r5,r3,-1
-	addi	r4,r4,-1
-1:	lbzu	r3,1(r5)
-	cmpwi	1,r3,0
-	lbzu	r0,1(r4)
-	subf.	r3,r0,r3
-	beqlr	1
-	beq	1b
-	blr
-
-	.globl	strlen
-strlen:
-	addi	r4,r3,-1
-1:	lbzu	r0,1(r4)
-	cmpwi	0,r0,0
-	bne	1b
-	subf	r3,r3,r4
-	blr
-
-	.globl	memset
-memset:
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
-	addi	r6,r3,-4
-	cmplwi	0,r5,4
-	blt	7f
-	stwu	r4,4(r6)
-	beqlr
-	andi.	r0,r6,3
-	add	r5,r0,r5
-	subf	r6,r0,r6
-	rlwinm	r0,r5,32-2,2,31
-	mtctr	r0
-	bdz	6f
-1:	stwu	r4,4(r6)
-	bdnz	1b
-6:	andi.	r5,r5,3
-7:	cmpwi	0,r5,0
-	beqlr
-	mtctr	r5
-	addi	r6,r6,3
-8:	stbu	r4,1(r6)
-	bdnz	8b
-	blr
-
-	.globl	bcopy
-bcopy:
-	mr	r6,r3
-	mr	r3,r4
-	mr	r4,r6
-	b	memcpy
-
-	.globl	memmove
-memmove:
-	cmplw	0,r3,r4
-	bgt	backwards_memcpy
-	/* fall through */
-
-	.globl	memcpy
-memcpy:
-	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
-	addi	r6,r3,-4
-	addi	r4,r4,-4
-	beq	2f			/* if less than 8 bytes to do */
-	andi.	r0,r6,3			/* get dest word aligned */
-	mtctr	r7
-	bne	5f
-1:	lwz	r7,4(r4)
-	lwzu	r8,8(r4)
-	stw	r7,4(r6)
-	stwu	r8,8(r6)
-	bdnz	1b
-	andi.	r5,r5,7
-2:	cmplwi	0,r5,4
-	blt	3f
-	lwzu	r0,4(r4)
-	addi	r5,r5,-4
-	stwu	r0,4(r6)
-3:	cmpwi	0,r5,0
-	beqlr
-	mtctr	r5
-	addi	r4,r4,3
-	addi	r6,r6,3
-4:	lbzu	r0,1(r4)
-	stbu	r0,1(r6)
-	bdnz	4b
-	blr
-5:	subfic	r0,r0,4
-	mtctr	r0
-6:	lbz	r7,4(r4)
-	addi	r4,r4,1
-	stb	r7,4(r6)
-	addi	r6,r6,1
-	bdnz	6b
-	subf	r5,r0,r5
-	rlwinm.	r7,r5,32-3,3,31
-	beq	2b
-	mtctr	r7
-	b	1b
-
-	.globl	backwards_memcpy
-backwards_memcpy:
-	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
-	add	r6,r3,r5
-	add	r4,r4,r5
-	beq	2f
-	andi.	r0,r6,3
-	mtctr	r7
-	bne	5f
-1:	lwz	r7,-4(r4)
-	lwzu	r8,-8(r4)
-	stw	r7,-4(r6)
-	stwu	r8,-8(r6)
-	bdnz	1b
-	andi.	r5,r5,7
-2:	cmplwi	0,r5,4
-	blt	3f
-	lwzu	r0,-4(r4)
-	subi	r5,r5,4
-	stwu	r0,-4(r6)
-3:	cmpwi	0,r5,0
-	beqlr
-	mtctr	r5
-4:	lbzu	r0,-1(r4)
-	stbu	r0,-1(r6)
-	bdnz	4b
-	blr
-5:	mtctr	r0
-6:	lbzu	r7,-1(r4)
-	stbu	r7,-1(r6)
-	bdnz	6b
-	subf	r5,r0,r5
-	rlwinm.	r7,r5,32-3,3,31
-	beq	2b
-	mtctr	r7
-	b	1b
-
-	.globl	memcmp
-memcmp:
-	cmpwi	0,r5,0
-	blelr
-	mtctr	r5
-	addi	r6,r3,-1
-	addi	r4,r4,-1
-1:	lbzu	r3,1(r6)
-	lbzu	r0,1(r4)
-	subf.	r3,r0,r3
-	bdnzt	2,1b
-	blr
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/zlib.c linux/arch/ppc/coffboot/zlib.c
--- v2.4.4/linux/arch/ppc/coffboot/zlib.c	Mon Jun  7 12:11:51 1999
+++ linux/arch/ppc/coffboot/zlib.c	Wed Dec 31 16:00:00 1969
@@ -1,2148 +0,0 @@
-/*
- * This file is derived from various .h and .c files from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.  See zlib.h for conditions of
- * distribution and use.
- *
- * Changes that have been made include:
- * - changed functions not used outside this file to "local"
- * - added minCompression parameter to deflateInit2
- * - added Z_PACKET_FLUSH (see zlib.h for details)
- * - added inflateIncomp
- *
- * $Id: zlib.c,v 1.3 1999/05/27 22:22:54 cort Exp $
- */
-
-/*+++++*/
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
-
-#define _Z_UTIL_H
-
-#include "zlib.h"
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-#define FAR
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-extern char *z_errmsg[]; /* indexed by 1-zlib_error */
-
-#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
-/* To be used only when the state is known to be valid */
-
-#ifndef NULL
-#define NULL	((void *) 0)
-#endif
-
-        /* common constants */
-
-#define DEFLATED   8
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-         /* functions */
-
-#include <linux/string.h>
-#define zmemcpy memcpy
-#define zmemzero(dest, len)	memset(dest, 0, len)
-
-/* Diagnostic functions */
-#ifdef DEBUG_ZLIB
-#  include <stdio.h>
-#  ifndef verbose
-#    define verbose 0
-#  endif
-#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-
-typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
-
-/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
-/* void   zcfree  OF((voidpf opaque, voidpf ptr)); */
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr, size)	\
-	   (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
-#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
-
-/* deflate.h -- internal compression state
- * Copyright (C) 1995 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/*+++++*/
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-local inflate_blocks_statef * inflate_blocks_new OF((
-    z_stream *z,
-    check_func c,               /* check function */
-    uInt w));                   /* window size */
-
-local int inflate_blocks OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));                      /* initial return code */
-
-local void inflate_blocks_reset OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    uLongf *));                  /* check value on output */
-
-local int inflate_blocks_free OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    uLongf *));                  /* check value on output */
-
-local int inflate_addhistory OF((
-    inflate_blocks_statef *,
-    z_stream *));
-
-local int inflate_packet_flush OF((
-    inflate_blocks_statef *));
-
-/*+++++*/
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
-   that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
-  union {
-    struct {
-      Byte Exop;        /* number of extra bits or operation */
-      Byte Bits;        /* number of bits in this code or subcode */
-    } what;
-    uInt Nalloc;	/* number of these allocated here */
-    Bytef *pad;         /* pad structure to a power of 2 (4 bytes for */
-  } word;               /*  16-bit, 8 bytes for 32-bit machines) */
-  union {
-    uInt Base;          /* literal, length base, or distance base */
-    inflate_huft *Next; /* pointer to next level of table */
-  } more;
-};
-
-#ifdef DEBUG_ZLIB
-  local uInt inflate_hufts;
-#endif
-
-local int inflate_trees_bits OF((
-    uIntf *,                    /* 19 code lengths */
-    uIntf *,                    /* bits tree desired/actual depth */
-    inflate_huft * FAR *,       /* bits tree result */
-    z_stream *));               /* for zalloc, zfree functions */
-
-local int inflate_trees_dynamic OF((
-    uInt,                       /* number of literal/length codes */
-    uInt,                       /* number of distance codes */
-    uIntf *,                    /* that many (total) code lengths */
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *,       /* distance tree result */
-    z_stream *));               /* for zalloc, zfree functions */
-
-local int inflate_trees_fixed OF((
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *));     /* distance tree result */
-
-local int inflate_trees_free OF((
-    inflate_huft *,             /* tables to free */
-    z_stream *));               /* for zfree function */
-
-
-/*+++++*/
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-local inflate_codes_statef *inflate_codes_new OF((
-    uInt, uInt,
-    inflate_huft *, inflate_huft *,
-    z_stream *));
-
-local int inflate_codes OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));
-
-local void inflate_codes_free OF((
-    inflate_codes_statef *,
-    z_stream *));
-
-
-/*+++++*/
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* inflate private state */
-struct internal_state {
-
-  /* mode */
-  enum {
-      METHOD,   /* waiting for method byte */
-      FLAG,     /* waiting for flag byte */
-      BLOCKS,   /* decompressing blocks */
-      CHECK4,   /* four check bytes to go */
-      CHECK3,   /* three check bytes to go */
-      CHECK2,   /* two check bytes to go */
-      CHECK1,   /* one check byte to go */
-      DONE,     /* finished check, done */
-      BAD}      /* got an error--stay here */
-    mode;               /* current inflate mode */
-
-  /* mode dependent information */
-  union {
-    uInt method;        /* if FLAGS, method byte */
-    struct {
-      uLong was;                /* computed check value */
-      uLong need;               /* stream check value */
-    } check;            /* if CHECK, check values to compare */
-    uInt marker;        /* if BAD, inflateSync's marker bytes count */
-  } sub;        /* submode */
-
-  /* mode independent information */
-  int  nowrap;          /* flag for no wrapper */
-  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
-  inflate_blocks_statef 
-    *blocks;            /* current inflate_blocks state */
-
-};
-
-
-int inflateReset(z)
-z_stream *z;
-{
-  uLong c;
-
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->total_in = z->total_out = 0;
-  z->msg = Z_NULL;
-  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
-  inflate_blocks_reset(z->state->blocks, z, &c);
-  Trace((stderr, "inflate: reset\n"));
-  return Z_OK;
-}
-
-
-int inflateEnd(z)
-z_stream *z;
-{
-  uLong c;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->blocks != Z_NULL)
-    inflate_blocks_free(z->state->blocks, z, &c);
-  ZFREE(z, z->state, sizeof(struct internal_state));
-  z->state = Z_NULL;
-  Trace((stderr, "inflate: end\n"));
-  return Z_OK;
-}
-
-
-int inflateInit2(z, w)
-z_stream *z;
-int w;
-{
-  /* initialize state */
-  if (z == Z_NULL)
-    return Z_STREAM_ERROR;
-/*  if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
-/*  if (z->zfree == Z_NULL) z->zfree = zcfree; */
-  if ((z->state = (struct internal_state FAR *)
-       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
-    return Z_MEM_ERROR;
-  z->state->blocks = Z_NULL;
-
-  /* handle undocumented nowrap option (no zlib header or check) */
-  z->state->nowrap = 0;
-  if (w < 0)
-  {
-    w = - w;
-    z->state->nowrap = 1;
-  }
-
-  /* set window size */
-  if (w < 8 || w > 15)
-  {
-    inflateEnd(z);
-    return Z_STREAM_ERROR;
-  }
-  z->state->wbits = (uInt)w;
-
-  /* create inflate_blocks state */
-  if ((z->state->blocks =
-       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
-      == Z_NULL)
-  {
-    inflateEnd(z);
-    return Z_MEM_ERROR;
-  }
-  Trace((stderr, "inflate: allocated\n"));
-
-  /* reset state */
-  inflateReset(z);
-  return Z_OK;
-}
-
-
-int inflateInit(z)
-z_stream *z;
-{
-  return inflateInit2(z, DEF_WBITS);
-}
-
-
-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int inflate(z, f)
-z_stream *z;
-int f;
-{
-  int r;
-  uInt b;
-
-  if (z == Z_NULL || z->next_in == Z_NULL)
-    return Z_STREAM_ERROR;
-  r = Z_BUF_ERROR;
-  while (1) switch (z->state->mode)
-  {
-    case METHOD:
-      NEEDBYTE
-      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
-      {
-        z->state->mode = BAD;
-        z->msg = "unknown compression method";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
-      {
-        z->state->mode = BAD;
-        z->msg = "invalid window size";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = FLAG;
-    case FLAG:
-      NEEDBYTE
-      if ((b = NEXTBYTE) & 0x20)
-      {
-        z->state->mode = BAD;
-        z->msg = "invalid reserved bit";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if (((z->state->sub.method << 8) + b) % 31)
-      {
-        z->state->mode = BAD;
-        z->msg = "incorrect header check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Trace((stderr, "inflate: zlib header ok\n"));
-      z->state->mode = BLOCKS;
-    case BLOCKS:
-      r = inflate_blocks(z->state->blocks, z, r);
-      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
-	  r = inflate_packet_flush(z->state->blocks);
-      if (r == Z_DATA_ERROR)
-      {
-        z->state->mode = BAD;
-        z->state->sub.marker = 0;       /* can try inflateSync */
-        break;
-      }
-      if (r != Z_STREAM_END)
-        return r;
-      r = Z_OK;
-      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
-      if (z->state->nowrap)
-      {
-        z->state->mode = DONE;
-        break;
-      }
-      z->state->mode = CHECK4;
-    case CHECK4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = CHECK3;
-    case CHECK3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = CHECK2;
-    case CHECK2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = CHECK1;
-    case CHECK1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
-
-      if (z->state->sub.check.was != z->state->sub.check.need)
-      {
-        z->state->mode = BAD;
-        z->msg = "incorrect data check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Trace((stderr, "inflate: zlib check ok\n"));
-      z->state->mode = DONE;
-    case DONE:
-      return Z_STREAM_END;
-    case BAD:
-      return Z_DATA_ERROR;
-    default:
-      return Z_STREAM_ERROR;
-  }
-
- empty:
-  if (f != Z_PACKET_FLUSH)
-    return r;
-  z->state->mode = BAD;
-  z->state->sub.marker = 0;       /* can try inflateSync */
-  return Z_DATA_ERROR;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int inflateIncomp(z)
-z_stream *z;
-{
-    if (z->state->mode != BLOCKS)
-	return Z_DATA_ERROR;
-    return inflate_addhistory(z->state->blocks, z);
-}
-
-
-int inflateSync(z)
-z_stream *z;
-{
-  uInt n;       /* number of bytes to look at */
-  Bytef *p;     /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != BAD)
-  {
-    z->state->mode = BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    if (*p == (Byte)(m < 2 ? 0 : 0xff))
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-#undef NEEDBYTE
-#undef NEXTBYTE
-
-/*+++++*/
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
-  /* mode */
-  enum {
-      TYPE,     /* get type bits (3, including end bit) */
-      LENS,     /* get lengths for stored */
-      STORED,   /* processing stored block */
-      TABLE,    /* get table lengths */
-      BTREE,    /* get bit lengths tree for a dynamic block */
-      DTREE,    /* get length, distance trees for a dynamic block */
-      CODES,    /* processing fixed or dynamic block */
-      DRY,      /* output remaining window bytes */
-      DONEB,     /* finished last block, done */
-      BADB}      /* got a data error--stuck here */
-    mode;               /* current inflate_block mode */
-
-  /* mode dependent information */
-  union {
-    uInt left;          /* if STORED, bytes left to copy */
-    struct {
-      uInt table;               /* table lengths (14 bits) */
-      uInt index;               /* index into blens (or border) */
-      uIntf *blens;             /* bit lengths of codes */
-      uInt bb;                  /* bit length tree depth */
-      inflate_huft *tb;         /* bit length decoding tree */
-      int nblens;		/* # elements allocated at blens */
-    } trees;            /* if DTREE, decoding info for trees */
-    struct {
-      inflate_huft *tl, *td;    /* trees to free */
-      inflate_codes_statef 
-         *codes;
-    } decode;           /* if CODES, current state */
-  } sub;                /* submode */
-  uInt last;            /* true if this block is the last block */
-
-  /* mode independent information */
-  uInt bitk;            /* bits in bit buffer */
-  uLong bitb;           /* bit buffer */
-  Bytef *window;        /* sliding window */
-  Bytef *end;           /* one byte after sliding window */
-  Bytef *read;          /* window read pointer */
-  Bytef *write;         /* window write pointer */
-  check_func checkfn;   /* check function */
-  uLong check;          /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/*   update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/*   get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/*   output bytes */
-#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/*   load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/*
- * The IBM 150 firmware munges the data right after _etext[].  This
- * protects it. -- Cort
- */
-local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
-/* And'ing with mask[n] masks the lower n bits */
-local uInt inflate_mask[] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));
-
-/*+++++*/
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-local int inflate_fast OF((
-    uInt,
-    uInt,
-    inflate_huft *,
-    inflate_huft *,
-    inflate_blocks_statef *,
-    z_stream *));
-
-
-/*+++++*/
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local uInt border[] = { /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
-   Notes beyond the 1.93a appnote.txt:
-
-   1. Distance pointers never point before the beginning of the output
-      stream.
-   2. Distance pointers can point back across blocks, up to 32k away.
-   3. There is an implied maximum of 7 bits for the bit length table and
-      15 bits for the actual data.
-   4. If only one code exists, then it is encoded using one bit.  (Zero
-      would be more efficient, but perhaps a little confusing.)  If two
-      codes exist, they are coded using one bit each (0 and 1).
-   5. There is no way of sending zero distance codes--a dummy must be
-      sent if there are none.  (History: a pre 2.0 version of PKZIP would
-      store blocks with no distance codes, but this was discovered to be
-      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
-      zero distance codes, which is sent as one code of zero bits in
-      length.
-   6. There are up to 286 literal/length codes.  Code 256 represents the
-      end-of-block.  Note however that the static length tree defines
-      288 codes just to fill out the Huffman codes.  Codes 286 and 287
-      cannot be used though, since there is no length base or extra bits
-      defined for them.  Similarily, there are up to 30 distance codes.
-      However, static trees define 32 codes (all 5 bits) to fill out the
-      Huffman codes, but the last two had better not show up in the data.
-   7. Unzip can check dynamic Huffman blocks for complete code sets.
-      The exception is that a single code would not be complete (see #4).
-   8. The five bits following the block type is really the number of
-      literal codes sent minus 257.
-   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
-      (1+6+6).  Therefore, to output three times the length, you output
-      three codes (1+1+1), whereas to output four times the same length,
-      you only need two codes (1+3).  Hmm.
-  10. In the tree reconstruction algorithm, Code = Code + Increment
-      only if BitLength(i) is not zero.  (Pretty obvious.)
-  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
-  12. Note: length code 284 can represent 227-258, but length code 285
-      really is 258.  The last length deserves its own, short code
-      since it gets used a lot in very redundant files.  The length
-      258 is special since 258 - 3 (the min match length) is 255.
-  13. The literal/length and distance code bit lengths are read as a
-      single stream of lengths.  It is possible (and advantageous) for
-      a repeat code (16, 17, or 18) to go across the boundary between
-      the two sets of lengths.
- */
-
-
-local void inflate_blocks_reset(s, z, c)
-inflate_blocks_statef *s;
-z_stream *z;
-uLongf *c;
-{
-  if (s->checkfn != Z_NULL)
-    *c = s->check;
-  if (s->mode == BTREE || s->mode == DTREE)
-    ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
-  if (s->mode == CODES)
-  {
-    inflate_codes_free(s->sub.decode.codes, z);
-    inflate_trees_free(s->sub.decode.td, z);
-    inflate_trees_free(s->sub.decode.tl, z);
-  }
-  s->mode = TYPE;
-  s->bitk = 0;
-  s->bitb = 0;
-  s->read = s->write = s->window;
-  if (s->checkfn != Z_NULL)
-    s->check = (*s->checkfn)(0L, Z_NULL, 0);
-  Trace((stderr, "inflate:   blocks reset\n"));
-}
-
-
-local inflate_blocks_statef *inflate_blocks_new(z, c, w)
-z_stream *z;
-check_func c;
-uInt w;
-{
-  inflate_blocks_statef *s;
-
-  if ((s = (inflate_blocks_statef *)ZALLOC
-       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
-    return s;
-  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
-  {
-    ZFREE(z, s, sizeof(struct inflate_blocks_state));
-    return Z_NULL;
-  }
-  s->end = s->window + w;
-  s->checkfn = c;
-  s->mode = TYPE;
-  Trace((stderr, "inflate:   blocks allocated\n"));
-  inflate_blocks_reset(s, z, &s->check);
-  return s;
-}
-
-
-local int inflate_blocks(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
-  uInt t;               /* temporary storage */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input based on current state */
-  while (1) switch (s->mode)
-  {
-    case TYPE:
-      NEEDBITS(3)
-      t = (uInt)b & 7;
-      s->last = t & 1;
-      switch (t >> 1)
-      {
-        case 0:                         /* stored */
-          Trace((stderr, "inflate:     stored block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          t = k & 7;                    /* go to byte boundary */
-          DUMPBITS(t)
-          s->mode = LENS;               /* get length of stored block */
-          break;
-        case 1:                         /* fixed */
-          Trace((stderr, "inflate:     fixed codes block%s\n",
-                 s->last ? " (last)" : ""));
-          {
-            uInt bl, bd;
-            inflate_huft *tl, *td;
-
-            inflate_trees_fixed(&bl, &bd, &tl, &td);
-            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
-            if (s->sub.decode.codes == Z_NULL)
-            {
-              r = Z_MEM_ERROR;
-              LEAVE
-            }
-            s->sub.decode.tl = Z_NULL;  /* don't try to free these */
-            s->sub.decode.td = Z_NULL;
-          }
-          DUMPBITS(3)
-          s->mode = CODES;
-          break;
-        case 2:                         /* dynamic */
-          Trace((stderr, "inflate:     dynamic codes block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          s->mode = TABLE;
-          break;
-        case 3:                         /* illegal */
-          DUMPBITS(3)
-          s->mode = BADB;
-          z->msg = "invalid block type";
-          r = Z_DATA_ERROR;
-          LEAVE
-      }
-      break;
-    case LENS:
-      NEEDBITS(32)
-      if (((~b) >> 16) != (b & 0xffff))
-      {
-        s->mode = BADB;
-        z->msg = "invalid stored block lengths";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-      s->sub.left = (uInt)b & 0xffff;
-      b = k = 0;                      /* dump bits */
-      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
-      s->mode = s->sub.left ? STORED : TYPE;
-      break;
-    case STORED:
-      if (n == 0)
-        LEAVE
-      NEEDOUT
-      t = s->sub.left;
-      if (t > n) t = n;
-      if (t > m) t = m;
-      zmemcpy(q, p, t);
-      p += t;  n -= t;
-      q += t;  m -= t;
-      if ((s->sub.left -= t) != 0)
-        break;
-      Tracev((stderr, "inflate:       stored end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      s->mode = s->last ? DRY : TYPE;
-      break;
-    case TABLE:
-      NEEDBITS(14)
-      s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
-      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
-      {
-        s->mode = BADB;
-        z->msg = "too many length or distance symbols";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-#endif
-      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
-      if (t < 19)
-        t = 19;
-      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
-      {
-        r = Z_MEM_ERROR;
-        LEAVE
-      }
-      s->sub.trees.nblens = t;
-      DUMPBITS(14)
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       table sizes ok\n"));
-      s->mode = BTREE;
-    case BTREE:
-      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
-      {
-        NEEDBITS(3)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
-        DUMPBITS(3)
-      }
-      while (s->sub.trees.index < 19)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
-      s->sub.trees.bb = 7;
-      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
-                             &s->sub.trees.tb, z);
-      if (t != Z_OK)
-      {
-        r = t;
-        if (r == Z_DATA_ERROR)
-          s->mode = BADB;
-        LEAVE
-      }
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       bits tree ok\n"));
-      s->mode = DTREE;
-    case DTREE:
-      while (t = s->sub.trees.table,
-             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
-      {
-        inflate_huft *h;
-        uInt i, j, c;
-
-        t = s->sub.trees.bb;
-        NEEDBITS(t)
-        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
-        t = h->word.what.Bits;
-        c = h->more.Base;
-        if (c < 16)
-        {
-          DUMPBITS(t)
-          s->sub.trees.blens[s->sub.trees.index++] = c;
-        }
-        else /* c == 16..18 */
-        {
-          i = c == 18 ? 7 : c - 14;
-          j = c == 18 ? 11 : 3;
-          NEEDBITS(t + i)
-          DUMPBITS(t)
-          j += (uInt)b & inflate_mask[i];
-          DUMPBITS(i)
-          i = s->sub.trees.index;
-          t = s->sub.trees.table;
-          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
-              (c == 16 && i < 1))
-          {
-            s->mode = BADB;
-            z->msg = "invalid bit length repeat";
-            r = Z_DATA_ERROR;
-            LEAVE
-          }
-          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
-          do {
-            s->sub.trees.blens[i++] = c;
-          } while (--j);
-          s->sub.trees.index = i;
-        }
-      }
-      inflate_trees_free(s->sub.trees.tb, z);
-      s->sub.trees.tb = Z_NULL;
-      {
-        uInt bl, bd;
-        inflate_huft *tl, *td;
-        inflate_codes_statef *c;
-
-        bl = 9;         /* must be <= 9 for lookahead assumptions */
-        bd = 6;         /* must be <= 9 for lookahead assumptions */
-        t = s->sub.trees.table;
-        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
-                                  s->sub.trees.blens, &bl, &bd, &tl, &td, z);
-        if (t != Z_OK)
-        {
-          if (t == (uInt)Z_DATA_ERROR)
-            s->mode = BADB;
-          r = t;
-          LEAVE
-        }
-        Tracev((stderr, "inflate:       trees ok\n"));
-        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
-        {
-          inflate_trees_free(td, z);
-          inflate_trees_free(tl, z);
-          r = Z_MEM_ERROR;
-          LEAVE
-        }
-        ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
-        s->sub.decode.codes = c;
-        s->sub.decode.tl = tl;
-        s->sub.decode.td = td;
-      }
-      s->mode = CODES;
-    case CODES:
-      UPDATE
-      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
-        return inflate_flush(s, z, r);
-      r = Z_OK;
-      inflate_codes_free(s->sub.decode.codes, z);
-      inflate_trees_free(s->sub.decode.td, z);
-      inflate_trees_free(s->sub.decode.tl, z);
-      LOAD
-      Tracev((stderr, "inflate:       codes end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      if (!s->last)
-      {
-        s->mode = TYPE;
-        break;
-      }
-      if (k > 7)              /* return unused byte, if any */
-      {
-        Assert(k < 16, "inflate_codes grabbed too many bytes")
-        k -= 8;
-        n++;
-        p--;                    /* can always return one */
-      }
-      s->mode = DRY;
-    case DRY:
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      s->mode = DONEB;
-    case DONEB:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADB:
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-local int inflate_blocks_free(s, z, c)
-inflate_blocks_statef *s;
-z_stream *z;
-uLongf *c;
-{
-  inflate_blocks_reset(s, z, c);
-  ZFREE(z, s->window, s->end - s->window);
-  ZFREE(z, s, sizeof(struct inflate_blocks_state));
-  Trace((stderr, "inflate:   blocks freed\n"));
-  return Z_OK;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-local int inflate_addhistory(s, z)
-inflate_blocks_statef *s;
-z_stream *z;
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Bytef *p;             /* input data pointer */
-    uInt n;               /* bytes available there */
-    Bytef *q;             /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-	return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-	return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-	t = n;  /* how many to do */
-	/* is there room until end of buffer? */
-	if (t > m) t = m;
-	/* update check information */
-	if (s->checkfn != Z_NULL)
-	    s->check = (*s->checkfn)(s->check, q, t);
-	zmemcpy(q, p, t);
-	q += t;
-	p += t;
-	n -= t;
-	z->total_out += t;
-	s->read = q;    /* drag read pointer forward */
-/*      WRAP  */ 	/* expand WRAP macro by hand to handle s->read */
-	if (q == s->end) {
-	    s->read = q = s->window;
-	    m = WAVAIL;
-	}
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * At the end of a Deflate-compressed PPP packet, we expect to have seen
- * a `stored' block type value but not the (zero) length bytes.
- */
-local int inflate_packet_flush(s)
-    inflate_blocks_statef *s;
-{
-    if (s->mode != LENS)
-	return Z_DATA_ERROR;
-    s->mode = TYPE;
-    return Z_OK;
-}
-
-
-/*+++++*/
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
-    uIntf *,            /* code lengths in bits */
-    uInt,               /* number of codes */
-    uInt,               /* number of "simple" codes */
-    uIntf *,            /* list of base values for non-simple codes */
-    uIntf *,            /* list of extra bits for non-simple codes */
-    inflate_huft * FAR*,/* result: starting table */
-    uIntf *,            /* maximum lookup bits (returns actual) */
-    z_stream *));       /* for zalloc function */
-
-local voidpf falloc OF((
-    voidpf,             /* opaque pointer (not used) */
-    uInt,               /* number of items */
-    uInt));             /* size of item */
-
-local void ffree OF((
-    voidpf q,           /* opaque pointer (not used) */
-    voidpf p,           /* what to free (not used) */
-    uInt n));		/* number of bytes (not used) */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* actually lengths - 2; also see note #13 above about 258 */
-local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
-local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-local uInt cpdext[] = { /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
-
-/*
-   Huffman code decoding is performed using a multi-level table lookup.
-   The fastest way to decode is to simply build a lookup table whose
-   size is determined by the longest code.  However, the time it takes
-   to build this table can also be a factor if the data being decoded
-   is not very long.  The most common codes are necessarily the
-   shortest codes, so those codes dominate the decoding time, and hence
-   the speed.  The idea is you can have a shorter table that decodes the
-   shorter, more probable codes, and then point to subsidiary tables for
-   the longer codes.  The time it costs to decode the longer codes is
-   then traded against the time it takes to make longer tables.
-
-   This results of this trade are in the variables lbits and dbits
-   below.  lbits is the number of bits the first level table for literal/
-   length codes can decode in one step, and dbits is the same thing for
-   the distance codes.  Subsequent tables are also less than or equal to
-   those sizes.  These values may be adjusted either when all of the
-   codes are shorter than that, in which case the longest code length in
-   bits is used, or when the shortest code is *longer* than the requested
-   table size, in which case the length of the shortest code in bits is
-   used.
-
-   There are two different values for the two tables, since they code a
-   different number of possibilities each.  The literal/length table
-   codes 286 possible values, or in a flat code, a little over eight
-   bits.  The distance table codes 30 possible values, or a little less
-   than five bits, flat.  The optimum values for speed end up being
-   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
-   The optimum values may differ though from machine to machine, and
-   possibly even between compilers.  Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15         /* maximum bit length of any code */
-#define N_MAX 288       /* maximum number of codes in any set */
-
-#ifdef DEBUG_ZLIB
-  uInt inflate_hufts;
-#endif
-
-local int huft_build(b, n, s, d, e, t, m, zs)
-uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
-uInt n;                 /* number of codes (assumed <= N_MAX) */
-uInt s;                 /* number of simple-valued codes (0..s-1) */
-uIntf *d;               /* list of base values for non-simple codes */
-uIntf *e;               /* list of extra bits for non-simple codes */  
-inflate_huft * FAR *t;  /* result: starting table */
-uIntf *m;               /* maximum lookup bits, returns actual */
-z_stream *zs;           /* for zalloc function */
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
-   if the given code set is incomplete (the tables are still built in this
-   case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
-   over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
-  uInt a;                       /* counter for codes of length k */
-  uInt c[BMAX+1];               /* bit length count table */
-  uInt f;                       /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register uInt i;              /* counter, current code */
-  register uInt j;              /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  register uIntf *p;            /* pointer into c[], b[], or v[] */
-  inflate_huft *q;              /* points to current table */
-  struct inflate_huft_s r;      /* table entry for structure assignment */
-  inflate_huft *u[BMAX];        /* table stack */
-  uInt v[N_MAX];                /* values in order of bit length */
-  register int w;               /* bits before this table == (l * h) */
-  uInt x[BMAX+1];               /* bit offsets, then code stack */
-  uIntf *xp;                    /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  uInt z;                       /* number of entries in current table */
-
-
-  /* Generate counts for each bit length */
-  p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
-  C4                            /* clear c[]--assume BMAX+1 is 16 */
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = (inflate_huft *)Z_NULL;
-    *m = 0;
-    return Z_OK;
-  }
-
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((uInt)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((uInt)l > i)
-    l = i;
-  *m = l;
-
-
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return Z_DATA_ERROR;
-  if ((y -= c[i]) < 0)
-    return Z_DATA_ERROR;
-  c[i] += y;
-
-
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
-
-
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
-  q = (inflate_huft *)Z_NULL;   /* ditto */
-  z = 0;                        /* ditto */
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-    a = c[k];
-    while (a--)
-    {
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = (z = g - w) > (uInt)l ? l : z;      /* table size upper limit */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          if (j < z)
-            while (++j < z)     /* try smaller tables up to z bits */
-            {
-              if ((f <<= 1) <= *++xp)
-                break;          /* enough codes to use up j bits */
-              f -= *xp;         /* else deduct codes from patterns */
-            }
-        }
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate and link in new table */
-        if ((q = (inflate_huft *)ZALLOC
-             (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
-        {
-          if (h)
-            inflate_trees_free(u[0], zs);
-          return Z_MEM_ERROR;   /* not enough memory */
-        }
-	q->word.Nalloc = z + 1;
-#ifdef DEBUG_ZLIB
-        inflate_hufts += z + 1;
-#endif
-        *t = q + 1;             /* link to list for huft_free() */
-        *(t = &(q->next)) = Z_NULL;
-        u[h] = ++q;             /* table starts after link */
-
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.bits = (Byte)l;     /* bits to dump before this table */
-          r.exop = (Byte)j;     /* bits in this table */
-          r.next = q;           /* pointer to this table */
-          j = i >> (w - l);     /* (get around Turbo C bug) */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-      }
-
-      /* set up table entry in r */
-      r.bits = (Byte)(k - w);
-      if (p >= v + n)
-        r.exop = 128 + 64;      /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
-        r.base = *p++;          /* simple code is just the value */
-      }
-      else
-      {
-        r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
-        r.base = d[*p++ - s];
-      }
-
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
-
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
-
-      /* backup over finished tables */
-      while ((i & ((1 << w) - 1)) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-      }
-    }
-  }
-
-
-  /* Return Z_BUF_ERROR if we were given an incomplete table */
-  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-local int inflate_trees_bits(c, bb, tb, z)
-uIntf *c;               /* 19 code lengths */
-uIntf *bb;              /* bits tree desired/actual depth */
-inflate_huft * FAR *tb; /* bits tree result */
-z_stream *z;            /* for zfree function */
-{
-  int r;
-
-  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
-  if (r == Z_DATA_ERROR)
-    z->msg = "oversubscribed dynamic bit lengths tree";
-  else if (r == Z_BUF_ERROR)
-  {
-    inflate_trees_free(*tb, z);
-    z->msg = "incomplete dynamic bit lengths tree";
-    r = Z_DATA_ERROR;
-  }
-  return r;
-}
-
-
-local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
-uInt nl;                /* number of literal/length codes */
-uInt nd;                /* number of distance codes */
-uIntf *c;               /* that many (total) code lengths */
-uIntf *bl;              /* literal desired/actual bit depth */
-uIntf *bd;              /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-z_stream *z;            /* for zfree function */
-{
-  int r;
-
-  /* build literal/length tree */
-  if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = "oversubscribed literal/length tree";
-    else if (r == Z_BUF_ERROR)
-    {
-      inflate_trees_free(*tl, z);
-      z->msg = "incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    return r;
-  }
-
-  /* build distance tree */
-  if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = "oversubscribed literal/length tree";
-    else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
-      r = Z_OK;
-    }
-#else
-      inflate_trees_free(*td, z);
-      z->msg = "incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    inflate_trees_free(*tl, z);
-    return r;
-#endif
-  }
-
-  /* done */
-  return Z_OK;
-}
-
-
-/* build fixed tables only once--keep them here */
-local int fixed_lock = 0;
-local int fixed_built = 0;
-#define FIXEDH 530      /* number of hufts used by fixed tables */
-local uInt fixed_left = FIXEDH;
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-
-
-local voidpf falloc(q, n, s)
-voidpf q;        /* opaque pointer (not used) */
-uInt n;         /* number of items */
-uInt s;         /* size of item */
-{
-  Assert(s == sizeof(inflate_huft) && n <= fixed_left,
-         "inflate_trees falloc overflow");
-  if (q) s++; /* to make some compilers happy */
-  fixed_left -= n;
-  return (voidpf)(fixed_mem + fixed_left);
-}
-
-
-local void ffree(q, p, n)
-voidpf q;
-voidpf p;
-uInt n;
-{
-  Assert(0, "inflate_trees ffree called!");
-  if (q) q = p; /* to make some compilers happy */
-}
-
-
-local int inflate_trees_fixed(bl, bd, tl, td)
-uIntf *bl;               /* literal desired/actual bit depth */
-uIntf *bd;               /* distance desired/actual bit depth */
-inflate_huft * FAR *tl;  /* literal/length tree result */
-inflate_huft * FAR *td;  /* distance tree result */
-{
-  /* build fixed tables if not built already--lock out other instances */
-  while (++fixed_lock > 1)
-    fixed_lock--;
-  if (!fixed_built)
-  {
-    int k;              /* temporary variable */
-    unsigned c[288];    /* length list for huft_build */
-    z_stream z;         /* for falloc function */
-
-    /* set up fake z_stream for memory routines */
-    z.zalloc = falloc;
-    z.zfree = ffree;
-    z.opaque = Z_NULL;
-
-    /* literal table */
-    for (k = 0; k < 144; k++)
-      c[k] = 8;
-    for (; k < 256; k++)
-      c[k] = 9;
-    for (; k < 280; k++)
-      c[k] = 7;
-    for (; k < 288; k++)
-      c[k] = 8;
-    fixed_bl = 7;
-    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
-
-    /* distance table */
-    for (k = 0; k < 30; k++)
-      c[k] = 5;
-    fixed_bd = 5;
-    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
-
-    /* done */
-    fixed_built = 1;
-  }
-  fixed_lock--;
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
-  return Z_OK;
-}
-
-
-local int inflate_trees_free(t, z)
-inflate_huft *t;        /* table to free */
-z_stream *z;            /* for zfree function */
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
-   list of the tables it made, with the links in a dummy first entry of
-   each table. */
-{
-  register inflate_huft *p, *q;
-
-  /* Go through linked list, freeing from the malloced (t[-1]) address. */
-  p = t;
-  while (p != Z_NULL)
-  {
-    q = (--p)->next;
-    ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
-    p = q;
-  } 
-  return Z_OK;
-}
-
-/*+++++*/
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
-  /* mode */
-  enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-      START,    /* x: set up for LEN */
-      LEN,      /* i: get length/literal/eob next */
-      LENEXT,   /* i: getting length extra (have base) */
-      DIST,     /* i: get distance next */
-      DISTEXT,  /* i: getting distance extra */
-      COPY,     /* o: copying bytes in window, waiting for space */
-      LIT,      /* o: got literal, waiting for output space */
-      WASH,     /* o: got eob, possibly still output waiting */
-      END,      /* x: got eob and all data flushed */
-      BADCODE}  /* x: got error */
-    mode;               /* current inflate_codes mode */
-
-  /* mode dependent information */
-  uInt len;
-  union {
-    struct {
-      inflate_huft *tree;       /* pointer into tree */
-      uInt need;                /* bits needed */
-    } code;             /* if LEN or DIST, where in tree */
-    uInt lit;           /* if LIT, literal */
-    struct {
-      uInt get;                 /* bits to get for extra */
-      uInt dist;                /* distance back to copy from */
-    } copy;             /* if EXT or COPY, where and how much */
-  } sub;                /* submode */
-
-  /* mode independent information */
-  Byte lbits;           /* ltree bits decoded per branch */
-  Byte dbits;           /* dtree bits decoder per branch */
-  inflate_huft *ltree;          /* literal/length/eob tree */
-  inflate_huft *dtree;          /* distance tree */
-
-};
-
-
-local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
-uInt bl, bd;
-inflate_huft *tl, *td;
-z_stream *z;
-{
-  inflate_codes_statef *c;
-
-  if ((c = (inflate_codes_statef *)
-       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
-  {
-    c->mode = START;
-    c->lbits = (Byte)bl;
-    c->dbits = (Byte)bd;
-    c->ltree = tl;
-    c->dtree = td;
-    Tracev((stderr, "inflate:       codes new\n"));
-  }
-  return c;
-}
-
-
-local int inflate_codes(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
-  uInt j;               /* temporary storage */
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  Bytef *f;             /* pointer to copy strings from */
-  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input and output based on current state */
-  while (1) switch (c->mode)
-  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-    case START:         /* x: set up for LEN */
-#ifndef SLOW
-      if (m >= 258 && n >= 10)
-      {
-        UPDATE
-        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
-        LOAD
-        if (r != Z_OK)
-        {
-          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
-          break;
-        }
-      }
-#endif /* !SLOW */
-      c->sub.code.need = c->lbits;
-      c->sub.code.tree = c->ltree;
-      c->mode = LEN;
-    case LEN:           /* i: get length/literal/eob next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e == 0)               /* literal */
-      {
-        c->sub.lit = t->base;
-        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                 "inflate:         literal '%c'\n" :
-                 "inflate:         literal 0x%02x\n", t->base));
-        c->mode = LIT;
-        break;
-      }
-      if (e & 16)               /* length */
-      {
-        c->sub.copy.get = e & 15;
-        c->len = t->base;
-        c->mode = LENEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t->next;
-        break;
-      }
-      if (e & 32)               /* end of block */
-      {
-        Tracevv((stderr, "inflate:         end of block\n"));
-        c->mode = WASH;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = "invalid literal/length code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case LENEXT:        /* i: getting length extra (have base) */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->len += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      c->sub.code.need = c->dbits;
-      c->sub.code.tree = c->dtree;
-      Tracevv((stderr, "inflate:         length %u\n", c->len));
-      c->mode = DIST;
-    case DIST:          /* i: get distance next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e & 16)               /* distance */
-      {
-        c->sub.copy.get = e & 15;
-        c->sub.copy.dist = t->base;
-        c->mode = DISTEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t->next;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = "invalid distance code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case DISTEXT:       /* i: getting distance extra */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->sub.copy.dist += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
-      c->mode = COPY;
-    case COPY:          /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
-      f = (uInt)(q - s->window) < c->sub.copy.dist ?
-          s->end - (c->sub.copy.dist - (q - s->window)) :
-          q - c->sub.copy.dist;
-#else
-      f = q - c->sub.copy.dist;
-      if ((uInt)(q - s->window) < c->sub.copy.dist)
-        f = s->end - (c->sub.copy.dist - (q - s->window));
-#endif
-      while (c->len)
-      {
-        NEEDOUT
-        OUTBYTE(*f++)
-        if (f == s->end)
-          f = s->window;
-        c->len--;
-      }
-      c->mode = START;
-      break;
-    case LIT:           /* o: got literal, waiting for output space */
-      NEEDOUT
-      OUTBYTE(c->sub.lit)
-      c->mode = START;
-      break;
-    case WASH:          /* o: got eob, possibly more output */
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      c->mode = END;
-    case END:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADCODE:       /* x: got error */
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-local void inflate_codes_free(c, z)
-inflate_codes_statef *c;
-z_stream *z;
-{
-  ZFREE(z, c, sizeof(struct inflate_codes_state));
-  Tracev((stderr, "inflate:       codes free\n"));
-}
-
-/*+++++*/
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
-  uInt n;
-  Bytef *p, *q;
-
-  /* local copies of source and destination pointers */
-  p = z->next_out;
-  q = s->read;
-
-  /* compute number of bytes to copy as far as end of window */
-  n = (uInt)((q <= s->write ? s->write : s->end) - q);
-  if (n > z->avail_out) n = z->avail_out;
-  if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-  /* update counters */
-  z->avail_out -= n;
-  z->total_out += n;
-
-  /* update check information */
-  if (s->checkfn != Z_NULL)
-    s->check = (*s->checkfn)(s->check, q, n);
-
-  /* copy as far as end of window */
-  zmemcpy(p, q, n);
-  p += n;
-  q += n;
-
-  /* see if more to copy at beginning of window */
-  if (q == s->end)
-  {
-    /* wrap pointers */
-    q = s->window;
-    if (s->write == s->end)
-      s->write = s->window;
-
-    /* compute bytes to copy */
-    n = (uInt)(s->write - q);
-    if (n > z->avail_out) n = z->avail_out;
-    if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-    /* update counters */
-    z->avail_out -= n;
-    z->total_out += n;
-
-    /* update check information */
-    if (s->checkfn != Z_NULL)
-      s->check = (*s->checkfn)(s->check, q, n);
-
-    /* copy */
-    zmemcpy(p, q, n);
-    p += n;
-    q += n;
-  }
-
-  /* update pointers */
-  z->next_out = p;
-  s->read = q;
-
-  /* done */
-  return r;
-}
-
-
-/*+++++*/
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
-
-/* Called with number of bytes left to write in window at least 258
-   (the maximum string length) and number of input bytes available
-   at least ten.  The ten bytes are six bytes for the longest length/
-   distance pair plus four bytes for overloading the bit buffer. */
-
-local int inflate_fast(bl, bd, tl, td, s, z)
-uInt bl, bd;
-inflate_huft *tl, *td;
-inflate_blocks_statef *s;
-z_stream *z;
-{
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  uInt ml;              /* mask for literal/length tree */
-  uInt md;              /* mask for distance tree */
-  uInt c;               /* bytes to copy */
-  uInt d;               /* distance back to copy from */
-  Bytef *r;             /* copy source pointer */
-
-  /* load input, output, bit values */
-  LOAD
-
-  /* initialize masks */
-  ml = inflate_mask[bl];
-  md = inflate_mask[bd];
-
-  /* do until not enough input or output space for fast loop */
-  do {                          /* assume called with m >= 258 && n >= 10 */
-    /* get literal/length code */
-    GRABBITS(20)                /* max bits for literal/length code */
-    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
-    {
-      DUMPBITS(t->bits)
-      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                "inflate:         * literal '%c'\n" :
-                "inflate:         * literal 0x%02x\n", t->base));
-      *q++ = (Byte)t->base;
-      m--;
-      continue;
-    }
-    do {
-      DUMPBITS(t->bits)
-      if (e & 16)
-      {
-        /* get extra bits for length */
-        e &= 15;
-        c = t->base + ((uInt)b & inflate_mask[e]);
-        DUMPBITS(e)
-        Tracevv((stderr, "inflate:         * length %u\n", c));
-
-        /* decode distance base of block to copy */
-        GRABBITS(15);           /* max bits for distance code */
-        e = (t = td + ((uInt)b & md))->exop;
-        do {
-          DUMPBITS(t->bits)
-          if (e & 16)
-          {
-            /* get extra bits to add to distance base */
-            e &= 15;
-            GRABBITS(e)         /* get extra bits (up to 13) */
-            d = t->base + ((uInt)b & inflate_mask[e]);
-            DUMPBITS(e)
-            Tracevv((stderr, "inflate:         * distance %u\n", d));
-
-            /* do the copy */
-            m -= c;
-            if ((uInt)(q - s->window) >= d)     /* offset before dest */
-            {                                   /*  just copy */
-              r = q - d;
-              *q++ = *r++;  c--;        /* minimum count is three, */
-              *q++ = *r++;  c--;        /*  so unroll loop a little */
-            }
-            else                        /* else offset after destination */
-            {
-              e = d - (q - s->window);  /* bytes from offset to end */
-              r = s->end - e;           /* pointer to offset */
-              if (c > e)                /* if source crosses, */
-              {
-                c -= e;                 /* copy to end of window */
-                do {
-                  *q++ = *r++;
-                } while (--e);
-                r = s->window;          /* copy rest from start of window */
-              }
-            }
-            do {                        /* copy all or what's left */
-              *q++ = *r++;
-            } while (--c);
-            break;
-          }
-          else if ((e & 64) == 0)
-            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
-          else
-          {
-            z->msg = "invalid distance code";
-            UNGRAB
-            UPDATE
-            return Z_DATA_ERROR;
-          }
-        } while (1);
-        break;
-      }
-      if ((e & 64) == 0)
-      {
-        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
-        {
-          DUMPBITS(t->bits)
-          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                    "inflate:         * literal '%c'\n" :
-                    "inflate:         * literal 0x%02x\n", t->base));
-          *q++ = (Byte)t->base;
-          m--;
-          break;
-        }
-      }
-      else if (e & 32)
-      {
-        Tracevv((stderr, "inflate:         * end of block\n"));
-        UNGRAB
-        UPDATE
-        return Z_STREAM_END;
-      }
-      else
-      {
-        z->msg = "invalid literal/length code";
-        UNGRAB
-        UPDATE
-        return Z_DATA_ERROR;
-      }
-    } while (1);
-  } while (m >= 258 && n >= 10);
-
-  /* not enough input or output--restore pointers and return */
-  UNGRAB
-  UPDATE
-  return Z_OK;
-}
-
-
-/*+++++*/
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
-
-char *zlib_version = ZLIB_VERSION;
-
-char *z_errmsg[] = {
-"stream end",          /* Z_STREAM_END    1 */
-"",                    /* Z_OK            0 */
-"file error",          /* Z_ERRNO        (-1) */
-"stream error",        /* Z_STREAM_ERROR (-2) */
-"data error",          /* Z_DATA_ERROR   (-3) */
-"insufficient memory", /* Z_MEM_ERROR    (-4) */
-"buffer error",        /* Z_BUF_ERROR    (-5) */
-""};
-
-
-/*+++++*/
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf)  {s1 += *buf++; s2 += s1;}
-#define DO2(buf)  DO1(buf); DO1(buf);
-#define DO4(buf)  DO2(buf); DO2(buf);
-#define DO8(buf)  DO4(buf); DO4(buf);
-#define DO16(buf) DO8(buf); DO8(buf);
-
-/* ========================================================================= */
-uLong adler32(adler, buf, len)
-    uLong adler;
-    Bytef *buf;
-    uInt len;
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-            k -= 16;
-        }
-        if (k != 0) do {
-            DO1(buf);
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/coffboot/zlib.h linux/arch/ppc/coffboot/zlib.h
--- v2.4.4/linux/arch/ppc/coffboot/zlib.h	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/zlib.h	Wed Dec 31 16:00:00 1969
@@ -1,432 +0,0 @@
-/*	$Id: zlib.h,v 1.1 1997/07/31 07:16:15 paulus Exp $	*/
-
-/*
- * This file is derived from zlib.h and zconf.h from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.
- */
-
-/*
- *  ==FILEVERSION 960122==
- *
- * This marker is used by the Linux installation script to determine
- * whether an up-to-date version of this file is already installed.
- */
-
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 0.95, Aug 16th, 1995.
-
-  Copyright (C) 1995 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
- */
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-/* #include "zconf.h" */	/* included directly here */
-
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
-
-/*
-     The library does not install any signal handler. It is recommended to
-  add at least a handler for SIGSEGV when decompressing; the library checks
-  the consistency of the input data whenever possible but may go nuts
-  for some forms of corrupted input.
- */
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
- * at addresses which are not a multiple of their size.
- * Under DOS, -DFAR=far or -DFAR=__far may be needed.
- */
-
-#ifndef STDC
-#  if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
-#    define STDC
-#  endif
-#endif
-
-#ifdef	__MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
-#  include <unix.h>
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-#ifndef FAR
-#  define FAR
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            1 << (windowBits+2)   +  1 << (memLevel+9)
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-typedef Byte FAR Bytef;
-typedef char FAR charf;
-typedef int FAR intf;
-typedef uInt FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void FAR *voidpf;
-   typedef void     *voidp;
-#else
-   typedef Byte FAR *voidpf;
-   typedef Byte     *voidp;
-#endif
-
-/* end of original zconf.h */
-
-#define ZLIB_VERSION "0.95P"
-
-/* 
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms may be added later and will have the same
-  stream interface.
-
-     For compression the application must provide the output buffer and
-  may optionally provide the input buffer for optimization. For decompression,
-  the application must provide the input buffer and may optionally provide
-  the output buffer for optimization.
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
-  (providing more output space) before each call.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address, uInt nbytes));
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    Bytef    *next_in;  /* next input byte */
-    uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
-
-    Bytef    *next_out; /* next output byte should be put there */
-    uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state FAR *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    voidp      opaque;  /* private data object passed to zalloc and zfree */
-
-    Byte     data_type; /* best guess about the data type: ascii or binary */
-
-} z_stream;
-
-/*
-   The application must update next_in and avail_in when avail_in has
-   dropped to zero. It must update next_out and avail_out when avail_out
-   has dropped to zero. The application must initialize zalloc, zfree and
-   opaque before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application.
-
-   The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
-   opaque value.
-
-   zalloc must return Z_NULL if there is not enough memory for the object.
-   On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by zalloc for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
-   The fields total_in and total_out can be used for statistics or
-   progress reports. After compression, total_in holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1
-#define Z_FULL_FLUSH    2
-#define Z_SYNC_FLUSH    3 /* experimental: partial_flush + byte align */
-#define Z_FINISH        4
-#define Z_PACKET_FLUSH	5
-/* See deflate() below for the usage of these constants */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-/* error codes for the compression/decompression functions */
-
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_DEFAULT_STRATEGY    0
-
-#define Z_BINARY   0
-#define Z_ASCII    1
-#define Z_UNKNOWN  2
-/* Used to set the data_type field */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-extern char *zlib_version;
-/* The application can compare zlib_version and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
- */
-
-                        /* basic functions */
-
-extern int inflateInit OF((z_stream *strm));
-/* 
-     Initializes the internal stream state for decompression. The fields
-   zalloc and zfree must be initialized before by the caller.  If zalloc and
-   zfree are set to Z_NULL, inflateInit updates them to use default allocation
-   functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory.  msg is set to null if there is no error message.
-   inflateInit does not perform any decompression: this will be done by
-   inflate().
-*/
-
-
-extern int inflate OF((z_stream *strm, int flush));
-/*
-  Performs one or both of the following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of inflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() always provides as much output as possible
-    (until there is no more input data or no more space in the output buffer).
-
-  Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (avail_out == 0), or after each
-  call of inflate().
-
-    If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
-  inflate flushes as much output as possible to the output buffer. The
-  flushing behavior of inflate is not specified for values of the flush
-  parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
-  current implementation actually flushes as much output as possible
-  anyway.  For Z_PACKET_FLUSH, inflate checks that once all the input data
-  has been consumed, it is expecting to see the length field of a stored
-  block; if not, it returns Z_DATA_ERROR.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of inflate), the parameter flush should be set to
-  Z_FINISH. In this case all pending input is processed and all pending
-  output is flushed; avail_out must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster routine
-  may be used for the single inflate() call.
-
-    inflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if the end of the
-  compressed data has been reached and all uncompressed output has been
-  produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
-  the stream structure was inconsistent (for example if next_in or next_out
-  was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
-  progress is possible or if there was not enough room in the output buffer
-  when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
-  call inflateSync to look for a good compression block.  */
-
-
-extern int inflateEnd OF((z_stream *strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent. In the error case, msg may be set but then points to a
-   static string (which must not be deallocated).
-*/
-
-                        /* advanced functions */
-
-extern int inflateInit2 OF((z_stream *strm,
-                            int  windowBits));
-/*   
-     This is another version of inflateInit with more compression options. The
-   fields next_out, zalloc and zfree must be initialized before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library (the value 16 will be allowed soon). The
-   default value is 15 if inflateInit is used instead. If a compressed stream
-   with a larger window size is given as input, inflate() will return with
-   the error code Z_DATA_ERROR instead of trying to allocate a larger window.
-
-     If next_out is not null, the library will use this buffer for the history
-   buffer; the buffer must either be large enough to hold the entire output
-   data, or have at least 1<<windowBits bytes.  If next_out is null, the
-   library will allocate its own buffer (and leave next_out null). next_in
-   need not be provided here but must be provided by the application for the
-   next call of inflate().
-
-     If the history buffer is provided by the application, next_out must
-   never be changed by the application since the decompressor maintains
-   history information inside this buffer from call to call; the application
-   can only reset next_out to the beginning of the history buffer when
-   avail_out is zero and all output has been consumed.
-
-      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
-   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
-   windowBits < 8). msg is set to null if there is no error message.
-   inflateInit2 does not perform any decompression: this will be done by
-   inflate().
-*/
-
-extern int inflateSync OF((z_stream *strm));
-/* 
-    Skips invalid compressed data until the special marker (see deflate()
-  above) can be found, or until all available input is skipped. No output
-  is provided.
-
-    inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
-  if no more input was provided, Z_DATA_ERROR if no marker has been found,
-  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call inflateSync, providing more input each time,
-  until success or end of the input data.
-*/
-
-extern int inflateReset OF((z_stream *strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.
-   The stream will keep attributes that may have been set by inflateInit2.
-
-      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-extern int inflateIncomp OF((z_stream *strm));
-/*
-     This function adds the data at next_in (avail_in bytes) to the output
-   history without performing any output.  There must be no pending output,
-   and the decompressor must be expecting to see the start of a block.
-   Calling this function is equivalent to decompressing a stored block
-   containing the data at next_in (except that the data is not output).
-*/
-
-                        /* checksum functions */
-
-/*
-     This function is not related to compression but is exported
-   anyway because it might be useful in applications using the
-   compression library.
-*/
-
-extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
-
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-#ifndef _Z_UTIL_H
-    struct internal_state {int dummy;}; /* hack for buggy compilers */
-#endif
-
-#endif /* _ZLIB_H */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.4.4/linux/arch/ppc/config.in	Tue Apr 17 17:19:25 2001
+++ linux/arch/ppc/config.in	Tue May 22 10:23:16 2001
@@ -1,10 +1,11 @@
-# $Id: config.in,v 1.106 1999/09/14 19:21:18 cort Exp $
+# BK Id: SCCS/s.config.in 1.24 05/21/01 00:48:24 cort
+#
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
 define_bool CONFIG_UID16 n
-define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
-define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
@@ -84,6 +85,7 @@
 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
   choice 'Machine Type'		\
 	"PowerMac/PReP/MTX/CHRP	CONFIG_ALL_PPC	\
+	 Gemini         CONFIG_GEMINI           \
 	 APUS		CONFIG_APUS"		PowerMac/PReP/MTX/CHRP
 fi
 
@@ -104,10 +106,6 @@
   bool 'AltiVec Support' CONFIG_ALTIVEC
 fi
 
-if [ "$CONFIG_ALL_PPC" != "y" ];then
-  define_bool CONFIG_MACH_SPECIFIC y
-fi
-
 if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then
   bool 'Math emulation' CONFIG_MATH_EMULATION
 fi
@@ -118,7 +116,6 @@
 comment 'General setup'
 
 bool 'High memory support (experimental)' CONFIG_HIGHMEM
-bool 'Mac-on-Linux support' CONFIG_MOL
 
 define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
@@ -127,15 +124,19 @@
 # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
 define_bool CONFIG_MCA n
 
-if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \
-     "$CONFIG_8260" = "y" ]; then
+if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8260" = "y" ]; then
   define_bool CONFIG_PCI n
 else
   if [ "$CONFIG_8xx" = "y" ]; then
      bool 'QSpan PCI' CONFIG_PCI_QSPAN
      define_bool CONFIG_PCI $CONFIG_PCI_QSPAN
   else
-     define_bool CONFIG_PCI y
+     if [ "$CONFIG_APUS" = "y" ]; then
+       bool 'PCI for Permedia2' CONFIG_PCI_PERMEDIA
+       define_bool CONFIG_PCI $CONFIG_PCI_PERMEDIA
+     else
+       define_bool CONFIG_PCI y
+     fi
   fi
 fi
 
@@ -165,7 +166,11 @@
 source drivers/parport/Config.in
 
 if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
-  tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
+  if [ "$CONFIG_APUS" != "y" ]; then
+    tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
+  else
+    bool 'Generic /dev/rtc emulation' CONFIG_GEN_RTC
+  fi
 fi
 
 if [ "$CONFIG_ALL_PPC" = "y" ]; then
@@ -186,12 +191,26 @@
   define_bool CONFIG_AMIGAMOUSE y
   define_bool CONFIG_ABSTRACT_CONSOLE y
   define_bool CONFIG_FB y
+  define_bool CONFIG_MOUSE y
+  define_bool CONFIG_BUSMOUSE y
+  define_bool CONFIG_APUS_FAST_EXCEPT y
+
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    bool 'Amiga 1200/600 PCMCIA support' CONFIG_AMIGA_PCMCIA
+  fi
+
   tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
-  tristate 'Parallel printer support' CONFIG_M68K_PRINTER
   tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
   dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
   dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
   tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
+  fi
+  if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
+    tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL
+    tristate 'PCMCIA NE2000 support' CONFIG_APNE
+  fi
   if [ "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o "$CONFIG_GVPIOEXT" = "y" -o \
        "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
     bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/IVMS8_defconfig linux/arch/ppc/configs/IVMS8_defconfig
--- v2.4.4/linux/arch/ppc/configs/IVMS8_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/IVMS8_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -40,9 +41,9 @@
 # CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SASH=y
 CONFIG_SASH_PATH="/bin/sash"
@@ -50,8 +51,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -87,17 +92,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -116,10 +127,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -136,6 +145,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -184,11 +194,10 @@
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
-CONFIG_BLK_DEV_MPC8xx_IDE=y
 # CONFIG_IDE_CHIPSETS is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_IDE_MODES is not set
 
 #
 # SCSI support
@@ -207,6 +216,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -232,8 +242,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -288,6 +299,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -312,6 +332,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -321,12 +345,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_FLASH is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -335,8 +353,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -344,6 +367,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -356,6 +381,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -398,8 +424,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -416,6 +440,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -430,14 +455,15 @@
 CONFIG_FEC_ENET=y
 CONFIG_USE_MDIO=y
 CONFIG_ENET_BIG_BUFFERS=y
-# CONFIG_8xxSMC2 is not set
-# CONFIG_8xxSCC is not set
+# CONFIG_SMC2_UART is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
 #
 CONFIG_8xx_COPYBACK=y
 # CONFIG_8xx_CPU6 is not set
+CONFIG_BLK_DEV_MPC8xx_IDE=y
 
 #
 # USB support
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/SM850_defconfig linux/arch/ppc/configs/SM850_defconfig
--- v2.4.4/linux/arch/ppc/configs/SM850_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/SM850_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,13 +37,14 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
 CONFIG_SM850=y
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SASH=y
 CONFIG_SASH_PATH="/bin/sash"
@@ -50,8 +52,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -87,17 +93,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -116,10 +128,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -136,6 +146,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -170,6 +181,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -195,8 +207,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -251,6 +264,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -275,6 +297,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -284,13 +310,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -299,8 +318,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -308,6 +332,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -320,6 +346,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -362,8 +389,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -380,6 +405,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -396,10 +422,10 @@
 CONFIG_SCC3_ENET=y
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-CONFIG_8xx_CONS_SMC2=y
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+CONFIG_CONS_SMC2=y
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/SPD823TS_defconfig linux/arch/ppc/configs/SPD823TS_defconfig
--- v2.4.4/linux/arch/ppc/configs/SPD823TS_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/SPD823TS_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,11 +37,13 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 CONFIG_SPD823TS=y
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SASH=y
 CONFIG_SASH_PATH="/bin/sash"
@@ -48,8 +51,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -85,17 +92,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -114,10 +127,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -134,6 +145,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -168,6 +180,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -193,8 +206,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -249,6 +263,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -273,6 +296,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -282,12 +309,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_FLASH is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -296,8 +317,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -305,6 +331,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -317,6 +345,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -359,8 +388,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -377,6 +404,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -390,12 +418,13 @@
 CONFIG_SCC_ENET=y
 # CONFIG_SCC1_ENET is not set
 CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/TQM823L_defconfig linux/arch/ppc/configs/TQM823L_defconfig
--- v2.4.4/linux/arch/ppc/configs/TQM823L_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/TQM823L_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,12 +37,14 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SASH=y
 CONFIG_SASH_PATH="/bin/sash"
@@ -49,8 +52,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -86,17 +93,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -115,10 +128,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -135,6 +146,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -169,6 +181,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -194,8 +207,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -250,6 +264,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -274,6 +297,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -283,13 +310,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -298,8 +318,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -307,6 +332,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -319,6 +346,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -361,8 +389,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -379,6 +405,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -395,10 +422,10 @@
 # CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/TQM850L_defconfig linux/arch/ppc/configs/TQM850L_defconfig
--- v2.4.4/linux/arch/ppc/configs/TQM850L_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/TQM850L_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,12 +37,14 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SASH=y
 CONFIG_SASH_PATH="/bin/sash"
@@ -49,8 +52,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -86,17 +93,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -115,10 +128,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -135,6 +146,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -169,6 +181,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -194,8 +207,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -250,6 +264,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -274,6 +297,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -283,13 +310,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -298,8 +318,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -307,6 +332,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -319,6 +346,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -361,8 +389,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -379,6 +405,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -395,10 +422,10 @@
 # CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/TQM860L_defconfig linux/arch/ppc/configs/TQM860L_defconfig
--- v2.4.4/linux/arch/ppc/configs/TQM860L_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/TQM860L_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,12 +37,14 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SASH=y
 CONFIG_SASH_PATH="/bin/sash"
@@ -49,8 +52,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -86,17 +93,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -115,10 +128,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -135,6 +146,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -169,6 +181,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -194,8 +207,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -250,6 +264,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -274,6 +297,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -283,13 +310,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -298,8 +318,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -307,6 +332,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -319,6 +346,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -361,8 +389,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -379,6 +405,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -395,10 +422,10 @@
 # CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/apus_defconfig linux/arch/ppc/configs/apus_defconfig
--- v2.4.4/linux/arch/ppc/configs/apus_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/apus_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -11,7 +13,9 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
 
 #
 # Platform support
@@ -24,22 +28,21 @@
 # CONFIG_8xx is not set
 # CONFIG_8260 is not set
 # CONFIG_ALL_PPC is not set
+# CONFIG_GEMINI is not set
 CONFIG_APUS=y
-CONFIG_PPC601_SYNC_FIX=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_SMP is not set
 # CONFIG_ALTIVEC is not set
-CONFIG_MACH_SPECIFIC=y
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
 # CONFIG_MCA is not set
-# CONFIG_PCI is not set
+CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -47,32 +50,42 @@
 CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
+CONFIG_BINFMT_MISC=m
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
 
 #
 # Parallel port support
 #
-# CONFIG_PARPORT is not set
-CONFIG_PPC_RTC=y
+CONFIG_PARPORT=m
+# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_AMIGA=m
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+CONFIG_GEN_RTC=y
 CONFIG_FB_CONSOLE=y
 CONFIG_AMIGA=y
 CONFIG_ZORRO=y
 CONFIG_AMIGAMOUSE=y
 CONFIG_ABSTRACT_CONSOLE=y
 CONFIG_FB=y
+CONFIG_MOUSE=y
+CONFIG_BUSMOUSE=y
+CONFIG_APUS_FAST_EXCEPT=y
+CONFIG_AMIGA_PCMCIA=y
 CONFIG_AMIGA_BUILTIN_SERIAL=y
-# CONFIG_M68K_PRINTER is not set
 CONFIG_GVPIOEXT=y
-# CONFIG_GVPIOEXT_LP is not set
-CONFIG_GVPIOEXT_PLIP=y
+CONFIG_GVPIOEXT_LP=m
+CONFIG_GVPIOEXT_PLIP=m
 CONFIG_MULTIFACE_III_TTY=y
-# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_A2232=y
+CONFIG_WHIPPET_SERIAL=y
+CONFIG_APNE=y
+CONFIG_SERIAL_CONSOLE=y
 CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=y
 CONFIG_ZORRO_NAMES=y
@@ -93,14 +106,14 @@
 #
 # CONFIG_BLK_DEV_FD is not set
 CONFIG_AMIGA_FLOPPY=y
-CONFIG_AMIGA_Z2RAM=y
+CONFIG_AMIGA_Z2RAM=m
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -108,22 +121,25 @@
 #
 # Multi-device support (RAID and LVM)
 #
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_BLK_DEV_LVM=m
 
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+CONFIG_NETLINK_DEV=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_FILTER=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -132,9 +148,42 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
+CONFIG_SYN_COOKIES=y
+
+#
+#   IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_UNCLEAN=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_COMPAT_IPCHAINS=m
+CONFIG_IP_NF_NAT_NEEDED=y
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
 # CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
+CONFIG_KHTTPD=m
 # CONFIG_ATM is not set
 
 #
@@ -186,9 +235,9 @@
 # CONFIG_BLK_DEV_TIVO is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
 
 #
 # IDE chipset support/bugfixes
@@ -196,6 +245,9 @@
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
 CONFIG_BLK_DEV_GAYLE=y
 CONFIG_BLK_DEV_IDEDOUBLER=y
 CONFIG_BLK_DEV_BUDDHA=y
@@ -214,35 +266,38 @@
 #
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_SR_EXTRA_DEVS=4
+CONFIG_CHR_DEV_SG=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -253,20 +308,47 @@
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_MESH is not set
 # CONFIG_SCSI_MAC53C94 is not set
+CONFIG_A3000_SCSI=y
+CONFIG_A4000T_SCSI=y
+CONFIG_A2091_SCSI=y
+CONFIG_GVP11_SCSI=y
+CONFIG_CYBERSTORM_SCSI=y
+CONFIG_CYBERSTORMII_SCSI=y
+CONFIG_BLZ2060_SCSI=y
+CONFIG_BLZ1230_SCSI=y
+CONFIG_FASTLANE_SCSI=y
+CONFIG_A4091_SCSI=y
+CONFIG_WARPENGINE_SCSI=y
+CONFIG_BLZ603EPLUS_SCSI=y
+CONFIG_OKTAGON_SCSI=y
+CONFIG_CYBERSTORMIII_SCSI=y
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
 
 #
 # Network device support
@@ -277,10 +359,11 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
 #
@@ -290,9 +373,10 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 CONFIG_ARIADNE=y
-# CONFIG_NE2K_ZORRO is not set
+CONFIG_NE2K_ZORRO=y
 CONFIG_A2065=y
 CONFIG_HYDRA=y
 # CONFIG_NET_VENDOR_3COM is not set
@@ -301,6 +385,7 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
@@ -314,17 +399,19 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
+CONFIG_PLIP=m
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 CONFIG_PPP_DEFLATE=y
 CONFIG_PPP_BSDCOMP=y
-# CONFIG_PPPOE is not set
+CONFIG_PPPOE=y
 CONFIG_SLIP=y
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_SLIP_MODE_SLIP6=y
 
 #
 # Wireless LAN (non-hamradio)
@@ -374,10 +461,13 @@
 #
 CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
 CONFIG_FB_CLGEN=y
 CONFIG_FB_PM2=y
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+# CONFIG_FB_PM2_PCI is not set
 CONFIG_FB_PM2_CVPPC=y
-# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_CYBER2000=y
 CONFIG_FB_AMIGA=y
 CONFIG_FB_AMIGA_OCS=y
 CONFIG_FB_AMIGA_ECS=y
@@ -385,7 +475,7 @@
 CONFIG_FB_CYBER=y
 CONFIG_FB_VIRGE=y
 CONFIG_FB_RETINAZ3=y
-# CONFIG_FB_FM2 is not set
+CONFIG_FB_FM2=y
 # CONFIG_FB_OF is not set
 # CONFIG_FB_CONTROL is not set
 # CONFIG_FB_PLATINUM is not set
@@ -394,25 +484,50 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_SIS is not set
 # CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=y
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
 CONFIG_FBCON_CFB8=y
 CONFIG_FBCON_CFB16=y
 CONFIG_FBCON_CFB24=y
 CONFIG_FBCON_CFB32=y
 CONFIG_FBCON_AFB=y
 CONFIG_FBCON_ILBM=y
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-# CONFIG_FBCON_FONTS is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
+# CONFIG_FBCON_VGA is not set
+# CONFIG_FBCON_HGA is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+CONFIG_FONT_6x11=y
 CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
 
 #
 # Input core support
 #
-# CONFIG_INPUT is not set
+CONFIG_INPUT=m
+CONFIG_INPUT_KEYBDEV=m
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
 
 #
 # Macintosh device drivers
@@ -423,11 +538,14 @@
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
 
 #
 # I2C support
@@ -437,8 +555,14 @@
 #
 # Mice
 #
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
 
 #
 # Joysticks
@@ -477,8 +601,10 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 CONFIG_AFFS_FS=y
@@ -490,10 +616,11 @@
 CONFIG_VFAT_FS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
+CONFIG_CRAMFS=y
+CONFIG_TMPFS=y
+CONFIG_RAMFS=m
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+CONFIG_JOLIET=y
 CONFIG_MINIX_FS=y
 # CONFIG_NTFS_FS is not set
 # CONFIG_NTFS_RW is not set
@@ -502,10 +629,10 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVFS_MOUNT is not set
 # CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
+CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_ROMFS_FS=y
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_SYSV_FS_WRITE is not set
@@ -517,15 +644,17 @@
 #
 # Network File Systems
 #
-# CONFIG_CODA_FS is not set
+CONFIG_CODA_FS=m
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
-# CONFIG_SMB_FS is not set
+CONFIG_LOCKD_V4=y
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -539,53 +668,116 @@
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
 CONFIG_AMIGA_PARTITION=y
-# CONFIG_SMB_NLS is not set
+CONFIG_ATARI_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_SMB_NLS=y
 CONFIG_NLS=y
 
 #
 # Native Language Support
 #
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND_PAULA=m
+CONFIG_DMASOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_TRACEINIT=y
+CONFIG_SOUND_DMAP=y
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+CONFIG_SOUND_VMIDI=m
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_YMFPCI_LEGACY is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
@@ -595,6 +787,6 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_KGDB is not set
 # CONFIG_XMON is not set
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/bseip_defconfig linux/arch/ppc/configs/bseip_defconfig
--- v2.4.4/linux/arch/ppc/configs/bseip_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/bseip_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,22 +28,26 @@
 # CONFIG_RPXLITE is not set
 # CONFIG_RPXCLASSIC is not set
 CONFIG_BSEIP=y
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -100,7 +106,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -184,6 +189,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -323,6 +329,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -335,6 +343,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -407,11 +416,13 @@
 CONFIG_SCC_ENET=y
 # CONFIG_SCC1_ENET is not set
 CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 # CONFIG_ENET_BIG_BUFFERS is not set
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- v2.4.4/linux/arch/ppc/configs/common_defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/ppc/configs/common_defconfig	Wed May 16 09:57:20 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@
 # CONFIG_8xx is not set
 # CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
+# CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
@@ -35,7 +38,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-CONFIG_MOL=y
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -105,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -141,6 +142,7 @@
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -151,8 +153,10 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
@@ -296,6 +300,8 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
+CONFIG_AIC7XXX_RESET_DELAY=5000
 CONFIG_SCSI_AIC7XXX_OLD=m
 # CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT is not set
 CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8
@@ -376,8 +382,10 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
 CONFIG_BMAC=y
 CONFIG_GMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -404,7 +412,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -425,6 +435,7 @@
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
 CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=y
@@ -492,6 +503,7 @@
 CONFIG_FB_IMSTT=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -544,6 +556,7 @@
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_ADBKEYCODES=y
 CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -612,6 +625,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -624,6 +639,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -680,6 +696,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
@@ -707,11 +724,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -719,11 +738,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
@@ -740,6 +760,8 @@
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -814,7 +836,6 @@
 # USB Serial Converter support
 #
 CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
@@ -822,6 +843,7 @@
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 # CONFIG_USB_SERIAL_KEYSPAN is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/est8260_defconfig linux/arch/ppc/configs/est8260_defconfig
--- v2.4.4/linux/arch/ppc/configs/est8260_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/est8260_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -28,13 +30,11 @@
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -93,7 +93,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -177,6 +176,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -317,6 +317,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -329,6 +331,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig
--- v2.4.4/linux/arch/ppc/configs/gemini_defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/configs/gemini_defconfig	Mon May 21 17:04:46 2001
@@ -0,0 +1,509 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_6xx=y
+# CONFIG_4xx is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_8260 is not set
+# CONFIG_ALL_PPC is not set
+CONFIG_GEMINI=y
+# CONFIG_APUS is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_SMP is not set
+CONFIG_ALTIVEC=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_PCI=y
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PPC_RTC is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+#   IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_DEBUG_QUEUES is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+CONFIG_NCR885E=y
+# CONFIG_OAKNET is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+# CONFIG_RAMFS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+CONFIG_XMON=y
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/ibmchrp_defconfig linux/arch/ppc/configs/ibmchrp_defconfig
--- v2.4.4/linux/arch/ppc/configs/ibmchrp_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/ibmchrp_defconfig	Wed May 16 09:57:20 2001
@@ -1,7 +1,9 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,8 +25,8 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
+# CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
 # CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
@@ -36,7 +38,6 @@
 # General setup
 #
 CONFIG_HIGHMEM=y
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -101,7 +102,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -137,6 +137,7 @@
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -147,14 +148,20 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -184,6 +191,10 @@
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -192,6 +203,10 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
@@ -207,6 +222,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -306,7 +322,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -337,11 +355,9 @@
 # Token Ring devices
 #
 CONFIG_TR=y
-# CONFIG_IBMTR is not set
 CONFIG_IBMOL=y
 # CONFIG_IBMLS is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_SMCTR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -393,6 +409,7 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -439,6 +456,7 @@
 # CONFIG_MAC_FLOPPY is not set
 # CONFIG_MAC_SERIAL is not set
 # CONFIG_ADB is not set
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -473,6 +491,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -504,6 +526,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -516,6 +540,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -572,6 +597,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
@@ -599,11 +625,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -611,11 +639,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/mbx_defconfig linux/arch/ppc/configs/mbx_defconfig
--- v2.4.4/linux/arch/ppc/configs/mbx_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/mbx_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,22 +28,26 @@
 # CONFIG_RPXLITE is not set
 # CONFIG_RPXCLASSIC is not set
 # CONFIG_BSEIP is not set
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 CONFIG_MBX=y
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -99,7 +105,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -178,6 +183,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -316,6 +322,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -328,6 +336,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -399,11 +408,14 @@
 #
 CONFIG_SCC_ENET=y
 CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-CONFIG_8xxSCC=y
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+CONFIG_USE_SCC_IO=y
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig
--- v2.4.4/linux/arch/ppc/configs/oak_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/oak_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -28,14 +30,12 @@
 # CONFIG_WALNUT is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -93,7 +93,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -173,6 +172,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 CONFIG_OAKNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -312,6 +312,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -324,6 +326,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/power3_defconfig linux/arch/ppc/configs/power3_defconfig
--- v2.4.4/linux/arch/ppc/configs/power3_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/power3_defconfig	Wed May 16 09:57:20 2001
@@ -1,7 +1,9 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -27,12 +29,12 @@
 CONFIG_PPC64BRIDGE=y
 CONFIG_ALL_PPC=y
 CONFIG_SMP=y
+# CONFIG_IRQ_ALL_CPUS is not set
 
 #
 # General setup
 #
 CONFIG_HIGHMEM=y
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -105,10 +107,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID5=y
-# CONFIG_MD_BOOT is not set
-# CONFIG_AUTODETECT_RAID is not set
 CONFIG_BLK_DEV_LVM=y
-CONFIG_LVM_PROC_FS=y
 
 #
 # Networking options
@@ -133,6 +132,10 @@
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -162,6 +165,10 @@
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -170,6 +177,10 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
@@ -185,6 +196,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -259,6 +271,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -285,7 +298,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -317,11 +332,9 @@
 # Token Ring devices
 #
 CONFIG_TR=y
-# CONFIG_IBMTR is not set
 CONFIG_IBMOL=y
 # CONFIG_IBMLS is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_SMCTR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -373,6 +386,7 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -421,6 +435,7 @@
 # CONFIG_MAC_FLOPPY is not set
 # CONFIG_MAC_SERIAL is not set
 # CONFIG_ADB is not set
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -462,6 +477,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -507,6 +526,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
@@ -579,11 +599,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -591,11 +613,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
@@ -611,6 +634,8 @@
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -626,7 +651,6 @@
 CONFIG_SOUND_CS4232=m
 # CONFIG_SOUND_SSCAPE is not set
 # CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
 CONFIG_SOUND_MSS=m
@@ -643,8 +667,8 @@
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMPCI is not set
 # CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_YMFPCI_LEGACY is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
 CONFIG_SOUND_TVMIXER=y
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/rpxcllf_defconfig linux/arch/ppc/configs/rpxcllf_defconfig
--- v2.4.4/linux/arch/ppc/configs/rpxcllf_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/rpxcllf_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,22 +28,26 @@
 # CONFIG_RPXLITE is not set
 CONFIG_RPXCLASSIC=y
 # CONFIG_BSEIP is not set
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -100,7 +106,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -184,6 +189,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -323,6 +329,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -335,6 +343,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -406,11 +415,15 @@
 #
 CONFIG_SCC_ENET=y
 CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
 CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-CONFIG_8xxSCC=y
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+CONFIG_USE_SCC_IO=y
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/rpxlite_defconfig linux/arch/ppc/configs/rpxlite_defconfig
--- v2.4.4/linux/arch/ppc/configs/rpxlite_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/rpxlite_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,22 +28,26 @@
 CONFIG_RPXLITE=y
 # CONFIG_RPXCLASSIC is not set
 # CONFIG_BSEIP is not set
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_MATH_EMULATION=y
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -100,7 +106,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -184,6 +189,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -323,6 +329,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -335,6 +343,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -407,10 +416,11 @@
 CONFIG_SCC_ENET=y
 # CONFIG_SCC1_ENET is not set
 CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 # CONFIG_ENET_BIG_BUFFERS is not set
-# CONFIG_8xxSMC2 is not set
-# CONFIG_8xxSCC is not set
+# CONFIG_SMC2_UART is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig
--- v2.4.4/linux/arch/ppc/configs/walnut_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/walnut_defconfig	Mon May 21 17:04:46 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -28,14 +30,12 @@
 CONFIG_WALNUT=y
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
 
 #
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -93,7 +93,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -173,6 +172,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -315,6 +315,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -327,6 +329,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.4.4/linux/arch/ppc/defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/ppc/defconfig	Wed May 16 09:57:20 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@
 # CONFIG_8xx is not set
 # CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
+# CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
@@ -35,7 +38,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-CONFIG_MOL=y
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -105,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -141,6 +142,7 @@
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -151,8 +153,10 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
@@ -297,7 +301,7 @@
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=y
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY=15000
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
@@ -375,8 +379,10 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
 CONFIG_BMAC=y
 CONFIG_GMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -403,7 +409,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -424,6 +432,7 @@
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
 CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=y
@@ -491,6 +500,7 @@
 CONFIG_FB_IMSTT=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -543,6 +553,7 @@
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_ADBKEYCODES=y
 CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -611,6 +622,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -623,6 +636,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -679,6 +693,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
@@ -706,11 +721,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -718,11 +735,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
@@ -739,6 +757,8 @@
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -813,7 +833,6 @@
 # USB Serial Converter support
 #
 CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
@@ -821,6 +840,7 @@
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 # CONFIG_USB_SERIAL_KEYSPAN is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.4.4/linux/arch/ppc/kernel/Makefile	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/kernel/Makefile	Mon May 21 17:04:46 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.17 05/21/01 00:48:24 cort
+#
 #
 # Makefile for the linux kernel.
 #
@@ -7,12 +9,10 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
+USE_STANDARD_AS_RULE	:= true
+
 ifdef CONFIG_PPC64BRIDGE
-.S.o:
-	$(CC) $(CFLAGS) -D__ASSEMBLY__ -mppc64bridge -c $< -o $*.o
-else
-.S.o:
-	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
+EXTRA_AFLAGS		:= -Wa,-mppc64bridge
 endif
 
 ifeq ($(CONFIG_4xx),y)
@@ -31,7 +31,7 @@
 
 export-objs			:= ppc_ksyms.o prep_setup.o 
 
-obj-$(CONFIG_PPC)		:= entry.o traps.o irq.o idle.o time.o misc.o \
+obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o bitops.o ptrace.o \
 					ppc_htab.o semaphore.o syscalls.o  \
 					align.o setup.o
@@ -53,18 +53,25 @@
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.c
+ifndef CONFIG_MATH_EMULATION
+obj-y				+= softemu8xx.o
+endif
 else
-obj-$(CONFIG_PPC)		+= hashtable.o
+obj-y				+= hashtable.o
 endif
-obj-$(CONFIG_MATH_EMULATION)	+= softemu8xx.o
 obj-$(CONFIG_MBX)		+= i8259.o
 obj-$(CONFIG_APUS)		+= apus_setup.o
+ifeq ($(CONFIG_APUS),y)
+obj-$(CONFIG_PCI)		+= apus_pci.o
+endif
 obj-$(CONFIG_ALL_PPC)		+= pmac_pic.o pmac_setup.o pmac_time.o prom.o \
 					feature.o pmac_pci.o chrp_setup.o \
 					chrp_time.o chrp_pci.o 	open_pic.o \
 					indirect_pci.o i8259.o prep_pci.o \
 					prep_time.o prep_nvram.o prep_setup.o
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
+obj-$(CONFIG_GEMINI)		+= gemini_prom.o gemini_pci.o gemini_setup.o \
+					open_pic.o
 obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
 
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c
--- v2.4.4/linux/arch/ppc/kernel/align.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/align.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.align.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  * align.c - handle alignment exceptions for the Power PC.
  *
  * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/apus_pci.c linux/arch/ppc/kernel/apus_pci.c
--- v2.4.4/linux/arch/ppc/kernel/apus_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/apus_pci.c	Mon May 21 17:04:46 2001
@@ -0,0 +1,189 @@
+/*
+ * BK Id: SCCS/s.apus_pci.c 1.3 05/17/01 18:14:21 cort
+ */
+/*
+ * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
+ *
+ * APUS PCI routines.
+ *
+ * Currently, only B/CVisionPPC cards (Permedia2) are supported.
+ *
+ * Thanks to Geert Uytterhoeven for the idea:
+ * Read values from given config space(s) for the first devices, -1 otherwise
+ *
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_AMIGA
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+#include <asm/init.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "apus_pci.h"
+
+
+/* These definitions are mostly adapted from pm2fb.c */
+
+#undef APUS_PCI_MASTER_DEBUG
+#ifdef APUS_PCI_MASTER_DEBUG
+#define DPRINTK(a,b...)	printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif 
+
+/*
+ * The _DEFINITIVE_ memory mapping/unmapping functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define DEFW()		wmb()
+#define DEFR()		rmb()
+#define DEFRW()		mb()
+
+#define DEVNO(d)	((d)>>3)
+#define FNNO(d)		((d)&7)
+
+
+extern unsigned long powerup_PCI_present;
+
+static struct pci_controller *apus_hose;
+
+
+__apus
+void *pci_io_base(unsigned int bus)
+{
+	return 0;
+}
+
+
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((val), (type *)(addr)); DEFW()
+#define cfg_read_bad	*val = ~0;
+#define cfg_write_bad	;
+#define cfg_read_val(val)	*val
+#define cfg_write_val(val)	val
+
+#define APUS_PCI_OP(rw, size, type, op, mask)					\
+__apus int									\
+apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
+{										\
+	int fnno = FNNO(dev->devfn);						\
+	int devno = DEVNO(dev->devfn);						\
+										\
+	if (dev->bus->number > 0 || devno != 1) {				\
+		cfg_##rw##_bad;							\
+		return PCIBIOS_DEVICE_NOT_FOUND;				\
+	}									\
+	/* base address + function offset + offset ^ endianness conversion */	\
+	cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask),	\
+		 type, op);							\
+										\
+	DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n",		\
+		dev->bus->number, dev->devfn>>3, dev->devfn&7,			\
+		offset, cfg_##rw##_val(val));					\
+	return PCIBIOS_SUCCESSFUL;						\
+}
+
+APUS_PCI_OP(read, byte, u8 *, readb, 3)
+APUS_PCI_OP(read, word, u16 *, readw, 2)
+APUS_PCI_OP(read, dword, u32 *, readl, 0)
+APUS_PCI_OP(write, byte, u8, writeb, 3)
+APUS_PCI_OP(write, word, u16, writew, 2)
+APUS_PCI_OP(write, dword, u32, writel, 0)
+
+
+static struct pci_ops apus_pci_ops = {
+	apus_pcibios_read_config_byte,
+	apus_pcibios_read_config_word,
+	apus_pcibios_read_config_dword,
+	apus_pcibios_write_config_byte,
+	apus_pcibios_write_config_word,
+	apus_pcibios_write_config_dword
+};
+
+static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
+
+void __init
+apus_pcibios_fixup(void)
+{
+/*	struct pci_dev *dev = pci_find_slot(0, 1<<3);
+	unsigned int reg, val, offset;*/
+
+	/* FIXME: interrupt? */
+	/*dev->interrupt = xxx;*/
+
+        request_resource(&iomem_resource, &pci_mem);
+    	printk("%s: PCI mem resource requested\n", __FUNCTION__);
+}
+
+static void __init apus_pcibios_fixup_bus(struct pci_bus *bus)
+{
+        bus->resource[1] = &pci_mem;
+}
+
+
+/* 
+ * This is from pm2fb.c again
+ * 
+ * Check if PCI (B/CVisionPPC) is available, initialize it and set up
+ * the pcibios_* pointers
+ */
+
+
+void __init
+apus_setup_pci_ptrs(void)
+{
+	if (!powerup_PCI_present) {
+		DPRINTK("no PCI bridge detected\n");
+		return;
+	}
+	DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n");
+
+	apus_hose = pcibios_alloc_controller();
+	if (!apus_hose) {
+		printk("apus_pci: Can't allocate PCI controller structure\n");
+		return;
+	}
+
+	if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) {
+		printk("apus_pci: unable to map PCI config region\n");
+		return;
+	}
+
+	if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) {
+		printk("apus_pci: unable to map PCI bridge\n");
+		return;
+	}
+
+	writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN);
+	DEFW();
+
+	writel(CVPPC_REGS_REGION,  apus_hose->cfg_data+ PCI_BASE_ADDRESS_0);
+	DEFW();
+	writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1);
+	DEFW();
+	writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2);
+	DEFW();
+	writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS);
+	DEFW();
+
+	writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND);
+	DEFW();
+
+	apus_hose->first_busno = 0;
+	apus_hose->last_busno = 0;
+	apus_hose->ops = &apus_pci_ops;
+	ppc_md.pcibios_fixup = apus_pcibios_fixup;
+	ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus;
+
+	return;
+}
+
+#endif /* CONFIG_AMIGA */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/apus_pci.h linux/arch/ppc/kernel/apus_pci.h
--- v2.4.4/linux/arch/ppc/kernel/apus_pci.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/apus_pci.h	Mon May 21 17:04:46 2001
@@ -0,0 +1,40 @@
+/*
+ * BK Id: SCCS/s.apus_pci.h 1.4 05/17/01 18:14:21 cort
+ */
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef APUS_PCI_H
+#define APUS_PCI_H
+
+
+#include "pci.h"
+
+
+#define CSPPC_PCI_BRIDGE		0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN		0x0000
+#define CSPPC_BRIDGE_INT		0x0010
+
+#define	CVPPC_PCI_CONFIG		0xfffc0000
+#define CVPPC_ROM_ADDRESS		0xe2000001
+#define CVPPC_REGS_REGION		0xef000000
+#define CVPPC_FB_APERTURE_ONE		0xe0000000
+#define CVPPC_FB_APERTURE_TWO		0xe1000000
+#define CVPPC_FB_SIZE			0x00800000
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN	0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2	0x01
+
+
+#endif	/* APUS_PCI_H */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.4.4/linux/arch/ppc/kernel/apus_setup.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/apus_setup.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.apus_setup.c 1.11 05/17/01 18:14:21 cort
+ */
+/*
  *  linux/arch/ppc/kernel/apus_setup.c
  *
  *  Copyright (C) 1998, 1999  Jesper Skov
@@ -1017,6 +1020,59 @@
 	0
 };
 
+#define HARDWARE_MAPPED_SIZE (512*1024)
+unsigned long __init apus_find_end_of_memory(void)
+{
+	int shadow = 0;
+	unsigned long total;
+
+	/* The memory size reported by ADOS excludes the 512KB
+	   reserved for PPC exception registers and possibly 512KB
+	   containing a shadow of the ADOS ROM. */
+	{
+		unsigned long size = memory[0].size;
+
+		/* If 2MB aligned, size was probably user
+                   specified. We can't tell anything about shadowing
+                   in this case so skip shadow assignment. */
+		if (0 != (size & 0x1fffff)){
+			/* Align to 512KB to ensure correct handling
+			   of both memfile and system specified
+			   sizes. */
+			size = ((size+0x0007ffff) & 0xfff80000);
+			/* If memory is 1MB aligned, assume
+                           shadowing. */
+			shadow = !(size & 0x80000);
+		}
+
+		/* Add the chunk that ADOS does not see. by aligning
+                   the size to the nearest 2MB limit upwards.  */
+		memory[0].size = ((size+0x001fffff) & 0xffe00000);
+	}
+
+	total = memory[0].size;
+
+	/* Remove the memory chunks that are controlled by special
+           Phase5 hardware. */
+
+	/* Remove the upper 512KB if it contains a shadow of
+	   the ADOS ROM. FIXME: It might be possible to
+	   disable this shadow HW. Check the booter
+	   (ppc_boot.c) */
+	if (shadow)
+		total -= HARDWARE_MAPPED_SIZE;
+
+	/* Remove the upper 512KB where the PPC exception
+	   vectors are mapped. */
+	total -= HARDWARE_MAPPED_SIZE;
+
+	/* Linux/APUS only handles one block of memory -- the one on
+	   the PowerUP board. Other system memory is horrible slow in
+	   comparison. The user can use other memory for swapping
+	   using the z2ram device. */
+	ram_phys_base = memory[0].addr;
+	return total;
+}
 
 __init
 void apus_init_IRQ(void)
@@ -1037,10 +1093,6 @@
 
 	amiga_init_IRQ();
 
-	int_control.int_sti = __no_use_sti;
-	int_control.int_cli = __no_use_cli;
-	int_control.int_save_flags = __no_use_save_flags;
-	int_control.int_restore_flags = __no_use_restore_flags;
 }
 
 __init
@@ -1072,7 +1124,10 @@
 	ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
 	ppc_md.init_IRQ       = apus_init_IRQ;
 	ppc_md.get_irq        = apus_get_irq;
-	ppc_md.post_irq       = apus_post_irq;
+	
+#error Should use the ->end() member of irq_desc[x]. -- Cort
+	/*ppc_md.post_irq       = apus_post_irq;*/
+	
 #ifdef CONFIG_HEARTBEAT
 	ppc_md.heartbeat      = apus_heartbeat;
 	ppc_md.heartbeat_count = 1;
@@ -1091,6 +1146,8 @@
 	ppc_md.set_rtc_time   = apus_set_rtc_time;
 	ppc_md.get_rtc_time   = apus_get_rtc_time;
 	ppc_md.calibrate_decr = apus_calibrate_decr;
+
+	ppc_md.find_end_of_memory = apus_find_end_of_memory;
 
 	ppc_md.nvram_read_val = NULL;
 	ppc_md.nvram_write_val = NULL;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/bitops.c linux/arch/ppc/kernel/bitops.c
--- v2.4.4/linux/arch/ppc/kernel/bitops.c	Thu Jul 13 09:42:50 2000
+++ linux/arch/ppc/kernel/bitops.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.bitops.c 1.7 05/17/01 18:14:21 cort
+ */
+/*
  * Copyright (C) 1996 Paul Mackerras.
  */
 
@@ -16,10 +19,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 	
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%3
-	or	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%3 \n\
+	or	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=m" (*p)
@@ -33,10 +36,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%3
-	andc	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=m" (*p)
@@ -50,10 +53,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%3
-	xor	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%3 \n\
+	xor	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=m" (*p)
@@ -67,10 +70,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	or	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	or	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -86,10 +89,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	andc	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	andc	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -105,10 +108,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	xor	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	xor	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/checks.c linux/arch/ppc/kernel/checks.c
--- v2.4.4/linux/arch/ppc/kernel/checks.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/checks.c	Mon May 21 17:04:46 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.checks.c 1.6 05/17/01 18:14:21 cort
+ */
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.4.4/linux/arch/ppc/kernel/chrp_pci.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/kernel/chrp_pci.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.chrp_pci.c 1.16 05/17/01 18:14:21 cort
+ */
+/*
  * CHRP pci routines.
  */
 
@@ -264,6 +267,7 @@
 	}
 }
 
+#if 0
 static struct {
     /* parent is iomem */
     struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash;
@@ -297,62 +301,7 @@
 {
     	bus->resource[1] = &gg2_resources.pci_mem;
 }
-
-/* this is used by the pmac_pci code too... - paulus */
-void process_bridge_ranges(struct pci_controller *hose,
-			   struct device_node *dev, int primary)
-{
-	unsigned int *ranges;
-	int rlen = 0;
-	int memno = 0;
-	struct resource *res;
-
-	hose->io_base_phys = 0;
-	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
-	while ((rlen -= 6 * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		switch (ranges[0] >> 24) {
-		case 1:		/* I/O space */
-			if (ranges[2] != 0)
-				break;
-			hose->io_base_phys = ranges[3];
-			hose->io_base_virt = ioremap(ranges[3], ranges[5]);
-			if (primary)
-				isa_io_base = (unsigned long) hose->io_base_virt;
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = ranges[2];
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			if (ranges[1] == 0 && ranges[2] == 0
-			    && ranges[5] <= (16 << 20)) {
-				/* 1st 16MB, i.e. ISA memory area */
-				if (primary)
-					isa_mem_base = ranges[3];
-				memno = 1;
-			}
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-			if (memno == 0)
-				hose->pci_mem_offset = ranges[3] - ranges[2];
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				res->start = ranges[3];
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + ranges[5] - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-		ranges += 6;
-	}
-}
+#endif /* 0 */
 
 /* this is largely modeled and stolen after the pmac_pci code -- tgall
  */
@@ -366,8 +315,10 @@
 	volatile unsigned char *cfg;
 	unsigned int *dma;
 #ifdef CONFIG_POWER3
-	unsigned long *opprop = (unsigned long *)
-		get_property(find_path_device("/"), "platform-open-pic", NULL);
+	struct device_node *root = find_path_device("/");
+	unsigned int *opprop = (unsigned int *)
+		get_property(root, "platform-open-pic", NULL);
+	int i;
 #endif
 
 	for(; dev != NULL; dev = dev->next, ++index) {
@@ -405,10 +356,11 @@
        		hose->cfg_addr = (volatile unsigned int *) cfg;
        		hose->cfg_data = cfg + 0x10;
 
-		process_bridge_ranges(hose, dev, index == 0);
+		pci_process_bridge_OF_ranges(hose, dev, index == 0);
 
 #ifdef CONFIG_POWER3
-                openpic_setup_ISU(index, opprop[index+1]);
+		i = prom_n_addr_cells(root) * (index + 2) - 1;
+                openpic_setup_ISU(index, opprop[i]);
 #endif /* CONFIG_POWER3 */
 
 		/* check the first bridge for a property that we can
@@ -442,7 +394,7 @@
 void __init
 chrp_find_bridges(void)
 {
-	struct device_node *py;
+	struct device_node *py, *dev;
 	char *model, *name;
 	struct pci_controller* hose;
 
@@ -453,7 +405,7 @@
 #else /* CONFIG_POWER4 */
 	model = get_property(find_path_device("/"), "model", NULL);
         if (!strncmp("MOT", model, 3)) {
-		struct pci_controller* hose;
+		struct pci_controller *hose;
 
 		hose = pcibios_alloc_controller();
 		if (!hose)
@@ -463,8 +415,9 @@
         	/* Check that please. This must be the root of the OF
         	 * PCI tree (the root host bridge
         	 */
-               	hose->arch_data = find_devices("pci");
+               	hose->arch_data = dev = find_devices("pci");
                 setup_grackle(hose, 0x20000);
+		pci_process_bridge_OF_ranges(hose, dev, 1);
 		return;
         }
 
@@ -485,25 +438,22 @@
 	/* Check that please. This must be the root of the OF
 	 * PCI tree (the root host bridge
 	 */
-	hose->arch_data = find_devices("pci");
+	hose->arch_data = dev = find_devices("pci");
 	name = get_property(find_path_device("/"), "name", NULL);
 	if (!strncmp("IBM,7043-150", name, 12) ||
 	    !strncmp("IBM,7046-155", name, 12) ||
 	    !strncmp("IBM,7046-B50", name, 12) ) {
 		setup_grackle(hose, 0x01000000);
-		isa_mem_base = 0x80000000;
+		pci_process_bridge_OF_ranges(hose, dev, 1);
 		return;
 	}
 
 	/* LongTrail */
 	hose->ops = &gg2_pci_ops;
 	pci_dram_offset = 0;
-	isa_mem_base = 0xf7000000;
-	hose->io_base_phys = (unsigned long) 0xf8000000;
-	hose->io_base_virt = ioremap(hose->io_base_phys, 0x10000);
-	isa_io_base = (unsigned long) hose->io_base_virt;
-	ppc_md.pcibios_fixup = gg2_pcibios_fixup;
-	ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
+	pci_process_bridge_OF_ranges(hose, find_devices("pci"), 1);
+//	ppc_md.pcibios_fixup = gg2_pcibios_fixup;
+//	ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
 #endif /* CONFIG_POWER4 */
 }
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.4.4/linux/arch/ppc/kernel/chrp_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.chrp_setup.c 1.17 05/17/01 18:14:21 cort
+ */
+/*
  *  linux/arch/ppc/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
@@ -67,6 +70,7 @@
 void rtas_indicator_progress(char *, unsigned short);
 void bootx_text_progress(char *, unsigned short);
 
+extern unsigned long pmac_find_end_of_memory(void);
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
@@ -194,37 +198,36 @@
 				     u8 type)
 {
 	u8 level0, type0, active;
-	struct device_node *root;
-	
-	root = find_path_device("/");
-	if (root &&
-	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13 ) )
-	{
-		/* select logical device */
-		sio_write(device, 0x07);
-		active = sio_read(0x30);
-		level0 = sio_read(0x70);
-		type0 = sio_read(0x71);
-		printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
-		       !active ? "in" : "");
-		if (level0 == level && type0 == type && active)
-			printk("OK\n");
-		else {
-			printk("remapping to level %d, type %d, active\n", level, type);
-			sio_write(0x01, 0x30);
-			sio_write(level, 0x70);
-			sio_write(type, 0x71);
-		}
-	}
 
+	/* select logical device */
+	sio_write(device, 0x07);
+	active = sio_read(0x30);
+	level0 = sio_read(0x70);
+	type0 = sio_read(0x71);
+	printk("sio: %s irq level %d, type %d, %sactive: ", name, level0,
+	       type0, !active ? "in" : "");
+	if (level0 == level && type0 == type && active)
+		printk("OK\n");
+	else {
+		printk("remapping to level %d, type %d, active\n", level,
+		       type);
+		sio_write(0x01, 0x30);
+		sio_write(level, 0x70);
+		sio_write(type, 0x71);
+	}
 }
 
 static void __init sio_init(void)
 {
-	/* logical device 0 (KBC/Keyboard) */
-	sio_fixup_irq("keyboard", 0, 1, 2);
-	/* select logical device 1 (KBC/Mouse) */
-	sio_fixup_irq("mouse", 1, 12, 2);
+	struct device_node *root;
+
+	if ((root = find_path_device("/")) &&
+	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+		/* logical device 0 (KBC/Keyboard) */
+		sio_fixup_irq("keyboard", 0, 1, 2);
+		/* select logical device 1 (KBC/Mouse) */
+		sio_fixup_irq("mouse", 1, 12, 2);
+	}
 }
 
 
@@ -263,16 +266,19 @@
 
 #ifndef CONFIG_POWER4
 	/* Some IBM machines don't have the hydra -- Cort */
-	if ( !OpenPIC_Addr )
-	{
+	if (!OpenPIC_Addr) {
+		struct device_node *root;
 		unsigned long *opprop;
+		int n;
 
-		opprop = (unsigned long *)get_property(find_path_device("/"),
-						"platform-open-pic", NULL);
+		root = find_path_device("/");
+		opprop = (unsigned long *) get_property
+			(root, "platform-open-pic", NULL);
+		n = prom_n_addr_cells(root);
 		if (opprop != 0) {
 			printk("OpenPIC addrs: %lx %lx %lx\n",
-			       opprop[0], opprop[1], opprop[2]);
-			OpenPIC_Addr = ioremap(opprop[0], 0x40000);
+			       opprop[n-1], opprop[2*n-1], opprop[3*n-1]);
+			OpenPIC_Addr = ioremap(opprop[n-1], 0x40000);
 		}
 	}
 #endif
@@ -281,6 +287,10 @@
 	 *  Fix the Super I/O configuration
 	 */
 	sio_init();
+
+	/*
+	 *  Setup the console operations
+	 */
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
@@ -356,7 +366,7 @@
 {
 	struct device_node *np;
 	int i;
-	unsigned long *addrp;
+	unsigned int *addrp;
 	unsigned char* chrp_int_ack_special = 0;
 	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
 	int nmi_irq = -1;
@@ -365,11 +375,12 @@
 #endif
 
 	if (!(np = find_devices("pci"))
-	    || !(addrp = (unsigned long *)
+	    || !(addrp = (unsigned int *)
 		 get_property(np, "8259-interrupt-acknowledge", NULL)))
 		printk("Cannot find pci to get ack address\n");
 	else
-		chrp_int_ack_special = (unsigned char *)ioremap(*addrp, 1);
+		chrp_int_ack_special = (unsigned char *)
+			ioremap(addrp[prom_n_addr_cells(np)-1], 1);
 	/* hydra still sets OpenPIC_InitSenses to a static set of values */
 	if (OpenPIC_InitSenses == NULL) {
 		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
@@ -553,11 +564,9 @@
 #ifndef CONFIG_POWER4
 	ppc_md.init_IRQ       = chrp_init_IRQ;
 	ppc_md.get_irq        = openpic_get_irq;
-	ppc_md.post_irq	      = NULL;
 #else
 	ppc_md.init_IRQ	      = xics_init_IRQ;
 	ppc_md.get_irq	      = xics_get_irq;
-	ppc_md.post_irq	      = NULL;
 #endif /* CONFIG_POWER4 */
 
 	ppc_md.init           = chrp_init2;
@@ -570,6 +579,8 @@
 	ppc_md.set_rtc_time   = chrp_set_rtc_time;
 	ppc_md.get_rtc_time   = chrp_get_rtc_time;
 	ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
 
 #ifdef CONFIG_VT
 	/* these are adjusted in chrp_init2 if we have an ADB keyboard */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- v2.4.4/linux/arch/ppc/kernel/chrp_time.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/chrp_time.c	Mon May 21 17:04:46 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.chrp_time.c 1.7 05/17/01 18:14:21 cort
+ */
+/*
  *  linux/arch/i386/kernel/time.c
  *
  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
@@ -29,6 +32,8 @@
 #include <asm/init.h>
 #include <asm/time.h>
 
+extern spinlock_t rtc_lock;
+
 static int nvram_as1 = NVRAM_AS1;
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
@@ -74,6 +79,7 @@
 	unsigned char save_control, save_freq_select;
 	struct rtc_time tm;
 
+	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
 
 	save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
@@ -112,6 +118,7 @@
 
 	if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
 		time_state = TIME_OK;
+	spin_unlock(&rtc_lock);
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.4.4/linux/arch/ppc/kernel/entry.S	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/entry.S	Mon May 21 17:04:46 2001
@@ -1,8 +1,7 @@
 /*
- *  arch/ppc/kernel/entry.S
- *
- *  $Id: entry.S,v 1.4 1999/09/14 05:18:14 dmalek Exp $
- *
+ * BK Id: SCCS/s.entry.S 1.12 05/21/01 11:49:59 paulus
+ */
+/*
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
@@ -30,7 +29,6 @@
 #include <linux/errno.h>
 #include <linux/sys.h>
 #include <linux/config.h>
-#include "mol.h"
 
 #undef SHOW_SYSCALLS
 #undef SHOW_SYSCALLS_TASK
@@ -315,21 +313,12 @@
 	lwz	r5,_MSR(r1)
 	andi.	r5,r5,MSR_EE
 	beq	2f
-	.globl	lost_irq_ret
-lost_irq_ret:
-3:	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
-	cmpi	0,r4,0
-	beq+	1f
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	do_IRQ
-	b	3b
-1:	lis	r4,irq_stat@ha		/* &softirq_active for cpu 0 */
+	lis	r4,irq_stat@ha		/* &softirq_active for cpu 0 */
 	addi	r4,r4,irq_stat@l
 #ifdef CONFIG_SMP
 	/* get processor # */
 	lwz	r3,PROCESSOR(r2)
-	slwi	r3,r3,5
+	slwi	r3,r3,LG_CACHE_LINE_SIZE
 	add	r4,r4,r3
 #endif /* CONFIG_SMP */
 	lwz	r5,0(r4)		/* softirq_active */
@@ -351,7 +340,6 @@
 	beq+	do_signal_ret
 	li	r3,0
 	addi	r4,r1,STACK_FRAME_OVERHEAD
-	MOL_HOOK_MMU(8,r8)
 	bl	do_signal
 	.globl	do_signal_ret
 do_signal_ret:
@@ -373,7 +361,9 @@
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
 	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
-	
+
+	stwcx.	r0,0,r1		/* to clear the reservation */
+
 	/* if returning to user mode, set new sprg2 and save kernel SP */
 	lwz	r0,_MSR(r1)
 	andi.	r0,r0,MSR_PR
@@ -391,7 +381,6 @@
 	stw	r0,THREAD+KSP(r2)	/* save kernel stack pointer */
 	tophys(r8,r1)
 	CLR_TOP32(r8)
-	MOL_HOOK_MMU(9, r4)		/* mod. r0,r2-r7, lr, ctr */
 	mtspr	SPRG2,r8		/* phys exception stack pointer */	
 1:
 	lwz	r3,_CTR(r1)
@@ -412,29 +401,6 @@
 	lwz	r1,GPR1(r1)
 	SYNC
 	RFI
-
-/*
- * Fake an interrupt from kernel mode.
- * This is used when enable_irq loses an interrupt.
- * We only fill in the stack frame minimally.
- */
-_GLOBAL(fake_interrupt)
-	mflr	r0
-	stw	r0,4(r1)
-	stwu	r1,-INT_FRAME_SIZE(r1)
-	stw	r0,_NIP(r1)
-	stw	r0,_LINK(r1)
-	mfmsr	r3
-	stw	r3,_MSR(r1)
-	li	r0,0x0fac
-	stw	r0,TRAP(r1)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r4,1
-	bl	do_IRQ
-	addi	r1,r1,INT_FRAME_SIZE
-	lwz	r0,4(r1)
-	mtlr	r0
-	blr
 
 
 /*
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/error_log.c linux/arch/ppc/kernel/error_log.c
--- v2.4.4/linux/arch/ppc/kernel/error_log.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/error_log.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.error_log.c 1.6 05/17/01 18:14:21 cort
+ */
+/*
  *  arch/ppc/kernel/error_log.c
  *  
  *  Copyright (c) 2000 Tilmann Bitterberg
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/error_log.h linux/arch/ppc/kernel/error_log.h
--- v2.4.4/linux/arch/ppc/kernel/error_log.h	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/error_log.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.error_log.h 1.5 05/17/01 18:14:21 cort
+ */
 #ifndef __ERROR_LOG_H__
 #define __ERROR_LOG_H__
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
--- v2.4.4/linux/arch/ppc/kernel/feature.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/feature.c	Mon May 21 17:04:47 2001
@@ -1,18 +1,17 @@
 /*
+ * BK Id: SCCS/s.feature.c 1.10 05/17/01 18:14:21 cort
+ */
+/*
  *  arch/ppc/kernel/feature.c
  *
  *  Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *                     Ben. Herrenschmidt (bh40@calva.net)
+ *                     Ben. Herrenschmidt (benh@kernel.crashing.org)
  *
  *  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.
  *
- *  BenH: Changed implementation to work on multiple registers
- * 	  polarity is also taken into account. Removed delay (now
- * 	  responsibility of the caller). Added spinlocks.
- *
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -29,11 +28,12 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/feature.h>
+#include <asm/dbdma.h>
+#include <asm/machdep.h>
 
 #undef DEBUG_FEATURE
 
 #define MAX_FEATURE_CONTROLLERS		2
-#define MAX_FEATURE_OFFSET		0x100
 #define FREG(c,r)			(&(((c)->reg)[(r)>>2]))
 
 /* Keylargo reg. access. */
@@ -56,9 +56,7 @@
 	unsigned int	mask;		/* bit mask */
 } fbit;
 
-/* I don't have an OHare machine to test with, so I left those as they
- * were. Someone with such a machine chould check out what OF says and
- * try too see if they match the heathrow ones and should be changed too
+/* Those features concern for OHare-based PowerBooks (2400, 3400, 3500)
  */
 static fbit feature_bits_ohare_pbook[] = {
 	{0x38,0,0},			/* FEATURE_null */
@@ -159,11 +157,12 @@
 
 /*
  * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
- * Mostly the same as the heathrow.
+ * Mostly the same as the heathrow. They are used on both PowerBooks
+ * and desktop machines using the paddington chip
  */
 static fbit feature_bits_paddington[] = {
 	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,0},			/* FEATURE_Serial_reset */
+	{0x38,0,PADD_RESET_SCC},	/* FEATURE_Serial_reset */
 	{0x38,0,HRW_SCC_ENABLE},	/* FEATURE_Serial_enable */
 	{0x38,0,HRW_SCCA_IO},		/* FEATURE_Serial_IO_A */
 	{0x38,0,HRW_SCCB_IO},		/* FEATURE_Serial_IO_B */
@@ -192,6 +191,7 @@
 };
 
 /* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
+ * Note: Different sets may be needed for iBook, especially for sound
  */
 static fbit feature_bits_keylargo[] = {
 	{0x38,0,0},			/* FEATURE_null */
@@ -201,13 +201,13 @@
 	{0x38,0,KL0_SCC_B_INTF_ENABLE},	/* FEATURE_Serial_IO_B */
 	{0x38,0,0},			/* FEATURE_SWIM3_enable */
 	{0x38,0,0},			/* FEATURE_MESH_enable */
-	{0x3c,0,0},			/* FEATURE_IDE0_enable */
+	{0x3c,0,KL1_EIDE0_ENABLE},	/* FEATURE_IDE0_enable */
  	{0x3c,1,KL1_EIDE0_RESET_N},	/* FEATURE_IDE0_reset */
 	{0x38,0,0},			/* FEATURE_IOBUS_enable */
-	{0x34,1,0x00000200},		/* FEATURE_Mediabay_reset */
-	{0x34,1,0x00000400},		/* FEATURE_Mediabay_power */
+	{0x34,1,KL_MBCR_MB0_DEV_RESET},	/* FEATURE_Mediabay_reset */
+	{0x34,1,KL_MBCR_MB0_DEV_POWER},	/* FEATURE_Mediabay_power */
 	{0x38,0,0},			/* FEATURE_Mediabay_PCI_enable */
-	{0x3c,0,0x0},			/* FEATURE_IDE1_enable */
+	{0x3c,0,KL1_EIDE1_ENABLE},	/* FEATURE_IDE1_enable */
 	{0x3c,1,KL1_EIDE1_RESET_N},	/* FEATURE_IDE1_reset */
 	{0x38,0,0},			/* FEATURE_Mediabay_floppy_enable */
 	{0x38,0,0},			/* FEATURE_BMac_reset */
@@ -216,10 +216,10 @@
 	{0x38,0,0},			/* FEATURE_Slow_SCC_PCLK */
 	{0x38,0,0},			/* FEATURE_Sound_Power */
 	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
-	{0x38,0,0},			/* FEATURE_IDE2_enable */
+	{0x3c,0,KL1_UIDE_ENABLE},	/* FEATURE_IDE2_enable */
 	{0x3c,1,KL1_UIDE_RESET_N},	/* FEATURE_IDE2_reset */
-	{0x34,0,KL_MBCR_MBDEV_ENABLE},	/* FEATURE_Mediabay_IDE_switch */
-	{0x34,0,0x00000100},		/* FEATURE_Mediabay_content */
+	{0x34,0,KL_MBCR_MB0_DEV_ENABLE},/* FEATURE_Mediabay_IDE_switch */
+	{0x34,0,KL_MBCR_MB0_ENABLE},	/* FEATURE_Mediabay_content */
 	{0x40,1,KL2_AIRPORT_RESET_N},	/* FEATURE_Airport_reset */
 };
 
@@ -238,6 +238,8 @@
 static struct feature_controller*
 feature_lookup_controller(struct device_node *device);
 
+static void uninorth_init(void);
+static void keylargo_init(void);
 #ifdef CONFIG_PMAC_PBOOK
 static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
 static void heathrow_wakeup(struct feature_controller* ctrler);
@@ -245,32 +247,80 @@
 static void core99_wake_up(struct feature_controller* ctrler);
 #endif /* CONFIG_PMAC_PBOOK */
 
-static void keylargo_init(void);
-static void uninorth_init(void);
-
 /* static variables */
 static struct feature_controller	controllers[MAX_FEATURE_CONTROLLERS];
 static int				controller_count = 0;
 
 /* Core99 stuffs */
-static volatile u32*			uninorth_base = NULL;
-static volatile u32*			keylargo_base = NULL;
+/*static*/ volatile u32*		uninorth_base;
+static volatile u32*			keylargo_base;
+static struct feature_controller*	keylargo;
 static int				uninorth_rev;
 static int				keylargo_rev;
+static u32				board_features;
+static u8				airport_pwr_regs[5];
+static int				airport_pwr_state;
+static struct device_node*		airport_dev;
+
+#define FTR_NEED_OPENPIC_TWEAK		0x00000001
+#define FTR_CAN_NAP			0x00000002
+#define FTR_HAS_FW_POWER		0x00000004
+#define FTR_CAN_SLEEP			0x00000008
+
+static struct board_features_t {
+	char*	compatible;
+	u32	features;
+} board_features_datas[] __init = 
+{
+  {	"AAPL,PowerMac G3",	0				}, /* Beige G3 */
+  {	"iMac,1",		0				}, /* First iMac (gossamer) */
+  {	"PowerMac1,1",		0				}, /* B&W G3 / Yikes */
+  {	"PowerMac1,2",		0				}, /* B&W G3 / Yikes */
+  {	"PowerMac2,1",		FTR_CAN_SLEEP			}, /* r128 based iMac */
+  {	"PowerMac2,2",		FTR_HAS_FW_POWER|FTR_CAN_SLEEP	}, /* Summer 2000 iMac */
+  {	"PowerMac4,1",		FTR_CAN_SLEEP			}, /* iMac "Flower Power" */
+  {	"PowerMac3,1",		FTR_NEED_OPENPIC_TWEAK		}, /* Sawtooth (G4) */
+  {	"PowerMac3,2",		0				}, /* G4/Dual G4 */
+  {	"PowerMac3,3",		FTR_NEED_OPENPIC_TWEAK		}, /* G4/Dual G4 */
+  {	"PowerMac5,1",		0				}, /* Cube */
+  {	"AAPL,3400/2400",	FTR_CAN_SLEEP			}, /* 2400/3400 PowerBook */
+  {	"AAPL,3500",		FTR_CAN_SLEEP			}, /* 3500 PowerBook (G3) */
+  {	"AAPL,PowerBook1998",	FTR_CAN_SLEEP			}, /* Wallstreet PowerBook */
+  {	"PowerBook1,1",		FTR_CAN_SLEEP			}, /* 101 (Lombard) PowerBook */
+  {	"PowerBook2,1",		FTR_CAN_SLEEP 			}, /* iBook */
+  {	"PowerBook2,2",		FTR_CAN_SLEEP /*| FTR_CAN_NAP*/	}, /* iBook FireWire */
+  {	"PowerBook3,1",		FTR_CAN_SLEEP|FTR_CAN_NAP|	   /* PowerBook 2000 (Pismo) */
+  				FTR_HAS_FW_POWER		}, 
+  {	"PowerBook3,2",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* PowerBook Titanium */
+  {	"PowerBook4,1",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* New polycarbonate iBook */
+  {	NULL, 0 }
+};
+
+extern unsigned long powersave_nap;
 
-/*
- * WARNING ! This function is called early in setup_arch, neither the IO base
- * nor the udelay calibration have been done yet
- */
 void
 feature_init(void)
 {
 	struct device_node *np;
 	u32 *rev;
-	
+	int i;
+
 	if (_machine != _MACH_Pmac)
 		return;
 
+	/* Figure out motherboard type & options */
+	for(i=0;board_features_datas[i].compatible;i++) {
+		if (machine_is_compatible(board_features_datas[i].compatible)) {
+			board_features = board_features_datas[i].features;
+			break;
+		}
+	}
+
+	/* Set default value of powersave_nap on machines that support it */
+	if (board_features & FTR_CAN_NAP)
+		powersave_nap = 1;
+		
+	/* Track those poor mac-io's */
 	np = find_devices("mac-io");
 	while (np != NULL) {
 		/* KeyLargo contains several (5 ?) FCR registers in mac-io,
@@ -280,13 +330,25 @@
 			struct feature_controller* ctrler =
 				feature_add_controller(np, feature_bits_keylargo);
 			if (ctrler) {
+				keylargo = ctrler;
 				keylargo_base = ctrler->reg;
 				rev = (u32 *)get_property(ctrler->device, "revision-id", NULL);
 				if (rev)
 					keylargo_rev = *rev;
+				
+				rev = (u32 *)get_property(ctrler->device, "device-id", NULL);
+				if (rev && (*rev) == 0x0025)
+					keylargo_rev |= KL_PANGEA_REV;
 			}
 		} else if (device_is_compatible(np, "paddington")) {
 			feature_add_controller(np, feature_bits_paddington);
+			/* We disable the modem power bit on Yikes as it can
+			 * do bad things (it's the nvram power)
+			 */
+			if (machine_is_compatible("PowerMac1,1") ||
+				machine_is_compatible("PowerMac1,2")) {
+				feature_bits_paddington[FEATURE_Modem_power].mask = 0;
+			}
 		} else if (machine_is_compatible("AAPL,PowerBook1998")) {
 			feature_add_controller(np, feature_bits_wallstreet);
 		} else {
@@ -311,11 +373,12 @@
 		}
 	}
 
-	/* Handle core99 Uni-N */
+	/* Locate core99 Uni-N */
 	np = find_devices("uni-n");
 	if (np && np->n_addrs > 0) {
 		uninorth_base = ioremap(np->addrs[0].address, 0x1000);
 		uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+		printk("Uninorth at 0x%08x\n", np->addrs[0].address);
 	}
 	if (uninorth_base && keylargo_base)
 		printk("Uni-N revision: %d, KeyLargo revision: %d\n",
@@ -360,8 +423,12 @@
 		return NULL;
 	}
 
+	/* We remap the entire mac-io here. Normally, this will just
+	 * give us back our already existing BAT mapping
+	 */
 	controller->reg		= (volatile u32 *)ioremap(
-		controller_device->addrs[0].address, MAX_FEATURE_OFFSET);
+		controller_device->addrs[0].address,
+		controller_device->addrs[0].size);
 
 	if (bits == NULL) {
 		printk(KERN_INFO "Twiddling the magic ohare bits\n");
@@ -495,6 +562,12 @@
 	return bit->polarity ? (value == 0) : (value == bit->mask);
 }
 
+int
+feature_can_sleep(void)
+{
+	return ((board_features & FTR_CAN_SLEEP) != 0);	
+}
+
 /*
  * Core99 functions
  * 
@@ -506,53 +579,220 @@
 void
 feature_set_gmac_power(struct device_node* device, int power)
 {
-	if (!uninorth_base)
+	unsigned long flags;
+	
+	if (!uninorth_base || !keylargo)
 		return;
+		
+	/* TODO: Handle save/restore of PCI config space here
+	 */
+
+	spin_lock_irqsave(&keylargo->lock, flags);
 	if (power)
 		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
 	else
 		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+	spin_unlock_irqrestore(&keylargo->lock, flags);
 	udelay(20);
 }
 
 void
-feature_set_gmac_phy_reset(struct device_node* device, int reset)
+feature_gmac_phy_reset(struct device_node* device)
 {
-	if (!keylargo_base)
+	unsigned long flags;
+	
+	if (!keylargo_base || !keylargo)
 		return;
-	out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), reset);
+		
+	spin_lock_irqsave(&keylargo->lock, flags);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET),
+		KEYLARGO_GPIO_OUTPUT_ENABLE);
 	(void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET));
+	spin_unlock_irqrestore(&keylargo->lock, flags);
+	mdelay(10);
+	spin_lock_irqsave(&keylargo->lock, flags);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET),
+		KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+	(void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET));
+	spin_unlock_irqrestore(&keylargo->lock, flags);
+	mdelay(10);
 }
 
 /* Pass the node of the correct controller, please */
 void
 feature_set_usb_power(struct device_node* device, int power)
 {
+	char* prop;
+	int number;
+	u32 reg;
+	
+	unsigned long flags;
+	
+	if (!keylargo_base || !keylargo)
+		return;
+		
+	prop = (char *)get_property(device, "AAPL,clock-id", NULL);
+	if (!prop)
+		return;
+	if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
+		number = 0;
+	else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
+		number = 2;
+	else
+		return;
+
+	spin_lock_irqsave(&keylargo->lock, flags);
+	if (power) {
+		/* Turn ON */
+			
+		if (number == 0) {
+			KL_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			mdelay(1);
+			KL_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+		} else {
+			KL_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			mdelay(1);
+			KL_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+		}
+		reg = KL_IN(KEYLARGO_FCR4);
+		reg &=	~(KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
+			KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number));
+		reg &=	~(KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
+			KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1));
+		KL_OUT(KEYLARGO_FCR4, reg);
+		(void)KL_IN(KEYLARGO_FCR4);
+		udelay(10);
+	} else {
+		/* Turn OFF */
+		
+		reg = KL_IN(KEYLARGO_FCR4);
+		reg |=	KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
+			KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number);
+		reg |=	KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
+			KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1);
+		KL_OUT(KEYLARGO_FCR4, reg);
+		(void)KL_IN(KEYLARGO_FCR4);
+		udelay(1);
+		if (number == 0) {
+			KL_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+			(void)KL_IN(KEYLARGO_FCR0);
+			udelay(1);
+			KL_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			(void)KL_IN(KEYLARGO_FCR0);
+		} else {
+			KL_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+			(void)KL_IN(KEYLARGO_FCR0);
+			udelay(1);
+			KL_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			(void)KL_IN(KEYLARGO_FCR0);
+		}
+		udelay(1);
+	}
+	spin_unlock_irqrestore(&keylargo->lock, flags);
 }
 
-/* Not yet implemented */
 void 
 feature_set_firewire_power(struct device_node* device, int power)
 {
+	unsigned long flags;
+
+	/* TODO: Handle save/restore of PCI config space here
+	 */
+		
 	if (!uninorth_base)
 		return;
+	spin_lock_irqsave(&keylargo->lock, flags);
 	if (power)
 		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
 	else
 		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
 	udelay(20);
+	spin_unlock_irqrestore(&keylargo->lock, flags);
+}
+
+/* Warning: will kill the PHY.. */
+void 
+feature_set_firewire_cable_power(struct device_node* device, int power)
+{
+	unsigned long flags;
+	u8 gpioValue = power ? 0 : 4;
+	
+	if (!keylargo_base || !(board_features & FTR_HAS_FW_POWER))
+		return;
+	spin_lock_irqsave(&keylargo->lock, flags);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER), gpioValue);
+	(void)in_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER));
+	spin_unlock_irqrestore(&keylargo->lock, flags);		
 }
 
 #ifdef CONFIG_SMP
 void
-feature_core99_kick_cpu1(void)
+feature_core99_kick_cpu(int cpu_nr)
 {
-	out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_UP);
+#if 1 /* New way */
+	const int reset_lines[] = {	KL_GPIO_RESET_CPU0,
+					KL_GPIO_RESET_CPU1,
+					KL_GPIO_RESET_CPU2,
+					KL_GPIO_RESET_CPU3 };
+	volatile u8* reset_io;
+
+	if (!keylargo_base || cpu_nr > 3)
+		return;
+	reset_io = (volatile u8*)KL_FCR(reset_lines[cpu_nr]);
+	out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+	udelay(1);
+	out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+#else
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_ASSERT);
 	udelay(1);
-	out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_DOWN);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_RELEASE);
+#endif	
 }
 #endif /* CONFIG_SMP */
 
+void
+feature_set_airport_power(struct device_node* device, int power)
+{
+	if (!keylargo_base || !airport_dev || airport_dev != device)
+		return;
+	if (airport_pwr_state == power)
+		return;
+	if (power) {
+		/* Some if this is from Darwin code, some is from tracing of
+		 * MacOS driver with Macsbug. Some real bit definitions would
+		 * really help here...
+		 */
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), airport_pwr_regs[0]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), airport_pwr_regs[1]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), airport_pwr_regs[2]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), airport_pwr_regs[3]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), airport_pwr_regs[4]);
+		udelay(20);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 5);
+		udelay(20);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 4);
+		mdelay(20);
+		KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
+		udelay(10);
+		out_8((volatile u8*)KL_FCR(0x1a3e0), 0x41);
+		udelay(10);
+		KL_BIS(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
+		udelay(10);
+	} else {
+		airport_pwr_regs[0] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0));
+		airport_pwr_regs[1] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1));
+		airport_pwr_regs[2] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2));
+		airport_pwr_regs[3] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3));
+		airport_pwr_regs[4] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4));
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 0);
+	}
+	airport_pwr_state = power;	
+}
+
 /* Initialize the Core99 UniNorth host bridge and memory controller
  */
 static void
@@ -563,51 +803,106 @@
 	
 	/* Set the arbitrer QAck delay according to what Apple does
 	 */
-	actrl = in_be32(UN_REG(UNI_N_ARB_CTRL)) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
-	actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : UNI_N_ARB_CTRL_QACK_DELAY)
-		<< UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
-	UN_OUT(UNI_N_ARB_CTRL, actrl);
+	if (uninorth_rev < 0x10) {
+		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
+			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+		UN_OUT(UNI_N_ARB_CTRL, actrl);
+	}
 	
-	/* 
-	 * Turns OFF the gmac clock. The gmac driver will turn
-	 * it back ON when the interface is enabled. This save
-	 * power on portables.
-	 * 
-	 * Note: We could also try to turn OFF the PHY. Since this
-	 * has to be done by both the gmac driver and this code,
-	 * I'll probably end-up moving some of this out of the
-	 * modular gmac driver into a non-modular stub containing
-	 * some basic PHY management and power management stuffs
+	/* Enable GMAC for now for PCI probing. It will be disabled
+	 * later on after PCI probe
 	 */
 	gmac = find_devices("ethernet");
-
 	while(gmac) {
 		if (device_is_compatible(gmac, "gmac"))
 			break;
 		gmac = gmac->next;
 	}
 	if (gmac)
-		feature_set_gmac_power(gmac, 0);
+		feature_set_gmac_power(gmac, 1);
 
-	/* Kludge (enable FW before PCI probe) */
+	/* Enable FW before PCI probe. Will be disabled later on
+	 */
 	fw = find_devices("firewire");
 	if (fw && device_is_compatible(fw, "pci106b,18"))
 		feature_set_firewire_power(fw, 1);
 }
 
-/* Initialize the Core99 KeyLargo ASIC. Currently, we just make sure
- * OpenPIC is enabled
+/* Initialize the Core99 KeyLargo ASIC. 
  */
 static void
 keylargo_init(void)
 {
+	struct device_node* np;
+	
 	KL_BIS(KEYLARGO_FCR2, KL2_MPIC_ENABLE);
+
+	/* Lookup for an airport card, and disable it if found
+	 * to save power (will be re-enabled by driver if used)
+	 */
+	np = find_devices("radio");
+	if (np && np->parent == keylargo->device)
+		airport_dev = np;
+
+	if (airport_dev) {
+		airport_pwr_state = 1;
+		feature_set_airport_power(airport_dev, 0);
+	}
+	
 }
 
 #ifdef CONFIG_PMAC_PBOOK
+void
+feature_prepare_for_sleep(void)
+{
+	/* We assume gatwick is second */
+	struct feature_controller* ctrler = &controllers[0];
+
+	if (controller_count > 1 &&
+		device_is_compatible(ctrler->device, "gatwick"))
+		ctrler = &controllers[1];
+
+	if (ctrler->bits == feature_bits_heathrow ||
+		ctrler->bits == feature_bits_paddington) {
+		heathrow_prepare_for_sleep(ctrler);
+		return;
+	}
+	if (ctrler->bits == feature_bits_keylargo) {
+		core99_prepare_for_sleep(ctrler);
+		return;
+	}
+}
+
+
+void
+feature_wake_up(void)
+{
+	struct feature_controller* ctrler = &controllers[0];
+
+	if (controller_count > 1 &&
+		device_is_compatible(ctrler->device, "gatwick"))
+		ctrler = &controllers[1];
+	
+	if (ctrler->bits == feature_bits_heathrow ||
+		ctrler->bits == feature_bits_paddington) {
+		heathrow_wakeup(ctrler);
+		return;
+	}
+	if (ctrler->bits == feature_bits_keylargo) {
+		core99_wake_up(ctrler);
+		return;
+	}
+}
 
 static u32 save_fcr[5];
 static u32 save_mbcr;
+static u32 save_gpio_levels[2];
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
+static u32 save_unin_clock_ctl;
+static struct dbdma_regs save_dbdma[13];
+
 
 static void
 heathrow_prepare_for_sleep(struct feature_controller* ctrler)
@@ -631,60 +926,226 @@
 }
 
 static void
-core99_prepare_for_sleep(struct feature_controller* ctrler)
+turn_off_keylargo(void)
 {
-	/* Not yet implemented */
+	u32 temp;
+
+	/* For now, suspending the USB ref cause the machine to die on
+	 * wakeup -- BenH
+	 */
+#if 0
+	mdelay(1);
+	KL_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
+	(void)KL_IN(KEYLARGO_FCR0);
+	mdelay(1500);
+#endif
+
+	KL_BIC(KEYLARGO_FCR0,	KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+		      		KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
+		      		KL0_IRDA_CLK19_ENABLE);
+
+	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
+	KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
+	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
+
+	KL_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
+		KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
+		KL1_UIDE_ENABLE);
+	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
+
+	KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
+ 	udelay(10);
+ 	KL_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
+ 	udelay(10);
+	temp = KL_IN(KEYLARGO_FCR3);
+	if (keylargo_rev >= 2)
+		temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
+		
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
+	temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	KL_OUT(KEYLARGO_FCR3, temp);
+	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
 }
 
 static void
-core99_wake_up(struct feature_controller* ctrler)
+turn_off_pangea(void)
 {
-	/* Not yet implemented */
+	u32 temp;
+
+	KL_BIC(KEYLARGO_FCR0,	KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+				KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
+
+	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
+	KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
+	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
+
+	KL_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_UIDE_ENABLE);
+	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
+
+	KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
+ 	udelay(10);
+	temp = KL_IN(KEYLARGO_FCR3);
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35;
+	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	KL_OUT(KEYLARGO_FCR3, temp);
+	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
 }
 
-void
-feature_prepare_for_sleep(void)
+static void
+core99_prepare_for_sleep(struct feature_controller* ctrler)
 {
-	/* We assume gatwick is second */
-	struct feature_controller* ctrler = &controllers[0];
+	int i;
+	u8* base8;
+	
+	/*
+	 * Save various bits of KeyLargo
+	 */
 
-	if (!ctrler)
-		return;
-	if (controller_count > 1 &&
-		device_is_compatible(ctrler->device, "gatwick"))
-		ctrler = &controllers[1];
+	/* We power off the wireless slot in case it was not done
+	 * by the driver. We don't power it on automatically however
+	 */
+	feature_set_airport_power(airport_dev, 0);
 
-	if (ctrler->bits == feature_bits_heathrow ||
-		ctrler->bits == feature_bits_paddington) {
-		heathrow_prepare_for_sleep(ctrler);
-		return;
+	/* We power off the FW cable. Should be done by the driver... */
+	feature_set_firewire_cable_power(NULL, 0);
+	 
+	/* Save the state of the various GPIOs */
+	save_gpio_levels[0] = KL_IN(KEYLARGO_GPIO_LEVELS0);
+	save_gpio_levels[1] = KL_IN(KEYLARGO_GPIO_LEVELS1);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_EXTINT_0);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		save_gpio_extint[i] = in_8(base8+i);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_0);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		save_gpio_normal[i] = in_8(base8+i);
+
+	/* Save the FCRs */
+	save_mbcr = KL_IN(KEYLARGO_MBCR);
+	save_fcr[0] = KL_IN(KEYLARGO_FCR0);
+	save_fcr[1] = KL_IN(KEYLARGO_FCR1);
+	save_fcr[2] = KL_IN(KEYLARGO_FCR2);
+	save_fcr[3] = KL_IN(KEYLARGO_FCR3);
+	save_fcr[4] = KL_IN(KEYLARGO_FCR4);
+
+	/* Save state & config of DBDMA channels */
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
+			(keylargo_base + ((0x8000+i*0x100)>>2));
+		save_dbdma[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
+		save_dbdma[i].cmdptr = in_le32(&chan->cmdptr);
+		save_dbdma[i].intr_sel = in_le32(&chan->intr_sel);
+		save_dbdma[i].br_sel = in_le32(&chan->br_sel);
+		save_dbdma[i].wait_sel = in_le32(&chan->wait_sel);
 	}
-	if (ctrler->bits == feature_bits_keylargo) {
-		core99_prepare_for_sleep(ctrler);
-		return;
+
+	/*
+	 * Turn off as much as we can
+	 */
+	if (keylargo_rev & KL_PANGEA_REV)
+		turn_off_pangea();
+	else
+		turn_off_keylargo();
+	
+	/* 
+	 * Put the host bridge to sleep
+	 */
+
+	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
+		~(UNI_N_CLOCK_CNTL_GMAC|UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
+	udelay(100);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
+
+	/*
+	 * FIXME: A bit of black magic with OpenPIC (don't ask me why)
+	 */
+	if (board_features & FTR_NEED_OPENPIC_TWEAK) {
+		KL_BIS(0x506e0, 0x00400000);
+		KL_BIS(0x506e0, 0x80000000);
 	}
 }
 
-void
-feature_wake_up(void)
+static void
+core99_wake_up(struct feature_controller* ctrler)
 {
-	struct feature_controller* ctrler = &controllers[0];
+	int i;
+	u8* base8;
 
-	if (!ctrler)
-		return;
-	if (controller_count > 1 &&
-		device_is_compatible(ctrler->device, "gatwick"))
-		ctrler = &controllers[1];
+	/*
+	 * Wakeup the host bridge
+	 */
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+	udelay(10);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+	udelay(10);
 	
-	if (ctrler->bits == feature_bits_heathrow ||
-		ctrler->bits == feature_bits_paddington) {
-		heathrow_wakeup(ctrler);
-		return;
+	/*
+	 * Restore KeyLargo
+	 */
+	 
+	KL_OUT(KEYLARGO_MBCR, save_mbcr);
+	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
+	KL_OUT(KEYLARGO_FCR0, save_fcr[0]);
+	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
+	KL_OUT(KEYLARGO_FCR1, save_fcr[1]);
+	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
+	KL_OUT(KEYLARGO_FCR2, save_fcr[2]);
+	(void)KL_IN(KEYLARGO_FCR2); udelay(10);
+	KL_OUT(KEYLARGO_FCR3, save_fcr[3]);
+	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
+	KL_OUT(KEYLARGO_FCR4, save_fcr[4]);
+	(void)KL_IN(KEYLARGO_FCR4); udelay(10);
+
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
+			(keylargo_base + ((0x8000+i*0x100)>>2));
+		out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
+		while (in_le32(&chan->status) & ACTIVE)
+			mb();
+		out_le32(&chan->cmdptr_hi, save_dbdma[i].cmdptr_hi);
+		out_le32(&chan->cmdptr, save_dbdma[i].cmdptr);
+		out_le32(&chan->intr_sel, save_dbdma[i].intr_sel);
+		out_le32(&chan->br_sel, save_dbdma[i].br_sel);
+		out_le32(&chan->wait_sel, save_dbdma[i].wait_sel);
 	}
-	if (ctrler->bits == feature_bits_keylargo) {
-		core99_wake_up(ctrler);
-		return;
+
+	KL_OUT(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
+	KL_OUT(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_EXTINT_0);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		out_8(base8+i, save_gpio_extint[i]);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_0);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		out_8(base8+i, save_gpio_normal[i]);
+
+	/* FIXME more black magic with OpenPIC ... */
+	if (board_features & FTR_NEED_OPENPIC_TWEAK) {
+		KL_BIC(0x506e0, 0x00400000);
+		KL_BIC(0x506e0, 0x80000000);
 	}
-}
 
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
+	udelay(100);
+}
 #endif /* CONFIG_PMAC_PBOOK */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/find_name.c linux/arch/ppc/kernel/find_name.c
--- v2.4.4/linux/arch/ppc/kernel/find_name.c	Wed Sep 30 10:14:17 1998
+++ linux/arch/ppc/kernel/find_name.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.find_name.c 1.5 05/17/01 18:14:21 cort
+ */
 #include <stdio.h>
 #include <asm/page.h>
 #include <sys/mman.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/galaxy_pci.c linux/arch/ppc/kernel/galaxy_pci.c
--- v2.4.4/linux/arch/ppc/kernel/galaxy_pci.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/galaxy_pci.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.galaxy_pci.c 1.7 05/17/01 18:14:21 cort
+ */
+/*
  *
  *    Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
  *    All rights reserved.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/gemini_pci.c linux/arch/ppc/kernel/gemini_pci.c
--- v2.4.4/linux/arch/ppc/kernel/gemini_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_pci.c	Mon May 21 17:04:47 2001
@@ -0,0 +1,124 @@
+/*
+ * BK Id: SCCS/s.gemini_pci.c 1.5 05/17/01 18:14:21 cort
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+
+#include <asm/machdep.h>
+#include <asm/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pci-bridge.h>
+
+#include "pci.h"
+
+#define pci_config_addr(bus,dev,offset) \
+        (0x80000000 | (bus<<16) | (dev<<8) | offset)
+
+
+int
+gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
+{
+	unsigned long reg;
+	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					   (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
+{
+	unsigned long reg;
+	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					   (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
+{
+	*val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3))));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3)));
+
+	reg = grackle_read(addr);
+	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write(addr, reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3)));
+
+	reg = grackle_read(addr);
+	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write(addr, reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
+{
+	grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
+				      (offset & ~(0x3))), val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops gemini_pci_ops =
+{
+	gemini_pcibios_read_config_byte,
+	gemini_pcibios_read_config_word,
+	gemini_pcibios_read_config_dword,
+	gemini_pcibios_write_config_byte,
+	gemini_pcibios_write_config_word,
+	gemini_pcibios_write_config_dword
+};
+
+void __init gemini_pcibios_fixup(void)
+{
+	int i;
+	struct pci_dev *dev;
+	
+	pci_for_each_dev(dev) {
+		for(i = 0; i < 6; i++) {
+			if (dev->resource[i].flags & IORESOURCE_IO) {
+				dev->resource[i].start |= (0xfe << 24);
+				dev->resource[i].end |= (0xfe << 24);
+			}
+		}
+	}
+}
+
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+   lay it all out ourselves... --Dan */
+void __init gemini_find_bridges(void)
+{
+	struct pci_controller* hose;
+	
+	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	hose->ops = &gemini_pci_ops;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/gemini_prom.S linux/arch/ppc/kernel/gemini_prom.S
--- v2.4.4/linux/arch/ppc/kernel/gemini_prom.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_prom.S	Mon May 21 17:04:47 2001
@@ -0,0 +1,99 @@
+/*
+ * BK Id: SCCS/s.gemini_prom.S 1.5 05/17/01 18:14:21 cort
+ */
+/*
+ *  arch/ppc/kernel/gemini_prom.S
+ *
+ *  Not really prom support code (yet), but sort of anti-prom code.  The current
+ *  bootloader does a number of things it shouldn't and doesn't do things that it
+ *  should.  The stuff in here is mainly a hodge-podge collection of setup code
+ *  to get the board up and running.
+ *    ---Dan
+ */
+
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/gemini.h>
+
+#define HID0_ABE (1<<3)
+
+/*
+ *  On 750's the MMU is on when Linux is booted, so we need to clear out the
+ *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ *  and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef CONFIG_SMP
+	/* Since the MMU's on, get stuff in rom space that we'll need */
+	lis	r4,GEMINI_CPUSTAT@h
+	ori	r4,r4,GEMINI_CPUSTAT@l
+	lbz	r5,0(r4)
+	andi.	r5,r5,3
+	mr	r24,r5		/* cpu # used later on */
+#endif
+	mfmsr	r4
+	li	r3,MSR_PR	/* ensure supervisor! */
+	ori	r3,r3,MSR_IR|MSR_DR
+	andc	r4,r4,r3
+	mtmsr	r4
+	isync
+#if 0
+	/* zero out the bats now that the MMU is off */
+prom_no_mmu:	
+	li	r3,0
+        mtspr   IBAT0U,r3
+        mtspr   IBAT0L,r3
+        mtspr   IBAT1U,r3
+        mtspr   IBAT1L,r3
+        mtspr   IBAT2U,r3
+        mtspr   IBAT2L,r3
+        mtspr   IBAT3U,r3
+        mtspr   IBAT3L,r3
+
+        mtspr   DBAT0U,r3
+        mtspr   DBAT0L,r3
+        mtspr   DBAT1U,r3
+        mtspr   DBAT1L,r3
+        mtspr   DBAT2U,r3
+	mtspr   DBAT2L,r3
+        mtspr   DBAT3U,r3
+        mtspr   DBAT3L,r3
+#endif
+
+	/* the bootloader (as far as I'm currently aware) doesn't mess with page
+	   tables, but since we're already here, might as well zap these, too */
+	li	r4,0
+	mtspr	SDR1,r4
+
+	li	r4,16
+	mtctr	r4
+	li	r3,0
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1
+	bdnz	3b
+
+#ifdef CONFIG_SMP
+	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+	   when in SMP.  Not sure yet whether this should stay or leave... */
+	mfspr	r4,HID0
+	ori	r4,r4,HID0_ABE
+	mtspr	HID0,r4
+	sync
+#endif /* CONFIG_SMP */
+	blr
+
+/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
+    branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+	lis	r5,GEMINI_BOOT_INIT@h
+	ori	r5,r5,GEMINI_BOOT_INIT@l
+	li	r6,MSR_IP
+	mtspr	SRR0,r5
+	mtspr	SRR1,r6
+	rfi
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.4.4/linux/arch/ppc/kernel/gemini_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_setup.c	Mon May 21 17:04:47 2001
@@ -0,0 +1,540 @@
+/*
+ * BK Id: SCCS/s.gemini_setup.c 1.7 05/17/01 18:14:21 cort
+ */
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  Copyright (C) 1995 Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h> 
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <asm/gemini.h>
+#include <asm/time.h>
+
+#include "local_irq.h"
+#include "open_pic.h"
+
+void gemini_find_bridges(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
+
+static char *gemini_board_families[] = {
+  "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
+};
+static int gemini_board_count = sizeof(gemini_board_families) /
+                                 sizeof(gemini_board_families[0]);
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+int chrp_get_irq(struct pt_regs *);
+void chrp_post_irq(struct pt_regs* regs, int);
+
+static inline unsigned long _get_HID1(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__("mfspr %0,1009" : "=r" (val));
+	return val;
+}
+
+/*
+ * prom_init is the Gemini version of prom.c:prom_init.  We only need
+ * the BSS clearing code, so I copied that out of prom.c.  This is a
+ * lot simpler than hacking prom.c so it will build with Gemini. -VAL
+ */
+
+#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
+
+unsigned long
+prom_init(void)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long phys;
+	extern char __bss_start, _end;
+
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
+
+	gemini_prom_init();
+
+	return phys;
+}
+
+int
+gemini_get_cpuinfo(char *buffer)
+{
+	int len;
+	unsigned char reg, rev;
+	char *family;
+	unsigned int type;
+
+	reg = readb(GEMINI_FEAT);
+	family = gemini_board_families[((reg>>4) & 0xf)];
+	if (((reg>>4) & 0xf) > gemini_board_count)
+		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+	reg = readb(GEMINI_BREV);
+	type = (reg>>4) & 0xf;
+	rev = reg & 0xf;
+
+	reg = readb(GEMINI_BECO);
+
+	len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
+		       family, type, (rev + 'A'), (reg & 0xf));
+
+	len = sprintf(buffer, "board\t\t: Gemini %s", family);
+	if (type > 9)
+		len += sprintf(buffer+len, "%c", (type - 10) + 'A');
+	else
+		len += sprintf(buffer+len, "%d", type);
+
+	len += sprintf(buffer+len, ", rev %c, eco %d\n",
+		       (rev + 'A'), (reg & 0xf));
+
+	len += sprintf(buffer+len, "clock\t\t: %dMhz\n", 
+		       gemini_get_clock_speed());
+
+	return len;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+
+	OpenPIC_Addr = (volatile struct OpenPIC *)
+		grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
+	OpenPIC_InitSenses = gemini_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+	ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
+}
+
+
+extern unsigned long loops_per_jiffy;
+extern int root_mountflags;
+extern char cmd_line[];
+
+void
+gemini_heartbeat(void)
+{
+	static unsigned long led = GEMINI_LEDBASE+(4*8);
+	static char direction = 8;
+	*(char *)led = 0;
+	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
+	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
+		direction *= -1;
+	led += direction;
+	*(char *)led = 0xff;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __init gemini_setup_arch(void)
+{
+	extern char cmd_line[];
+
+
+	loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* bootable off CDROM */
+	if (initrd_start)
+		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(0x0801);
+
+	/* nothing but serial consoles... */
+	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+	printk("Boot arguments: %s\n", cmd_line);
+
+	ppc_md.heartbeat = gemini_heartbeat;
+	ppc_md.heartbeat_reset = HZ/8;
+	ppc_md.heartbeat_count = 1;
+	
+	/* Lookup PCI hosts */
+	gemini_find_bridges();
+	/* take special pains to map the MPIC, since it isn't mapped yet */
+	gemini_openpic_init();
+	/* start the L2 */
+	gemini_init_l2();
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+	unsigned long hid1, pvr = _get_PVR();
+	int clock;
+
+	hid1 = (_get_HID1() >> 28) & 0xf;
+	if (PVR_VER(pvr) == 8 ||
+	    PVR_VER(pvr) == 12)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
+
+	case 0:
+	default:
+		clock = (hid1*100)/3;
+		break;
+  
+	case 1:
+		clock = (hid1*125)/3;
+		break;
+  
+	case 2:
+		clock = (hid1*50);
+		break;
+	}
+
+	return clock;
+}
+
+void __init gemini_init_l2(void)
+{
+        unsigned char reg, brev, fam, creg;
+        unsigned long cache;
+        unsigned long pvr = _get_PVR();
+
+        reg = readb(GEMINI_L2CFG);
+        brev = readb(GEMINI_BREV);
+        fam = readb(GEMINI_FEAT);
+
+        switch(PVR_VER(pvr)) {
+
+        case 8:
+                if (reg & 0xc0)
+                        cache = (((reg >> 6) & 0x3) << 28);
+                else
+                        cache = 0x3 << 28;
+
+#ifdef CONFIG_SMP
+                /* Pre-3.0 processor revs had snooping errata.  Leave
+                   their L2's disabled with SMP. -- Dan */
+                if (PVR_CFG(pvr) < 3) {
+                        printk("Pre-3.0 750; L2 left disabled!\n");
+                        return;
+                }
+#endif /* CONFIG_SMP */
+
+                /* Special case: VGM5-B's came before L2 ratios were set on
+                   the board.  Processor speed shouldn't be too high, so
+                   set L2 ratio to 1:1.5.  */
+                if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+                        reg |= 1;
+
+                /* determine best cache ratio based upon what the board
+                   tells us (which sometimes _may_ not be true) and
+                   the processor speed. */
+                else {
+                        if (gemini_get_clock_speed() > 250)
+                                reg = 2;
+                }
+                break;
+        case 12:
+	{
+		static unsigned long l2_size_val = 0;
+		
+		if (!l2_size_val)
+			l2_size_val = _get_L2CR();
+		cache = l2_size_val;
+                break;
+	}
+        case 4:
+        case 9:
+                creg = readb(GEMINI_CPUSTAT);
+                if (((creg & 0xc) >> 2) != 1)
+                        printk("Dual-604 boards don't support the use of L2\n");
+                else
+                        writeb(1, GEMINI_L2CFG);
+                return;
+        default:
+                printk("Unknown processor; L2 left disabled\n");
+                return;
+        }
+
+        cache |= ((1<<reg) << 25);
+        cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
+        _set_L2CR(0);
+        _set_L2CR(cache | L2CR_L2E);
+
+}
+
+void
+gemini_restart(char *cmd)
+{
+	__cli();
+	/* make a clean restart, not via the MPIC */
+	_gemini_reboot();
+	for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+	for(;;);
+}
+
+void
+gemini_halt(void)
+{
+	gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+	/* gemini has no 8259 */
+	openpic_init(1, 0, 0, -1);
+}
+
+#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+long __init gemini_time_init(void)
+{
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+	if ( reg & M48T35_RTC_STOPPED ) {
+		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+	}
+	return 0;
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("get rtc: reg = %x\n", reg);
+#endif
+  
+	do {
+		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+		min = gemini_rtc_read(M48T35_RTC_MINUTES);
+		hour = gemini_rtc_read(M48T35_RTC_HOURS);
+		day = gemini_rtc_read(M48T35_RTC_DOM);
+		mon = gemini_rtc_read(M48T35_RTC_MONTH);
+		year = gemini_rtc_read(M48T35_RTC_YEAR);
+	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+	unsigned char reg;
+	struct rtc_time tm;
+
+	to_tm( now, &tm );
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: reg = %x\n", reg);
+#endif
+  
+	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+  
+	tm.tm_year -= 1900;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+	/* done writing */
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+		time_state = TIME_OK;
+  
+	return 0;
+}
+
+/*  use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+	int freq, divisor;
+	unsigned char reg;
+
+	/* determine processor bus speed */
+	reg = readb(GEMINI_BSTAT);
+
+	switch(((reg & 0x0c)>>2)&0x3) {
+	case 0:
+	default:
+		freq = 66667;
+		break;
+	case 1:
+		freq = 83000;
+		break;
+	case 2:
+		freq = 100000;
+		break;
+	}
+
+	freq *= 1000;
+	divisor = 4;
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+unsigned long __init gemini_find_end_of_memory(void)
+{
+	unsigned long total;
+	unsigned char reg;
+
+	reg = readb(GEMINI_MEMCFG);
+	total = ((1<<((reg & 0x7) - 1)) *
+		 (8<<((reg >> 3) & 0x7)));
+	total *= (1024*1024);
+	return total;
+}
+
+void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7)
+{
+	int i;
+	int chrp_get_irq( struct pt_regs * );
+
+	for(i = 0; i < GEMINI_LEDS; i++)
+		gemini_led_off(i);
+ 
+	ISA_DMA_THRESHOLD = 0;
+	DMA_MODE_READ = 0;
+	DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	ppc_md.setup_arch = gemini_setup_arch;
+	ppc_md.setup_residual = NULL;
+	ppc_md.get_cpuinfo = gemini_get_cpuinfo;
+	ppc_md.irq_cannonicalize = NULL;
+	ppc_md.init_IRQ = gemini_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = NULL;
+
+	ppc_md.restart = gemini_restart;
+	ppc_md.power_off = gemini_power_off;
+	ppc_md.halt = gemini_halt;
+
+	ppc_md.time_init = gemini_time_init;
+	ppc_md.set_rtc_time = gemini_set_rtc_time;
+	ppc_md.get_rtc_time = gemini_get_rtc_time;
+	ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+	ppc_md.find_end_of_memory = gemini_find_end_of_memory;
+
+	/* no keyboard/mouse/video stuff yet.. */
+	ppc_md.kbd_setkeycode = NULL;
+	ppc_md.kbd_getkeycode = NULL;
+	ppc_md.kbd_translate = NULL;
+	ppc_md.kbd_unexpected_up = NULL;
+	ppc_md.kbd_leds = NULL;
+	ppc_md.kbd_init_hw = NULL;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.ppc_kbd_sysrq_xlate = NULL;
+#endif
+	ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
+}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S
--- v2.4.4/linux/arch/ppc/kernel/hashtable.S	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/hashtable.S	Mon May 21 17:04:47 2001
@@ -1,8 +1,9 @@
 /*
+ * BK Id: SCCS/s.hashtable.S 1.11 05/17/01 18:14:21 cort
+ */
+/*
  *  arch/ppc/kernel/hashtable.S
  *
- *  $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $
- *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
@@ -27,7 +28,6 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <linux/config.h>
-#include "mol.h"
 
 /*
  * Load a PTE into the hash table, if possible.
@@ -609,11 +609,6 @@
  * flush_hash_page(unsigned context, unsigned long va)
  */
 _GLOBAL(flush_hash_page)
-#ifdef CONFIG_MOL
-	mflr    r10
-	MOL_HOOK_MMU(10, r6)
-	mtlr    r10
-#endif
 	lis	r6,Hash@ha
 	lwz	r6,Hash@l(r6)		/* hash table base */
 	cmpwi	0,r6,0			/* hash table in use? */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.4.4/linux/arch/ppc/kernel/head.S	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/kernel/head.S	Thu May 24 15:03:05 2001
@@ -1,8 +1,7 @@
 /*
- *  arch/ppc/kernel/head.S
- *
- *  $Id: head.S,v 1.154 1999/10/12 00:33:31 cort Exp $
- *
+ * BK Id: SCCS/s.head.S 1.21 05/23/01 00:38:42 cort
+ */
+/*
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *
@@ -31,24 +30,11 @@
 #include <asm/page.h>
 #include <linux/config.h>
 #include <asm/mmu.h>
-#include "mol.h"
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
 #endif
 
-#ifndef CONFIG_PPC64BRIDGE
-CACHELINE_BYTES = 32
-LG_CACHELINE_BYTES = 5
-CACHELINE_MASK = 0x1f
-CACHELINE_WORDS = 8
-#else
-CACHELINE_BYTES = 128
-LG_CACHELINE_BYTES = 7
-CACHELINE_MASK = 0x7f
-CACHELINE_WORDS = 32
-#endif /* CONFIG_PPC64BRIDGE */
-
 #ifdef CONFIG_PPC64BRIDGE
 #define LOAD_BAT(n, reg, RA, RB)	\
 	ld	RA,(n*32)+0(reg);	\
@@ -149,9 +135,12 @@
 	mr	r28,r6
 	mr	r27,r7
 	li	r24,0			/* cpu # */
-	/* N.B. prom_init clears the BSS even if it doesn't do
-	 * anything else -- paulus. */
-	bl	prom_init
+/*
+ * early_init() does the early machine identification and does
+ * the necessary low-level setup and clears the BSS
+ *  -- Cort <cort@fsmlabs.com>
+ */ 
+	bl	early_init
 
 #ifdef CONFIG_APUS
 /* On APUS the __va/__pa constants need to be set to the correct 
@@ -161,6 +150,7 @@
 	bl	fix_mem_constants
 #endif /* CONFIG_APUS */
 
+#ifndef CONFIG_GEMINI
 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
  * the physical address we are running at, returned by prom_init()
  */
@@ -168,6 +158,7 @@
 __after_mmu_off:
 	bl	clear_bats
 	bl	flush_tlbs
+#endif
 
 #ifndef CONFIG_POWER4
 	/* POWER4 doesn't have BATs */
@@ -294,21 +285,14 @@
 	.long	hdlr;				\
 	.long	ret_from_except
 
-#define STD_MOL_EXCEPTION(n, label, hdlr, hook)	\
-	. = n;					\
-label:						\
-	EXCEPTION_PROLOG;			\
-	MOL_HOOK(hook); 			\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;	\
-	li	r20,MSR_KERNEL;			\
-	bl	transfer_to_handler; 		\
-i##n:						\
-	.long	hdlr;				\
-	.long	ret_from_except
-
 /* System reset */
-#ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
+#ifdef CONFIG_SMP /* MVME/MTX and gemini start the secondary here */
+#ifdef CONFIG_GEMINI
+	. = 0x100
+	b	__secondary_start_gemini
+#else /* CONFIG_GEMINI */
 	STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
+#endif /* CONFIG_GEMINI */
 #else
 	STD_EXCEPTION(0x100, Reset, UnknownException)
 #endif
@@ -325,7 +309,6 @@
 DataAccess:
 	EXCEPTION_PROLOG
 #endif /* CONFIG_PPC64BRIDGE */
-	MOL_HOOK(0)
 	mfspr	r20,DSISR
 	andis.	r0,r20,0xa470		/* weird error? */
 	bne	1f			/* if not, try to put a PTE */
@@ -369,7 +352,6 @@
 InstructionAccess:
 	EXCEPTION_PROLOG
 #endif /* CONFIG_PPC64BRIDGE */
-	MOL_HOOK(1)
 	andis.	r0,r23,0x4000		/* no pte found? */
 	beq	1f			/* if so, try to put a PTE */
 	mr	r3,r22			/* into the hash table */
@@ -436,7 +418,6 @@
 	. = 0x700
 ProgramCheck:
 	EXCEPTION_PROLOG
-	MOL_HOOK(2)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
@@ -449,7 +430,6 @@
 	. = 0x800
 FPUnavailable:
 	EXCEPTION_PROLOG
-	MOL_HOOK_RESTORE(3)
 	bne	load_up_fpu		/* if from user, just load it up */
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler	/* if from kernel, take a trap */
@@ -460,7 +440,6 @@
 	. = 0x900
 Decrementer:
 	EXCEPTION_PROLOG
-	MOL_HOOK(4)	
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler
@@ -484,7 +463,7 @@
 	.long	ret_from_except
 
 /* Single step - not used on 601 */
-	STD_MOL_EXCEPTION(0xd00, SingleStep, SingleStepException, 5)
+	STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
 	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 
 /*
@@ -514,7 +493,6 @@
  */
 	. = 0x1000
 InstructionTLBMiss:
-	MOL_HOOK_TLBMISS( 14 )
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -586,7 +564,6 @@
  */
 	. = 0x1100
 DataLoadTLBMiss:
-	MOL_HOOK_TLBMISS( 15 )
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -657,7 +634,6 @@
  */
 	. = 0x1200
 DataStoreTLBMiss:
-	MOL_HOOK_TLBMISS( 16 )
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -704,7 +680,7 @@
 	mtcrf	0x80,r3
 	rfi
 
-	STD_MOL_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, 11)
+	STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
 	STD_EXCEPTION(0x1400, SMI, SMIException)
 	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
 	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
@@ -717,7 +693,7 @@
 	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
 	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
 	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
-	STD_MOL_EXCEPTION(0x2000, RunMode, RunModeException, 5)
+	STD_EXCEPTION(0x2000, RunMode, RunModeException)
 	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
 	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
 	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
@@ -739,7 +715,6 @@
 #ifdef CONFIG_ALTIVEC
 AltiVecUnavailable:
 	EXCEPTION_PROLOG
-	MOL_HOOK_RESTORE(12)
 	bne	load_up_altivec		/* if from user, just load it up */
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler	/* if from kernel, take a trap */
@@ -792,8 +767,6 @@
 	mflr	r23
 	andi.	r24,r23,0x3f00		/* get vector offset */
 	stw	r24,TRAP(r21)
-	li	r22,RESULT
-	stwcx.	r22,r22,r21		/* to clear the reservation */
 	li	r22,0
 	stw	r22,RESULT(r21)
 	mtspr	SPRG2,r22		/* r1 is now kernel sp */
@@ -805,7 +778,6 @@
 	lwz	r24,0(r23)		/* virtual address of handler */
 	lwz	r23,4(r23)		/* where to go when done */
 	FIX_SRR1(r20,r22)
-	MOL_HOOK(6)
 	mtspr	SRR0,r24
 	mtspr	SRR1,r20
 	mtlr	r23
@@ -1016,11 +988,6 @@
 
 	.globl	giveup_altivec
 giveup_altivec:
-#ifdef CONFIG_MOL
-	mflr	r4
-	MOL_HOOK_MMU(13, r5)
-	mtlr	r4
-#endif
 	mfmsr	r5
 	oris	r5,r5,MSR_VEC@h
 	SYNC
@@ -1057,11 +1024,6 @@
  */
 	.globl	giveup_fpu
 giveup_fpu:
-#ifdef CONFIG_MOL
-	mflr	r4
-	MOL_HOOK_MMU(7, r5)
-	mtlr	r4
-#endif		
 	mfmsr	r5
 	ori	r5,r5,MSR_FP
 	SYNC
@@ -1116,7 +1078,7 @@
 copy_and_flush:
 	addi	r5,r5,-4
 	addi	r6,r6,-4
-4:	li	r0,CACHELINE_WORDS
+4:	li	r0,CACHE_LINE_SIZE/4
 	mtctr	r0
 3:	addi	r6,r6,4			/* copy a cache line */
 	lwzx	r0,r6,r4
@@ -1127,6 +1089,7 @@
 	icbi	r6,r3			/* flush the icache line */
 	cmplw	0,r6,r5
 	blt	4b
+	sync				/* additional sync needed on g4 */
 	isync
 	addi	r5,r5,4
 	addi	r6,r6,4
@@ -1165,6 +1128,7 @@
 	icbi	r0,r14			 /* flush the icache line */
 	cmpw	r12,r13
 	bne     1b
+	sync				/* additional sync needed on g4 */
 	isync
 
 /*
@@ -1199,6 +1163,7 @@
 	cmpw	r12,r13
 	bne     1b
 
+	sync				/* additional sync needed on g4 */
 	isync				/* No speculative loading until now */
 	blr
 	
@@ -1266,6 +1231,20 @@
 #endif /* CONFIG_APUS */
 
 #ifdef CONFIG_SMP
+#ifdef CONFIG_GEMINI
+	.globl	__secondary_start_gemini
+__secondary_start_gemini:
+        mfspr   r4,HID0
+        ori     r4,r4,HID0_ICFI
+        li      r3,0
+        ori     r3,r3,HID0_ICE
+        andc    r4,r4,r3
+        mtspr   HID0,r4
+        sync
+        bl      prom_init
+        b       __secondary_start
+#endif /* CONFIG_GEMINI */
+	
 	.globl	__secondary_start_psurge
 __secondary_start_psurge:
 	li	r24,1			/* cpu # */
@@ -1536,6 +1515,7 @@
  *  -- Cort 
  */
 clear_bats:
+#if !defined(CONFIG_GEMINI)
 	li	r20,0
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
@@ -1559,8 +1539,10 @@
 	mtspr	IBAT2L,r20
 	mtspr	IBAT3U,r20
 	mtspr	IBAT3L,r20
+#endif /* !defined(CONFIG_GEMINI) */
 	blr
 
+#ifndef CONFIG_GEMINI
 flush_tlbs:
 	lis	r20, 0x40
 1:	addic.	r20, r20, -0x1000
@@ -1579,6 +1561,7 @@
 	mtspr	SRR1,r3
 	sync
 	RFI
+#endif
 
 #ifndef CONFIG_POWER4	
 /*
@@ -1690,17 +1673,6 @@
 	blr
 #endif
 
-#ifdef CONFIG_MOL
-/*
- * Mac-on-linux hook_table. Don't put this in the data section -
- * the base address must be within the first 32KB of RAM.
- */
-	.globl mol_interface
-mol_interface:
-	.long   MOL_INTERFACE_VERSION
-	.fill	24,4,0		/* space for 24 hooks */
-#endif
-
 
 /*
  * We put a few things here that have to be page-aligned.
@@ -1728,7 +1700,7 @@
 
 	.globl intercept_table
 intercept_table:
-	.long 0, i0x100, i0x200, i0x300, i0x400, 0, i0x600, i0x700
+	.long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700
 	.long i0x800, 0, 0, 0, 0, i0xd00, 0, 0
 	.long 0, 0, 0, i0x1300, 0, 0, 0, 0
 	.long 0, 0, 0, 0, 0, 0, 0, 0
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/head_4xx.S linux/arch/ppc/kernel/head_4xx.S
--- v2.4.4/linux/arch/ppc/kernel/head_4xx.S	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/kernel/head_4xx.S	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.head_4xx.S 1.6 05/21/01 11:50:00 paulus
+ */
+/*
  *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
  *      Initial PowerPC version.
  *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
@@ -387,8 +390,6 @@
 	mflr	r23
 	andi.	r24,r23,0x3f00		# Get vector offset
 	stw	r24,TRAP(r21)
-	li	r22,RESULT
-	stwcx.	r22,r22,r21		# Clear the reservation
 	li	r22,0
 	stw	r22,RESULT(r21)
 	mtspr	SPRN_SPRG2,r22		# r1 is now the kernel stack pointer
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- v2.4.4/linux/arch/ppc/kernel/head_8xx.S	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/head_8xx.S	Mon May 21 17:04:47 2001
@@ -1,8 +1,9 @@
 /*
+ * BK Id: SCCS/s.head_8xx.S 1.11 05/21/01 11:50:00 paulus
+ */
+/*
  *  arch/ppc/kernel/except_8xx.S
  *
- *  $Id: head_8xx.S,v 1.4 1999/09/18 18:43:19 dmalek Exp $
- *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
@@ -30,13 +31,6 @@
 #include <asm/mmu.h>
 #include <asm/cache.h>
 #include <asm/pgtable.h>
-	
-/* XXX need definitions here for 16 byte cachelines on some/all 8xx
-   -- paulus */
-CACHELINE_BYTES = 32
-LG_CACHELINE_BYTES = 5
-CACHELINE_MASK = 0x1f
-CACHELINE_WORDS = 8
 
 	.text
 	.globl	_stext
@@ -685,8 +679,6 @@
 	mflr	r23
 	andi.	r24,r23,0x3f00		/* get vector offset */
 	stw	r24,TRAP(r21)
-	li	r22,RESULT
-	stwcx.	r22,r22,r21		/* to clear the reservation */
 	li	r22,0
 	stw	r22,RESULT(r21)
 	mtspr	SPRG2,r22		/* r1 is now kernel sp */
@@ -757,7 +749,7 @@
 copy_and_flush:
 	addi	r5,r5,-4
 	addi	r6,r6,-4
-4:	li	r0,CACHELINE_WORDS
+4:	li	r0,CACHE_LINE_SIZE/4
 	mtctr	r0
 3:	addi	r6,r6,4			/* copy a cache line */
 	lwzx	r0,r6,r4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
--- v2.4.4/linux/arch/ppc/kernel/i8259.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/i8259.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.i8259.c 1.7 05/17/01 18:14:21 cort
+ */
 
 #include <linux/stddef.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/i8259.h linux/arch/ppc/kernel/i8259.h
--- v2.4.4/linux/arch/ppc/kernel/i8259.h	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/i8259.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.i8259.h 1.5 05/17/01 18:14:21 cort
+ */
 
 #ifndef _PPC_KERNEL_i8259_H
 #define _PPC_KERNEL_i8259_H
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.4.4/linux/arch/ppc/kernel/idle.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/idle.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: idle.c,v 1.68 1999/10/15 18:16:03 cort Exp $
- *
+ * BK Id: SCCS/s.idle.c 1.11 05/17/01 18:14:21 cort
+ */
+/*
  * Idle daemon for PowerPC.  Idle daemon will handle any action
  * that needs to be taken when the system becomes idle.
  *
@@ -56,6 +57,7 @@
 	case 7:			/* 603ev */
 	case 8:			/* 750 */
 	case 12:		/* 7400 */
+	case 0x800c:		/* 7410 */
 		do_power_save = 1;
 	}
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/indirect_pci.c linux/arch/ppc/kernel/indirect_pci.c
--- v2.4.4/linux/arch/ppc/kernel/indirect_pci.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/indirect_pci.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.indirect_pci.c 1.7 05/17/01 18:14:21 cort
+ */
+/*
  * Support for indirect PCI bridges.
  *
  * Copyright (C) 1998 Gabriel Paubert.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.4.4/linux/arch/ppc/kernel/irq.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/irq.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: irq.c,v 1.113 1999/09/17 17:22:56 cort Exp $
- *
+ * BK Id: SCCS/s.irq.c 1.23 05/17/01 18:14:21 cort
+ */
+/*
  *  arch/ppc/kernel/irq.c
  *
  *  Derived from arch/i386/kernel/irq.c
@@ -176,9 +177,19 @@
 	return 0;
 }
 
-/* This could be promoted to a real free_irq() ... */
-static int
-do_free_irq(int irq, void* dev_id)
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+/* Name change so we can catch standard drivers that potentially mess up
+ * the internal interrupt controller on 8xx and 8260.  Just bear with me,
+ * I don't like this either and I am searching a better solution.  For
+ * now, this is what I need. -- Dan
+ */
+#define request_irq	request_8xxirq
+#elif defined(CONFIG_APUS)
+#define request_irq	request_sysirq
+#define free_irq	sys_free_irq
+#endif
+
+void free_irq(unsigned int irq, void* dev_id)
 {
 	irq_desc_t *desc;
 	struct irqaction **p;
@@ -209,27 +220,15 @@
 				barrier();
 #endif
 			irq_kfree(action);
-			return 0;
+			return;
 		}
 		printk("Trying to free free IRQ%d\n",irq);
 		spin_unlock_irqrestore(&desc->lock,flags);
 		break;
 	}
-	return -ENOENT;
+	return;
 }
 
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
-/* Name change so we can catch standard drivers that potentially mess up
- * the internal interrupt controller on 8xx and 8260.  Just bear with me,
- * I don't like this either and I am searching a better solution.  For
- * now, this is what I need. -- Dan
- */
-#define request_irq	request_8xxirq
-#elif defined(CONFIG_APUS)
-#define request_irq	request_sysirq
-#define free_irq	sys_free_irq
-#endif
-
 int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
 	unsigned long irqflags, const char * devname, void *dev_id)
 {
@@ -239,8 +238,17 @@
 	if (irq >= NR_IRQS)
 		return -EINVAL;
 	if (!handler)
-		/* We could implement really free_irq() instead of that... */
-		return do_free_irq(irq, dev_id);
+	{
+		/*
+		 * free_irq() used to be implemented as a call to
+		 * request_irq() with handler being NULL.  Now we have
+		 * a real free_irq() but need to allow the old behavior
+		 * for old code that hasn't caught up yet.
+		 *  -- Cort <cort@fsmlabs.com>
+		 */
+		free_irq(irq, dev_id);
+		return 0;
+	}
 	
 	action = (struct irqaction *)
 		irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL);
@@ -266,11 +274,6 @@
 	return 0;
 }
 
-void free_irq(unsigned int irq, void *dev_id)
-{
-	request_irq(irq, NULL, 0, NULL, dev_id);
-}
-
 /*
  * Generic enable/disable code: this just calls
  * down into the PIC-specific version for the actual
@@ -524,7 +527,7 @@
 	spin_unlock(&desc->lock);
 }
 
-int do_IRQ(struct pt_regs *regs, int isfake)
+int do_IRQ(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 	int irq;
@@ -546,10 +549,7 @@
 		goto out;
 	}
 	ppc_irq_dispatch_handler( regs, irq );
-	if (ppc_md.post_irq)
-		ppc_md.post_irq( regs, irq );
-
- out:	
+out:	
         hardirq_exit( cpu );
 	return 1; /* lets ret_from_int know we can do checks */
 }
@@ -851,15 +851,18 @@
 }
 #endif /* CONFIG_SMP */
 
-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 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];
 
 #ifdef CONFIG_IRQ_ALL_CPUS
-unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0xffffffff};
-#else  /* CONFIG_IRQ_ALL_CPUS */
-unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0x00000000};
-#endif /* CONFIG_IRQ_ALL_CPUS */
+#define DEFAULT_CPU_AFFINITY 0xffffffff
+#else
+#define DEFAULT_CPU_AFFINITY 0x00000001
+#endif
+
+unsigned int irq_affinity [NR_IRQS] =
+	{ [0 ... NR_IRQS-1] = DEFAULT_CPU_AFFINITY };
 
 #define HEX_DIGITS 8
 
@@ -919,16 +922,18 @@
 
 	err = parse_hex_value(buffer, count, &new_value);
 
-/* Why is this disabled ? --BenH */
-#if 0/*CONFIG_SMP*/
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
+	 *
+	 * We assume a 1-1 logical<->physical cpu mapping here.  If
+	 * we assume that the cpu indices in /proc/irq/../smp_affinity
+	 * are actually logical cpu #'s then we have no problem.
+	 *  -- Cort <cort@fsmlabs.com>
 	 */
 	if (!(new_value & cpu_online_map))
 		return -EINVAL;
-#endif
 
 	irq_affinity[irq] = new_value;
 	irq_desc[irq].handler->set_affinity(irq, new_value);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- v2.4.4/linux/arch/ppc/kernel/local_irq.h	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/local_irq.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.local_irq.h 1.7 05/17/01 18:14:21 cort
+ */
 
 #ifndef _PPC_KERNEL_LOCAL_IRQ_H
 #define _PPC_KERNEL_LOCAL_IRQ_H
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c
--- v2.4.4/linux/arch/ppc/kernel/m8260_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/m8260_setup.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
- *
+ * BK Id: SCCS/s.m8260_setup.c 1.15 05/17/01 18:14:21 cort
+ */
+/*
  *  linux/arch/ppc/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
@@ -119,7 +120,7 @@
 	return(0);
 }
 
-unsigned long __init
+unsigned long
 m8260_get_rtc_time(void)
 {
 
@@ -206,6 +207,18 @@
 
 }
 
+/*
+ * Same hack as 8xx
+ */
+unsigned long __init m8260_find_end_of_memory(void)
+{
+	bd_t	*binfo;
+	extern unsigned char __res[];
+	
+	binfo = (bd_t *)__res;
+
+	return binfo->bi_memsize;
+}
 
 void __init
 m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -248,18 +261,8 @@
 	ppc_md.get_rtc_time   = m8260_get_rtc_time;
 	ppc_md.calibrate_decr = m8260_calibrate_decr;
 
-#if 0
-	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-	ppc_md.kbd_pretranslate  = pckbd_pretranslate;
-	ppc_md.kbd_translate     = pckbd_translate;
-	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-#endif
-#else
+	ppc_md.find_end_of_memory = m8260_find_end_of_memory;
+
 	ppc_md.kbd_setkeycode    = NULL;
 	ppc_md.kbd_getkeycode    = NULL;
 	ppc_md.kbd_translate     = NULL;
@@ -268,7 +271,6 @@
 	ppc_md.kbd_init_hw       = NULL;
 #ifdef CONFIG_MAGIC_SYSRQ
 	ppc_md.kbd_sysrq_xlate	 = NULL;
-#endif
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- v2.4.4/linux/arch/ppc/kernel/m8xx_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
- *
+ * BK Id: SCCS/s.m8xx_setup.c 1.17 05/18/01 07:54:04 patch
+ */
+/*
  *  linux/arch/ppc/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
@@ -107,11 +108,17 @@
 ide_pio_timings_t ide_pio_clocks[6];
 
 /* Make clock cycles and always round up */
-#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
+#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
 
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 #endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
 
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
+#endif
+
 extern char saved_command_line[256];
 
 extern unsigned long find_available_memory(void);
@@ -200,7 +207,7 @@
 	/* Processor frequency is MHz.
 	 * The value 'fp' is the number of decrementer ticks per second.
 	 */
-	fp = (binfo->bi_intfreq * 1000000) / 16;
+	fp = binfo->bi_intfreq / 16;
 	freq = fp*60;	/* try to make freq/1e6 an integer */
         divisor = 60;
         printk("Decrementer Frequency = %d/%d\n", freq, divisor);
@@ -308,10 +315,10 @@
 
 	bp = (bd_t *)__res;
 			
-	len += sprintf(len+buffer,"clock\t\t: %ldMHz\n"
-		       "bus clock\t: %ldMHz\n",
-		       bp->bi_intfreq /*/ 1000000*/,
-		       bp->bi_busfreq /*/ 1000000*/);
+	len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+		       "bus clock\t: %dMHz\n",
+		       bp->bi_intfreq / 1000000,
+		       bp->bi_busfreq / 1000000);
 
 	return len;
 }
@@ -358,7 +365,7 @@
 #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	ide_insw(port, buf, ns);
 #else
-	ide_insw(port+_IO_BASE, buf, ns);
+	_insw_ns((unsigned short *)(port+_IO_BASE), buf, ns);
 #endif
 }
 
@@ -368,7 +375,7 @@
 #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	ide_outsw(port, buf, ns);
 #else
-	ide_outsw(port+_IO_BASE, buf, ns);
+	_outsw_ns((unsigned short *)(port+_IO_BASE), buf, ns);
 #endif
 }
 
@@ -381,7 +388,7 @@
 	
 	return (ioport_dsc[base].irq);
 #else
-        return 14;
+        return 9;
 #endif
 }
 
@@ -398,11 +405,7 @@
 		       const char *device,
 		       void *dev_id)
 {
-#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	return request_8xxirq(irq, handler, flags, device, dev_id);
-#else
-	return request_irq(irq, handler, flags, device, dev_id);
-#endif
 }
 
 /* We can use an external IDE controller
@@ -413,16 +416,14 @@
 void m8xx_ide_init_hwif_ports(hw_regs_t *hw,
 	ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t *p = hw->io_ports;
 	int i;
 #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+	ide_ioreg_t *p = hw->io_ports;
 	volatile pcmconf8xx_t	*pcmp;
 
 	static unsigned long pcmcia_base = 0;
-#else
-	ide_ioreg_t port = data_port;	/* ??? XXX ??? XXX */
-#endif
 	unsigned long base;
+#endif
 
 #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	*p = 0;
@@ -500,12 +501,15 @@
 	
 	/* Just a regular IDE drive on some I/O port.
 	*/
-	i = 8;
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
-	if (irq != NULL)
-		*irq = 0;
+	if (data_port == 0)
+		return;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+		hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+
+	hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+        return;
+
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 }
 #endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
@@ -523,7 +527,6 @@
 #define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length	*/
 #endif
 
-
 /* Calculate PIO timings */
 static void
 m8xx_ide_tuneproc(ide_drive_t *drive, byte pio)
@@ -581,9 +584,27 @@
 
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 #endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
-
 /* -------------------------------------------------------------------- */
 
+/*
+ * This is a big hack right now, but it may turn into something real
+ * someday.
+ *
+ * For the 8xx boards (at this time anyway), there is nothing to initialize
+ * associated the PROM.  Rather than include all of the prom.c
+ * functions in the image just to get prom_init, all we really need right
+ * now is the initialization of the physical memory region.
+ */
+unsigned long __init m8xx_find_end_of_memory(void)
+{
+	bd_t	*binfo;
+	extern unsigned char __res[];
+	
+	binfo = (bd_t *)__res;
+
+	return binfo->bi_memsize;
+}
+
 void __init
 m8xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	 unsigned long r6, unsigned long r7)
@@ -629,18 +650,8 @@
 	ppc_md.get_rtc_time   = m8xx_get_rtc_time;
 	ppc_md.calibrate_decr = m8xx_calibrate_decr;
 
-#if 0
-	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-	ppc_md.kbd_pretranslate  = pckbd_pretranslate;
-	ppc_md.kbd_translate     = pckbd_translate;
-	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-#endif
-#else
+	ppc_md.find_end_of_memory = m8xx_find_end_of_memory;
+
 	ppc_md.kbd_setkeycode    = NULL;
 	ppc_md.kbd_getkeycode    = NULL;
 	ppc_md.kbd_translate     = NULL;
@@ -648,8 +659,7 @@
 	ppc_md.kbd_leds          = NULL;
 	ppc_md.kbd_init_hw       = NULL;
 #ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.kbd_sysrq_xlate	 = NULL;
-#endif
+	ppc_md.ppc_kbd_sysrq_xlate	 = NULL;
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.4.4/linux/arch/ppc/kernel/misc.S	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/misc.S	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.misc.S 1.16 05/17/01 18:14:21 cort
+ */
+/*
  * This file contains miscellaneous low-level functions.
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *
@@ -21,20 +24,6 @@
 #include <asm/cache.h>
 #include "ppc_asm.h"
 
-#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
-#define CACHE_LINE_SIZE		16
-#define LG_CACHE_LINE_SIZE	4
-#define MAX_COPY_PREFETCH	1
-#elif !defined(CONFIG_PPC64BRIDGE)
-#define CACHE_LINE_SIZE		32
-#define LG_CACHE_LINE_SIZE	5
-#define MAX_COPY_PREFETCH	4
-#else
-#define CACHE_LINE_SIZE		128
-#define LG_CACHE_LINE_SIZE	7
-#define MAX_COPY_PREFETCH	1
-#endif /* CONFIG_4xx || CONFIG_8xx */
-
 	.text
 
 	.align	5
@@ -60,14 +49,37 @@
 	mtlr	r0
 	blr
 
-/* void __no_use_save_flags(unsigned long *flags) */
-_GLOBAL(__no_use_save_flags)
+/* void __save_flags_ptr(unsigned long *flags) */
+_GLOBAL(__save_flags_ptr)
 	mfmsr	r4
 	stw	r4,0(r3)
 	blr
+	/* 
+	 * Need these nops here for taking over save/restore to
+	 * handle lost intrs
+	 * -- Cort
+	 */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__save_flags_ptr_end)
 
-/* void __no_use_restore_flags(unsigned long flags) */	
-_GLOBAL(__no_use_restore_flags)
+/* void __restore_flags(unsigned long flags) */	
+_GLOBAL(__restore_flags)
 /*
  * Just set/clear the MSR_EE bit through restore/flags but do not
  * change anything else.  This is needed by the RT system and makes
@@ -82,66 +94,95 @@
 	 /* Check if things are setup the way we want _already_. */
 	cmpw	0,r3,r4
 	beqlr
-	/* are we enabling interrupts? */
-	rlwinm.	r0,r3,0,16,16
-	beq	1f
-	/* if so, check if there are any lost interrupts */
-	lis	r7,ppc_n_lost_interrupts@ha
-	lwz	r7,ppc_n_lost_interrupts@l(r7)
-	cmpi	0,r7,0		/* lost interrupts to process first? */
-	bne-	do_lost_interrupts
 1:	SYNC
 	mtmsr	r3
 	SYNC
 	blr
-	
-_GLOBAL(__no_use_cli)
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__restore_flags_end)
+
+_GLOBAL(__cli)
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r3,r0,16+1,32-1,31	/* Extract old value of 'EE' */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
 	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
 	blr			/* Done */
+	/* 
+	 * Need these nops here for taking over save/restore to
+	 * handle lost intrs
+	 * -- Cort
+	 */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__cli_end)
 
-_GLOBAL(__no_use_sti)
-	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
+_GLOBAL(__sti)
 	mfmsr	r3		/* Get current state */
 	ori	r3,r3,MSR_EE	/* Turn on 'EE' bit */
-	cmpi	0,r4,0		/* lost interrupts to process first? */
-	bne-	do_lost_interrupts
 	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r3		/* Update machine state */
 	blr
-
-/*
- * We were about to enable interrupts but we have to simulate
- * some interrupts that were lost by enable_irq first.
- */
-_GLOBAL(do_lost_interrupts)
-	stwu	r1,-16(r1)
-	mflr	r0
-	stw	r0,20(r1)
-	stw	r3,8(r1)
-1:	bl	fake_interrupt
-	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
-	cmpi	0,r4,0
-	bne-	1b
-	lwz	r3,8(r1)
-	SYNC
-	mtmsr	r3
-	lwz	r0,20(r1)
-	mtlr	r0
-	addi	r1,r1,16
-	blr
+	/* 
+	 * Need these nops here for taking over save/restore to
+	 * handle lost intrs
+	 * -- Cort
+	 */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__sti_end)
 
 
 /*
  * complement mask on the msr then "or" some values on.
  *     _nmask_and_or_msr(nmask, value_to_or)
  */
-	_GLOBAL(_nmask_and_or_msr)
+_GLOBAL(_nmask_and_or_msr)
 	mfmsr	r0		/* Get current msr */
 	andc	r0,r0,r3	/* And off the bits set in r3 (first parm) */
 	or	r0,r0,r4		/* Or on the bits in r4 (second parm) */
@@ -267,6 +308,7 @@
 2:	icbi	0,r6
 	addi	r6,r6,CACHE_LINE_SIZE
 	bdnz	2b
+	sync				/* additional sync needed on g4 */
 	isync
 	blr
 
@@ -1283,7 +1325,7 @@
 	.long sys_vfork
 	.long sys_getrlimit	/* 190 */
 	.long sys_ni_syscall		/* 191 */	/* Unused */
-	.long sys_ni_syscall		/* 192 - reserved - mmap2 */
+	.long sys_mmap2			/* 192 */
 	.long sys_truncate64		/* 193 */
 	.long sys_ftruncate64		/* 194 */
 	.long sys_stat64		/* 195 */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
--- v2.4.4/linux/arch/ppc/kernel/mk_defs.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/mk_defs.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mk_defs.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  * This program is used to generate definitions needed by
  * assembly language modules.
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/mol.h linux/arch/ppc/kernel/mol.h
--- v2.4.4/linux/arch/ppc/kernel/mol.h	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/mol.h	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-/* 
- *   arch/ppc/kernel/mol.h
- *   
- *	<mol.h>
- *	
- *	Mac-on-Linux hook macros
- *	<http://www.maconlinux.org>
- *   
- *   Copyright (C) 2000 Samuel Rydh (samuel@ibrium.se)
- *   
- *   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
- *   
- */
-
-#ifndef _PPC_KERNEL_MOL
-#define _PPC_KERNEL_MOL
-
-#include <linux/config.h>
-
-#ifdef CONFIG_MOL
-#define MOL_INTERFACE_VERSION		3
-
-#define MOL_HOOK(hook_num)					\
-	lwz	r0,(mol_interface + 4 * hook_num + 4)@l(0); 	\
-	cmpwi	cr1,r0,0; 					\
-	beq+	cr1,777f; 					\
-	mtctr	r0; 						\
-	bctrl; 							\
-777:	lwz	r0,GPR0(r21)
-
-#define MOL_HOOK_RESTORE(hook_num)				\
-	mfcr	r2;						\
-	MOL_HOOK(hook_num);					\
-	mtcrf	0x80,r2;					\
-	lwz	r2,_CTR(r21);					\
-	mtctr	r2;						\
-	lwz	r2,GPR2(r21)
-
-#define MOL_HOOK_MMU(hook_num, scr)				\
-	lis	scr,(mol_interface + 4 * hook_num + 4)@ha;	\
-	lwz	scr,(mol_interface + 4 * hook_num + 4)@l(scr);	\
-	cmpwi	cr1,scr,0;					\
-	beq+	cr1,778f;					\
-	mtctr	scr;						\
-	bctrl;							\
-778:
-
-#define MOL_HOOK_TLBMISS(hook_num)				\
-	lwz	r0,(mol_interface + 4 * hook_num + 4)@l(0);	\
-	cmpwi	r0,0;						\
-	beq+	779f;						\
-	mflr	r3;						\
-	mtlr	r0;						\
-	blrl;							\
-	mtlr	r3;						\
-779:
-
-#else
-#define MOL_HOOK(num)
-#define MOL_HOOK_RESTORE(num)
-#define MOL_HOOK_MMU(num, scr)
-#define MOL_HOOK_TLBMISS(num)
-#endif
-
-
-#endif   /* _PPC_KERNEL_MOL */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c
--- v2.4.4/linux/arch/ppc/kernel/oak_setup.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/oak_setup.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.oak_setup.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  *
  *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/oak_setup.h linux/arch/ppc/kernel/oak_setup.h
--- v2.4.4/linux/arch/ppc/kernel/oak_setup.h	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/kernel/oak_setup.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.oak_setup.h 1.5 05/17/01 18:14:21 cort
+ */
+/*
  *
  *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.4.4/linux/arch/ppc/kernel/open_pic.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/open_pic.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.open_pic.c 1.20 05/17/01 18:14:21 cort
+ */
+/*
  *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
  *
  *  Copyright (C) 1997 Geert Uytterhoeven
@@ -775,11 +778,17 @@
 int
 openpic_get_irq(struct pt_regs *regs)
 {
+/*
+ * Clean up needed. -VAL
+ */
+#ifndef CONFIG_GEMINI
 	extern int i8259_irq(int cpu);
-
+#endif
 	int irq = openpic_irq();
 
 	/* Management of the cascade should be moved out of here */
+
+	/* Yep - because openpic !=> i8259, for one thing. -VAL */
         if (open_pic_irq_offset && irq == open_pic_irq_offset)
         {
                 /*
@@ -787,8 +796,10 @@
                  */
 		if ( chrp_int_ack_special )
 			irq = *chrp_int_ack_special;
+#ifndef CONFIG_GEMINI
 		else
 			irq = i8259_irq( smp_processor_id() );
+#endif
 		openpic_eoi();
         }
 	if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) {
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
--- v2.4.4/linux/arch/ppc/kernel/open_pic.h	Wed Jan 24 15:28:36 2001
+++ linux/arch/ppc/kernel/open_pic.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.open_pic.h 1.8 05/17/01 18:14:21 cort
+ */
+/*
  *  arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
  *
  *  Copyright (C) 1997 Geert Uytterhoeven
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/open_pic_defs.h linux/arch/ppc/kernel/open_pic_defs.h
--- v2.4.4/linux/arch/ppc/kernel/open_pic_defs.h	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/open_pic_defs.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.open_pic_defs.h 1.7 05/17/01 18:14:21 cort
+ */
+/*
  *  linux/openpic.h -- OpenPIC definitions
  *
  *  Copyright (C) 1997 Geert Uytterhoeven
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pci-dma.c linux/arch/ppc/kernel/pci-dma.c
--- v2.4.4/linux/arch/ppc/kernel/pci-dma.c	Mon Feb 14 15:34:21 2000
+++ linux/arch/ppc/kernel/pci-dma.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.pci-dma.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
  *
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.4.4/linux/arch/ppc/kernel/pci.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/pci.c	Mon May 21 17:04:47 2001
@@ -1,5 +1,7 @@
 /*
- * $Id: pci.c,v 1.64 1999/09/17 18:01:53 cort Exp $
+ * BK Id: SCCS/s.pci.c 1.21 05/21/01 01:31:30 cort
+ */
+/*
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
@@ -385,6 +387,8 @@
 	return 0;
 }
 
+static int next_controller_index;
+
 struct pci_controller * __init
 pcibios_alloc_controller(void)
 {
@@ -396,9 +400,15 @@
 	*hose_tail = hose;
 	hose_tail = &hose->next;
 
+	hose->index = next_controller_index++;
+
 	return hose;
 }
 
+#ifdef CONFIG_ALL_PPC
+/*
+ * Functions below are used on OpenFirmware machines.
+ */
 static void
 make_one_node_map(struct device_node* node, u8 pci_bus)
 {
@@ -579,6 +589,95 @@
 }
 
 void __init
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			   struct device_node *dev, int primary)
+{
+	unsigned int *ranges, *prev;
+	int rlen = 0;
+	int memno = 0;
+	struct resource *res;
+	int np, na = prom_n_addr_cells(dev);
+	np = na + 5;
+
+	/* First we try to merge ranges to fix a problem with some pmacs
+	 * that can have more than 3 ranges, fortunately using contiguous
+	 * addresses -- BenH
+	 */
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	prev = NULL;
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		if (prev) {
+			if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
+				(prev[2] + prev[na+4]) == ranges[2] &&
+				(prev[na+2] + prev[na+4]) == ranges[na+2]) {
+				prev[na+4] += ranges[na+4];
+				ranges[0] = 0;
+				ranges += np;
+				continue;
+			}
+		}
+		prev = ranges;
+		ranges += np;
+	}
+
+	/*
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 2:	a PCI address
+	 *   cells 3 or 3+4:	a CPU physical address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cells 4+5 or 5+6:	the size of the range
+	 */
+	rlen = 0;
+	hose->io_base_phys = 0;
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		res = NULL;
+		switch (ranges[0] >> 24) {
+		case 1:		/* I/O space */
+			if (ranges[2] != 0)
+				break;
+			hose->io_base_phys = ranges[na+2];
+			hose->io_base_virt = ioremap(ranges[na+2], ranges[na+4]);
+			if (primary)
+				isa_io_base = (unsigned long) hose->io_base_virt;
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			res->start = ranges[2];
+			break;
+		case 2:		/* memory space */
+			memno = 0;
+			if (ranges[1] == 0 && ranges[2] == 0
+			    && ranges[na+4] <= (16 << 20)) {
+				/* 1st 16MB, i.e. ISA memory area */
+				if (primary)
+					isa_mem_base = ranges[na+2];
+				memno = 1;
+			}
+			while (memno < 3 && hose->mem_resources[memno].flags)
+				++memno;
+			if (memno == 0)
+				hose->pci_mem_offset = ranges[na+2] - ranges[2];
+			if (memno < 3) {
+				res = &hose->mem_resources[memno];
+				res->flags = IORESOURCE_MEM;
+				res->start = ranges[na+2];
+			}
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->end = res->start + ranges[na+4] - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+		ranges += np;
+	}
+}
+#endif /* CONFIG_ALL_PPC */
+
+void __init
 pcibios_init(void)
 {
 	struct pci_controller *hose;
@@ -632,9 +731,6 @@
 	/* OF fails to initialize IDE controllers on macs
 	 * (and maybe other machines)
 	 * 
-	 * This late fixup is done here since I want it to happen after
-	 * resource assignement, and there's no "late-init" arch hook
-	 * 
 	 * Ideally, this should be moved to the IDE layer, but we need
 	 * to check specifically with Andre Hedrick how to do it cleanly
 	 * since the common IDE code seem to care about the fact that the
@@ -651,6 +747,9 @@
 		}
 	}
 #endif /* CONFIG_BLK_DEV_IDE */
+
+	if (ppc_md.pcibios_after_init)
+		ppc_md.pcibios_after_init();
 }
 
 int __init
@@ -802,6 +901,143 @@
 	/* We may want to do something with IOs here... */
 	return res->start;
 #endif	
+}
+
+/*
+ * Return the index of the PCI controller for device pdev.
+ */
+int pci_controller_num(struct pci_dev *dev)
+{
+	struct pci_controller *hose = (struct pci_controller *) dev->sysdata;
+
+	return hose->index;
+}
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ *  -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static __inline__ int
+__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+		       enum pci_mmap_state mmap_state)
+{
+	struct pci_controller *hose = (struct pci_controller *) dev->sysdata;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long io_offset = 0;
+	int i, res_bit;
+
+	if (hose == 0)
+		return -EINVAL;		/* should never happen */
+
+	/* If memory, add on the PCI bridge address offset */
+	if (mmap_state == pci_mmap_mem) {
+		offset += hose->pci_mem_offset;
+		res_bit = IORESOURCE_MEM;
+	} else {
+		io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+		offset += io_offset;
+		res_bit = IORESOURCE_IO;
+	}
+
+	/*
+	 * Check that the offset requested corresponds to one of the
+	 * resources of the device.
+	 */
+	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+		struct resource *rp = &dev->resource[i];
+		int flags = rp->flags;
+
+		/* treat ROM as memory (should be already) */
+		if (i == PCI_ROM_RESOURCE)
+			flags |= IORESOURCE_MEM;
+
+		/* Active and same type? */
+		if ((flags & res_bit) == 0)
+			continue;
+
+		/* In the range of this resource? */
+		if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
+			continue;
+
+		/* found it! construct the final physical address */
+		if (mmap_state == pci_mmap_io)
+			offset += hose->io_base_phys - io_offset;
+
+		vma->vm_pgoff = offset >> PAGE_SHIFT;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
+ * mapping.
+ */
+static __inline__ void
+__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+		     enum pci_mmap_state mmap_state)
+{
+	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static __inline__ void
+__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+		      enum pci_mmap_state mmap_state, int write_combine)
+{
+	int prot = pgprot_val(vma->vm_page_prot);
+
+	/* XXX would be nice to have a way to ask for write-through */
+	prot |= _PAGE_NO_CACHE;
+	if (!write_combine)
+		prot |= _PAGE_GUARDED;
+	vma->vm_page_prot = __pgprot(prot);
+}
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture.  The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state,
+			int write_combine)
+{
+	int ret;
+
+	ret = __pci_mmap_make_offset(dev, vma, mmap_state);
+	if (ret < 0)
+		return ret;
+
+	__pci_mmap_set_flags(dev, vma, mmap_state);
+	__pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
+
+	ret = remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
+			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+	return ret;
 }
 
 /* Obsolete functions. Should be removed once the symbios driver
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pci.h linux/arch/ppc/kernel/pci.h
--- v2.4.4/linux/arch/ppc/kernel/pci.h	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/pci.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pci.h 1.7 05/17/01 18:14:21 cort
+ */
 
 #ifndef __PPC_KERNEL_PCI_H__
 #define __PPC_KERNEL_PCI_H__
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_backlight.c linux/arch/ppc/kernel/pmac_backlight.c
--- v2.4.4/linux/arch/ppc/kernel/pmac_backlight.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/pmac_backlight.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.pmac_backlight.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  * Miscellaneous procedures for dealing with the PowerMac hardware.
  * Contains support for the backlight.
  * 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_nvram.c linux/arch/ppc/kernel/pmac_nvram.c
--- v2.4.4/linux/arch/ppc/kernel/pmac_nvram.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/pmac_nvram.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.pmac_nvram.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  * Miscellaneous procedures for dealing with the PowerMac hardware.
  */
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.4.4/linux/arch/ppc/kernel/pmac_pci.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/pmac_pci.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.pmac_pci.c 1.14 05/17/01 18:14:21 cort
+ */
+/*
  * Support for PCI bridges found on Power Macintoshes.
  * At present the "bandit" and "chaos" bridges are supported.
  * Fortunately you access configuration space in the same
@@ -24,13 +27,12 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
+#include <asm/feature.h>
 
 #include "pci.h"
 
 #undef DEBUG
 
-extern void process_bridge_ranges(struct pci_controller *hose,
-				  struct device_node *dev, int primary);
 static void add_bridges(struct device_node *dev);
 
 /* XXX Could be per-controller, but I don't think we risk anything by
@@ -382,17 +384,6 @@
 	hose->ops = &macrisc_pci_ops;
 	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
 	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = addr->address;
-	/* is 0x10000 enough for io space ? */
-	hose->io_base_virt = (void *)ioremap(addr->address, 0x10000);
-
-	/* XXX This is the bridge with the PCI expansion bus. We route
-	 * legacy IOs to it.
-	 */
-	if (addr->address == 0xf2000000)
-		isa_io_base = (unsigned long)hose->io_base_virt;
-#endif
 	/* We "know" that the bridge at f2000000 has the PCI slots. */
 	return addr->address == 0xf2000000;
 }
@@ -405,10 +396,6 @@
 		ioremap(addr->address + 0x800000, 0x1000);
 	hose->cfg_data = (volatile unsigned char *)
 		ioremap(addr->address + 0xc00000, 0x1000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = addr->address;
-	hose->io_base_virt = (void *) ioremap(addr->address, 0x10000);
-#endif
 	init_bandit(hose);
 }
 
@@ -421,23 +408,12 @@
 		ioremap(addr->address + 0x800000, 0x1000);
 	hose->cfg_data = (volatile unsigned char *)
 		ioremap(addr->address + 0xc00000, 0x1000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = addr->address;
-	hose->io_base_virt = (void *) ioremap(addr->address, 0x10000);
-#endif
 }
 
 void __init
 setup_grackle(struct pci_controller *hose, unsigned io_space_size)
 {
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = 0xfe000000;
-	hose->io_base_virt = (void *) ioremap(0xfe000000, io_space_size);
-	pci_dram_offset = 0;
-	isa_mem_base = 0xfd000000;
-	isa_io_base = (unsigned long) hose->io_base_virt;
-#endif
 	if (machine_is_compatible("AAPL,PowerBook1998"))
 		grackle_set_loop_snoop(hose, 1);
 #if 0	/* Disabled for now, HW problems ??? */
@@ -505,7 +481,7 @@
 		
 		/* Interpret the "ranges" property */
 		/* This also maps the I/O region and sets isa_io/mem_base */
-		process_bridge_ranges(hose, dev, primary);
+		pci_process_bridge_OF_ranges(hose, dev, primary);
 
 		/* Fixup "bus-range" OF property */
 		fixup_bus_range(dev);
@@ -557,19 +533,56 @@
 	pcibios_fixup_OF_interrupts();
 }
 
-/* We don't want to enable USB controllers absent from the OF tree
- * (iBook second controller)
- */
 int
 pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
 {
+	struct device_node* node;
+
+	node = pci_device_to_OF_node(dev);
+
+	/* We don't want to enable USB controllers absent from the OF tree
+	 * (iBook second controller)
+	 */
 	if (dev->vendor == PCI_VENDOR_ID_APPLE
-	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB) {
-		struct device_node* node;
-		node = pci_device_to_OF_node(dev);
-		if (!node)
-			return -EINVAL;
+	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node)
+		return -EINVAL;
+		
+	/* Firewire was disabled after PCI probe, the driver is claiming it,
+	 * so we must re-enable it now, at least until the driver can do it
+	 * itself.
+	 */
+	if (node && !strcmp(node->name, "firewire") && 
+	    device_is_compatible(node, "pci106b,18")) {
+		feature_set_firewire_cable_power(node, 1);
+		feature_set_firewire_power(node, 1);
 	}
+	
 	return 0;
+}
+
+/* We power down some devices after they have been probed. They'll
+ * be powered back on later on
+ */
+void
+pmac_pcibios_after_init(void)
+{
+	struct device_node* nd;
+
+	nd = find_devices("firewire");
+	while (nd) {
+		if (nd->parent && device_is_compatible(nd, "pci106b,18")
+		    && device_is_compatible(nd->parent, "uni-north")) {
+			feature_set_firewire_power(nd, 0);
+			feature_set_firewire_cable_power(nd, 0);
+		}
+		nd = nd->next;
+	}
+	nd = find_devices("ethernet");
+	while (nd) {
+		if (nd->parent && device_is_compatible(nd, "gmac")
+		    && device_is_compatible(nd->parent, "uni-north"))
+			feature_set_gmac_power(nd, 0);
+		nd = nd->next;
+	}
 }
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.4.4/linux/arch/ppc/kernel/pmac_pic.c	Fri Feb 16 16:02:34 2001
+++ linux/arch/ppc/kernel/pmac_pic.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pmac_pic.c 1.14 05/17/01 18:14:21 cort
+ */
 #include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/init.h>
@@ -10,6 +13,7 @@
 #include <asm/smp.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
+#include <asm/time.h>
 
 #include "pmac_pic.h"
 #include "open_pic.h"
@@ -44,10 +48,12 @@
  * since it can lose interrupts (see pmac_set_irq_mask).
  * -- Cort
  */
-void __pmac __no_use_set_lost(unsigned long irq_nr)
+void __pmac __set_lost(unsigned long irq_nr)
 {
-	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts))
+	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
 		atomic_inc(&ppc_n_lost_interrupts);
+		set_dec(1);
+	}
 }
 
 static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
@@ -373,7 +379,6 @@
 		irqctrler = NULL;
 	}
 
-	int_control.int_set_lost = __no_use_set_lost;
 	/*
 	 * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
 	 * 1998 G3 Series PowerBooks have 128, 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_pic.h linux/arch/ppc/kernel/pmac_pic.h
--- v2.4.4/linux/arch/ppc/kernel/pmac_pic.h	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/kernel/pmac_pic.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pmac_pic.h 1.5 05/17/01 18:14:21 cort
+ */
 #ifndef _PPC_KERNEL_PMAC_PIC_H
 #define _PPC_KERNEL_PMAC_PIC_H
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.4.4/linux/arch/ppc/kernel/pmac_setup.c	Tue Mar  6 19:28:35 2001
+++ linux/arch/ppc/kernel/pmac_setup.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.pmac_setup.c 1.21 05/17/01 18:14:21 cort
+ */
+/*
  *  linux/arch/ppc/kernel/setup.c
  *
  *  PowerPC version 
@@ -66,6 +69,7 @@
 #include <asm/time.h>
 #include "local_irq.h"
 #include "pmac_pic.h"
+#include "../mm/mem_pieces.h"
 
 #undef SHOW_GATWICK_IRQS
 
@@ -102,6 +106,9 @@
 extern void pmac_nvram_update(void);
 
 extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern void pmac_pcibios_after_init(void);
+
+struct device_node *memory_node;
 
 unsigned char drive_info;
 
@@ -470,7 +477,7 @@
 	char *p;
 
 	/* Do nothing if the root has been set already. */
-	if ((goodness < current_root_goodness) &&
+	if ((goodness <= current_root_goodness) &&
 		(ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE)))
 		return;
 	p = strstr(saved_command_line, "root=");
@@ -635,6 +642,88 @@
 #endif
 #endif
 
+/*
+ * Read in a property describing some pieces of memory.
+ */
+
+static void __init get_mem_prop(char *name, struct mem_pieces *mp)
+{
+	struct reg_property *rp;
+	int i, s;
+	unsigned int *ip;
+	int nac = prom_n_addr_cells(memory_node);
+	int nsc = prom_n_size_cells(memory_node);
+
+	ip = (unsigned int *) get_property(memory_node, name, &s);
+	if (ip == NULL) {
+		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
+		       name);
+		abort();
+	}
+	s /= (nsc + nac) * 4;
+	rp = mp->regions;
+	for (i = 0; i < s; ++i, ip += nac+nsc) {
+		if (nac >= 2 && ip[nac-2] != 0)
+			continue;
+		rp->address = ip[nac-1];
+		if (nsc >= 2 && ip[nac+nsc-2] != 0)
+			rp->size = ~0U;
+		else
+			rp->size = ip[nac+nsc-1];
+		++rp;
+	}
+	mp->n_regions = rp - mp->regions;
+
+	/* Make sure the pieces are sorted. */
+	mem_pieces_sort(mp);
+	mem_pieces_coalesce(mp);
+}
+
+/*
+ * On systems with Open Firmware, collect information about
+ * physical RAM and which pieces are already in use.
+ * At this point, we have (at least) the first 8MB mapped with a BAT.
+ * Our text, data, bss use something over 1MB, starting at 0.
+ * Open Firmware may be using 1MB at the 4MB point.
+ */
+unsigned long __init pmac_find_end_of_memory(void)
+{
+	unsigned long a, total;
+	struct mem_pieces phys_mem;
+
+	memory_node = find_devices("memory");
+	if (memory_node == NULL) {
+		printk(KERN_ERR "can't find memory node\n");
+		abort();
+	}
+
+	/*
+	 * Find out where physical memory is, and check that it
+	 * starts at 0 and is contiguous.  It seems that RAM is
+	 * always physically contiguous on Power Macintoshes.
+	 *
+	 * Supporting discontiguous physical memory isn't hard,
+	 * it just makes the virtual <-> physical mapping functions
+	 * more complicated (or else you end up wasting space
+	 * in mem_map).
+	 */
+	get_mem_prop("reg", &phys_mem);
+	if (phys_mem.n_regions == 0)
+		panic("No RAM??");
+	a = phys_mem.regions[0].address;
+	if (a != 0)
+		panic("RAM doesn't start at physical address 0");
+	total = phys_mem.regions[0].size;
+
+	if (phys_mem.n_regions > 1) {
+		printk("RAM starting at 0x%x is not contiguous\n",
+		       phys_mem.regions[1].address);
+		printk("Using RAM from 0 to 0x%lx\n", total-1);
+	}
+
+	return total;
+}
+
 void __init
 pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	  unsigned long r6, unsigned long r7)
@@ -656,6 +745,7 @@
 	
 	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
 	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
+	ppc_md.pcibios_after_init = pmac_pcibios_after_init;
 
 	ppc_md.restart        = pmac_restart;
 	ppc_md.power_off      = pmac_power_off;
@@ -665,6 +755,8 @@
 	ppc_md.set_rtc_time   = pmac_set_rtc_time;
 	ppc_md.get_rtc_time   = pmac_get_rtc_time;
 	ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
 
 #ifdef CONFIG_VT
 #ifdef CONFIG_INPUT
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- v2.4.4/linux/arch/ppc/kernel/pmac_time.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/pmac_time.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.pmac_time.c 1.8 05/17/01 18:14:21 cort
+ */
+/*
  * Support for periodic interrupts (100 per second) and for getting
  * the current time from the RTC on Power Macintoshes.
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc-stub.c linux/arch/ppc/kernel/ppc-stub.c
--- v2.4.4/linux/arch/ppc/kernel/ppc-stub.c	Sun Oct  1 20:35:15 2000
+++ linux/arch/ppc/kernel/ppc-stub.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
-/* $Id: ppc-stub.c,v 1.6 1999/08/12 22:18:11 cort Exp $
+/*
+ * BK Id: SCCS/s.ppc-stub.c 1.6 05/17/01 18:14:21 cort
+ */
+/*
  * ppc-stub.c:  KGDB support for the Linux kernel.
  *
  * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc4xx_pic.c linux/arch/ppc/kernel/ppc4xx_pic.c
--- v2.4.4/linux/arch/ppc/kernel/ppc4xx_pic.c	Tue Jan 11 21:49:26 2000
+++ linux/arch/ppc/kernel/ppc4xx_pic.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ppc4xx_pic.c 1.5 05/17/01 18:14:21 cort
+ */
+/*
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc4xx_pic.h linux/arch/ppc/kernel/ppc4xx_pic.h
--- v2.4.4/linux/arch/ppc/kernel/ppc4xx_pic.h	Mon Jan 10 18:25:32 2000
+++ linux/arch/ppc/kernel/ppc4xx_pic.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ppc4xx_pic.h 1.5 05/17/01 18:14:21 cort
+ */
+/*
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc8260_pic.c linux/arch/ppc/kernel/ppc8260_pic.c
--- v2.4.4/linux/arch/ppc/kernel/ppc8260_pic.c	Sat Nov 11 18:14:38 2000
+++ linux/arch/ppc/kernel/ppc8260_pic.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc8260_pic.c 1.5 05/17/01 18:14:21 cort
+ */
 
 #include <linux/stddef.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc8260_pic.h linux/arch/ppc/kernel/ppc8260_pic.h
--- v2.4.4/linux/arch/ppc/kernel/ppc8260_pic.h	Tue May  2 13:05:40 2000
+++ linux/arch/ppc/kernel/ppc8260_pic.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc8260_pic.h 1.7 05/17/01 18:14:21 cort
+ */
 
 #ifndef _PPC_KERNEL_PPC8260_H
 #define _PPC_KERNEL_PPC8260_H
@@ -8,8 +11,7 @@
 
 void m8260_pic_init(void);
 void m8260_do_IRQ(struct pt_regs *regs,
-                 int            cpu,
-                 int            isfake);
+                 int            cpu);
 int m8260_get_irq(struct pt_regs *regs);
 
 #endif /* _PPC_KERNEL_PPC8260_H */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc8xx_pic.c linux/arch/ppc/kernel/ppc8xx_pic.c
--- v2.4.4/linux/arch/ppc/kernel/ppc8xx_pic.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/ppc8xx_pic.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc8xx_pic.c 1.10 05/17/01 18:14:21 cort
+ */
 #include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/init.h>
@@ -67,8 +70,7 @@
 #if 0
 void
 m8xx_do_IRQ(struct pt_regs *regs,
-	   int            cpu,
-           int            isfake)
+	   int            cpu)
 {
 	int irq;
         unsigned long bits = 0;
@@ -158,13 +160,15 @@
 	 */
 	switch (irq) {
 #ifdef	IDE0_INTERRUPT
-	case IDE0_INTERRUPT:		/* fall through */
+		case IDE0_INTERRUPT:	/* IDE0 */
+			return (request_8xxirq(irq, handler, irqflags, devname,
+						dev_id));
 #endif
 #ifdef	IDE1_INTERRUPT
-	case IDE1_INTERRUPT:		/* fall through */
+		case IDE1_INTERRUPT:	/* IDE1 */
+			return (request_8xxirq(irq, handler, irqflags, devname,
+						dev_id));
 #endif
-		return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
-	
 	default:			/* unknown IRQ -> panic */
 		panic("request_irq");
 	}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc8xx_pic.h linux/arch/ppc/kernel/ppc8xx_pic.h
--- v2.4.4/linux/arch/ppc/kernel/ppc8xx_pic.h	Fri Nov 12 04:29:47 1999
+++ linux/arch/ppc/kernel/ppc8xx_pic.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc8xx_pic.h 1.7 05/17/01 18:14:21 cort
+ */
 #ifndef _PPC_KERNEL_PPC8xx_H
 #define _PPC_KERNEL_PPC8xx_H
 
@@ -8,8 +11,7 @@
 
 void m8xx_pic_init(void);
 void m8xx_do_IRQ(struct pt_regs *regs,
-                 int            cpu,
-                 int            isfake);
+                 int            cpu);
 int m8xx_get_irq(struct pt_regs *regs);
 
 #ifdef CONFIG_MBX
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h
--- v2.4.4/linux/arch/ppc/kernel/ppc_asm.h	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/ppc_asm.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ppc_asm.h 1.10 05/17/01 18:14:21 cort
+ */
+/*
  * arch/ppc/kernel/ppc_asm.h
  *
  * Definitions used by various bits of low-level assembly code on PowerPC.
@@ -130,3 +133,22 @@
 #define MTMSRD(r)	mtmsr	r
 #define CLR_TOP32(r)
 #endif /* CONFIG_PPC64BRIDGE */
+
+/*
+ * Defines for cache-line size etc.
+ */
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
+#define CACHE_LINE_SIZE		16
+#define LG_CACHE_LINE_SIZE	4
+#define MAX_COPY_PREFETCH	1
+
+#elif !defined(CONFIG_PPC64BRIDGE)
+#define CACHE_LINE_SIZE		32
+#define LG_CACHE_LINE_SIZE	5
+#define MAX_COPY_PREFETCH	4
+
+#else
+#define CACHE_LINE_SIZE		128
+#define LG_CACHE_LINE_SIZE	7
+#define MAX_COPY_PREFETCH	1
+#endif /* CONFIG_4xx || CONFIG_8xx */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.4.4/linux/arch/ppc/kernel/ppc_htab.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/ppc_htab.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: ppc_htab.c,v 1.29 1999/09/10 05:05:50 paulus Exp $
- *
+ * BK Id: SCCS/s.ppc_htab.c 1.8 05/17/01 18:14:21 cort
+ */
+/*
  * PowerPC hash table management proc entry.  Will show information
  * about the current hash table and will allow changes to it.
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.4.4/linux/arch/ppc/kernel/ppc_ksyms.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc_ksyms.c 1.31 05/18/01 08:18:10 patch
+ */
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/threads.h>
@@ -55,12 +58,11 @@
 
 extern void transfer_to_handler(void);
 extern void syscall_trace(void);
-extern void do_IRQ(struct pt_regs *regs, int isfake);
+extern void do_IRQ(struct pt_regs *regs);
 extern void MachineCheckException(struct pt_regs *regs);
 extern void AlignmentException(struct pt_regs *regs);
 extern void ProgramCheckException(struct pt_regs *regs);
 extern void SingleStepException(struct pt_regs *regs);
-extern void do_lost_interrupts(unsigned long);
 extern int do_signal(sigset_t *, struct pt_regs *);
 extern int pmac_newworld;
 extern int sys_sigreturn(struct pt_regs *regs);
@@ -83,7 +85,6 @@
 EXPORT_SYMBOL(sys_sigreturn);
 EXPORT_SYMBOL(ppc_n_lost_interrupts);
 EXPORT_SYMBOL(ppc_lost_interrupts);
-EXPORT_SYMBOL(do_lost_interrupts);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(disable_irq_nosync);
@@ -92,20 +93,13 @@
 EXPORT_SYMBOL(kernel_flag);
 #endif /* CONFIG_SMP */
 
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-EXPORT_SYMBOL_NOVERS(isa_io_base);
-EXPORT_SYMBOL_NOVERS(isa_mem_base);
-EXPORT_SYMBOL_NOVERS(pci_dram_offset);
-#endif
 EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
 EXPORT_SYMBOL_NOVERS(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
-#ifndef CONFIG_8xx
 #if defined(CONFIG_ALL_PPC)
 EXPORT_SYMBOL(_prep_type);
 EXPORT_SYMBOL(ucSystemType);
 #endif
-#endif
 
 #if !__INLINE_BITOPS
 EXPORT_SYMBOL(set_bit);
@@ -175,6 +169,9 @@
 #endif
 
 #ifdef CONFIG_PCI
+EXPORT_SYMBOL_NOVERS(isa_io_base);
+EXPORT_SYMBOL_NOVERS(isa_mem_base);
+EXPORT_SYMBOL_NOVERS(pci_dram_offset);
 EXPORT_SYMBOL(pci_alloc_consistent);
 EXPORT_SYMBOL(pci_free_consistent);
 #endif /* CONFIG_PCI */
@@ -216,9 +213,6 @@
 EXPORT_SYMBOL(synchronize_irq);
 #endif
 
-#ifndef CONFIG_MACH_SPECIFIC
-EXPORT_SYMBOL(_machine);
-#endif
 EXPORT_SYMBOL(ppc_md);
 
 #ifdef CONFIG_ADB
@@ -249,10 +243,9 @@
 EXPORT_SYMBOL(set_backlight_enable);
 EXPORT_SYMBOL(register_backlight_controller);
 #endif /* CONFIG_PMAC_BACKLIGHT */
-#ifndef CONFIG_MACH_SPECIFIC
-EXPORT_SYMBOL_NOVERS(have_of);
-#endif /* CONFIG_MACH_SPECIFIC */
 #if defined(CONFIG_ALL_PPC)
+EXPORT_SYMBOL(_machine);
+EXPORT_SYMBOL_NOVERS(have_of);
 EXPORT_SYMBOL_NOVERS(sys_ctrler);
 EXPORT_SYMBOL(find_devices);
 EXPORT_SYMBOL(find_type_devices);
@@ -277,9 +270,11 @@
 EXPORT_SYMBOL(feature_clear);
 EXPORT_SYMBOL(feature_test);
 EXPORT_SYMBOL(feature_set_gmac_power);
-EXPORT_SYMBOL(feature_set_gmac_phy_reset);
+EXPORT_SYMBOL(feature_gmac_phy_reset);
 EXPORT_SYMBOL(feature_set_usb_power);
 EXPORT_SYMBOL(feature_set_firewire_power);
+EXPORT_SYMBOL(feature_set_firewire_cable_power);
+EXPORT_SYMBOL(feature_set_airport_power);
 #endif /* defined(CONFIG_ALL_PPC) */
 #if defined(CONFIG_BOOTX_TEXT)
 EXPORT_SYMBOL(bootx_update_display);
@@ -314,7 +309,14 @@
 #endif
 
 EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(int_control);
+EXPORT_SYMBOL(__sti);
+EXPORT_SYMBOL(__sti_end);
+EXPORT_SYMBOL(__cli);
+EXPORT_SYMBOL(__cli_end);
+EXPORT_SYMBOL(__save_flags_ptr);
+EXPORT_SYMBOL(__save_flags_ptr_end);
+EXPORT_SYMBOL(__restore_flags);
+EXPORT_SYMBOL(__restore_flags_end);
 EXPORT_SYMBOL(timer_interrupt_intercept);
 EXPORT_SYMBOL(timer_interrupt);
 EXPORT_SYMBOL(do_IRQ_intercept);
@@ -331,9 +333,6 @@
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__down_trylock);
-EXPORT_SYMBOL(down_read_failed);
-EXPORT_SYMBOL(down_write_failed);
 
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
 extern void (*debugger)(struct pt_regs *regs);
@@ -362,6 +361,8 @@
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
 EXPORT_SYMBOL(mmu_context_overflow);
+EXPORT_SYMBOL(flush_hash_page); /* For MOL */
+EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
 EXPORT_SYMBOL_NOVERS(disarm_decr);
 #if !defined(CONFIG_8xx) && !defined(CONFIG_4xx)
 extern long *intercept_table;
@@ -369,17 +370,3 @@
 #endif
 extern long *ret_from_intercept;
 EXPORT_SYMBOL(ret_from_intercept);
-
-#ifdef CONFIG_MOL
-extern ulong mol_interface[];
-extern PTE *Hash;
-extern unsigned long Hash_mask;
-extern void (*ret_from_except)(void);
-extern struct task_struct *last_task_used_altivec;
-EXPORT_SYMBOL_NOVERS(mol_interface);
-EXPORT_SYMBOL(Hash);
-EXPORT_SYMBOL(Hash_mask);
-EXPORT_SYMBOL(handle_mm_fault);
-EXPORT_SYMBOL(last_task_used_math);
-EXPORT_SYMBOL(ret_from_except);
-#endif /* CONFIG_MOL */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c
--- v2.4.4/linux/arch/ppc/kernel/prep_nvram.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/prep_nvram.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.prep_nvram.c 1.9 05/17/01 18:14:22 cort
+ */
+/*
  *  linux/arch/ppc/kernel/prep_nvram.c
  *
  *  Copyright (C) 1998  Corey Minyard
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.4.4/linux/arch/ppc/kernel/prep_pci.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/prep_pci.c	Mon May 21 17:04:47 2001
@@ -1,5 +1,7 @@
 /*
- * $Id: prep_pci.c,v 1.40 1999/09/17 17:23:05 cort Exp $
+ * BK Id: SCCS/s.prep_pci.c 1.18 05/17/01 18:14:22 cort
+ */
+/*
  * PReP pci functions.
  * Originally by Gary Thomas
  * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -437,8 +439,8 @@
 
 static char ibm8xx_pci_IRQ_routes[] __prepdata = {
         0,      /* Line 0 - unused */
-        13,     /* Line 1 */
-        10,     /* Line 2 */
+        15,     /* Line 1 */
+        15,     /* Line 2 */
         15,     /* Line 3 */
         15,     /* Line 4 */
 };
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.4.4/linux/arch/ppc/kernel/prep_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/prep_setup.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.prep_setup.c 1.20 05/21/01 09:19:50 trini
+ */
+/*
  *  linux/arch/ppc/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
@@ -103,6 +106,17 @@
 extern int probingmem;
 extern unsigned long loops_per_jiffy;
 
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
+#endif
+
+#ifdef CONFIG_SOUND_MODULE
+EXPORT_SYMBOL(ppc_cs4232_dma);
+EXPORT_SYMBOL(ppc_cs4232_dma2);
+#endif
+
 int __prep
 prep_get_cpuinfo(char *buffer)
 {
@@ -246,7 +260,16 @@
 	case _PREP_Motorola:
 		/* Enable L2.  Assume we don't need to flush -- Cort*/
 		*(unsigned char *)(0x8000081c) |= 3;
-		ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
+#ifdef CONFIG_BLK_DEV_INITRD
+		if (initrd_start)
+			ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
+		else
+#endif
+#ifdef CONFIG_ROOT_NFS
+			ROOT_DEV = to_kdev_t(0x00ff); /* /dev/nfs */
+#else
+			ROOT_DEV = to_kdev_t(0x0802); /* /dev/sda2 */
+#endif
 		break;
 	}
 
@@ -313,6 +336,8 @@
 	vgacon_remap_base = 0xf0000000;
 	/*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
         conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
 #endif
 }
 
@@ -504,8 +529,8 @@
 	__cli();
 
 	__asm__ __volatile__("\n\
-	mtspr   26, %1  /* SRR0 */
-	mtspr   27, %0  /* SRR1 */
+	mtspr   26, %1  /* SRR0 */	\n\
+	mtspr   27, %0  /* SRR1 */	\n\
 	rfi"
 	:
 	: "r" (defaultmsr), "r" (jumpaddr));
@@ -575,7 +600,7 @@
 
 #if 0
 void __prep
-prep_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
+prep_do_IRQ(struct pt_regs *regs, int cpu)
 {
         int irq;
 
@@ -691,6 +716,35 @@
 }
 #endif
 
+/*
+ * This finds the amount of physical ram and does necessary
+ * setup for prep.  This is pretty architecture specific so
+ * this will likely stay separate from the pmac.
+ * -- Cort
+ */
+unsigned long __init prep_find_end_of_memory(void)
+{
+	unsigned long total;
+#ifdef CONFIG_PREP_RESIDUAL	
+	total = res->TotalMemory;
+#else
+	total = 0;
+#endif	
+
+	if (total == 0 )
+	{
+		/*
+		 * I need a way to probe the amount of memory if the residual
+		 * data doesn't contain it. -- Cort
+		 */
+		printk("Ramsize from residual data was 0 -- Probing for value\n");
+		total = 0x02000000;
+		printk("Ramsize default to be %ldM\n", total>>20);
+	}
+
+	return (total);
+}
+
 unsigned long *MotSave_SmpIar;
 unsigned char *MotSave_CpusState[2];
 
@@ -730,6 +784,14 @@
 	}
 #endif
 
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 	/* Copy cmd_line parameters */
 	if ( r6)
 	{
@@ -750,7 +812,8 @@
 	{
 		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
 			_prep_type = _PREP_IBM;
-		_prep_type = _PREP_Motorola;
+		else
+			_prep_type = _PREP_Motorola;
 	}
 	else /* assume motorola if no residual (netboot?) */
 #endif	  
@@ -784,6 +847,8 @@
 		ppc_md.time_init      = mk48t59_init;
 	}
 
+	ppc_md.find_end_of_memory = prep_find_end_of_memory;
+
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
         ppc_ide_md.insw = prep_ide_insw;
         ppc_ide_md.outsw = prep_ide_outsw;
@@ -810,8 +875,3 @@
 #endif
 #endif
 }
-
-#ifdef CONFIG_SOUND_MODULE
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
--- v2.4.4/linux/arch/ppc/kernel/prep_time.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/prep_time.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.prep_time.c 1.7 05/17/01 18:14:22 cort
+ */
+/*
  *  linux/arch/i386/kernel/time.c
  *
  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
@@ -30,6 +33,8 @@
 
 #include <asm/time.h>
 
+extern spinlock_t rtc_lock;
+
 /*
  * The motorola uses the m48t18 rtc (includes DS1643) whose registers
  * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
@@ -55,6 +60,7 @@
 	unsigned char save_control, save_freq_select;
 	struct rtc_time tm;
 
+	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
 
 	/* tell the clock it's being set */
@@ -92,6 +98,7 @@
 	 */
 	CMOS_WRITE(save_control,     RTC_CONTROL);
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
 
 	return 0;
 }
@@ -149,7 +156,7 @@
 	unsigned char save_control;
 	struct rtc_time tm;
 
-
+	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
 
 	/* tell the clock it's being written */
@@ -175,6 +182,7 @@
 	
 	/* Turn off the write bit. */
 	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+	spin_unlock(&rtc_lock);
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/proc_rtas.c linux/arch/ppc/kernel/proc_rtas.c
--- v2.4.4/linux/arch/ppc/kernel/proc_rtas.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/proc_rtas.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.proc_rtas.c 1.5 05/17/01 18:14:22 cort
+ */
+/*
  *   arch/ppc/kernel/proc_rtas.c
  *   Copyright (C) 2000 Tilmann Bitterberg
  *   (tilmann@bitterberg.de)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.4.4/linux/arch/ppc/kernel/process.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/process.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: process.c,v 1.97 1999/09/14 19:07:42 cort Exp $
- *
+ * BK Id: SCCS/s.process.c 1.15 05/17/01 18:14:22 cort
+ */
+/*
  *  linux/arch/ppc/kernel/process.c
  *
  *  Derived from "arch/i386/kernel/process.c"
@@ -378,45 +379,6 @@
 }
 
 /*
- * XXX ld.so expects the auxiliary table to start on
- * a 16-byte boundary, so we have to find it and
- * move it up. :-(
- */
-static inline void shove_aux_table(unsigned long sp)
-{
-	int argc;
-	char *p;
-	unsigned long e;
-	unsigned long aux_start, offset;
-
-	if (__get_user(argc, (int *)sp))
-		return;
-	sp += sizeof(int) + (argc + 1) * sizeof(char *);
-	/* skip over the environment pointers */
-	do {
-		if (__get_user(p, (char **)sp))
-			return;
-		sp += sizeof(char *);
-	} while (p != NULL);
-	aux_start = sp;
-	/* skip to the end of the auxiliary table */
-	do {
-		if (__get_user(e, (unsigned long *)sp))
-			return;
-		sp += 2 * sizeof(unsigned long);
-	} while (e != AT_NULL);
-	offset = ((aux_start + 15) & ~15) - aux_start;
-	if (offset != 0) {
-		do {
-			sp -= sizeof(unsigned long);
-			if (__get_user(e, (unsigned long *)sp)
-			    || __put_user(e, (unsigned long *)(sp + offset)))
-				return;
-		} while (sp > aux_start);
-	}
-}
-
-/*
  * Set up a thread for executing a new program
  */
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
@@ -425,7 +387,6 @@
 	regs->nip = nip;
 	regs->gpr[1] = sp;
 	regs->msr = MSR_USER;
-	shove_aux_table(sp);
 	if (last_task_used_math == current)
 		last_task_used_math = 0;
 	if (last_task_used_altivec == current)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.4.4/linux/arch/ppc/kernel/prom.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/prom.c	Thu May 24 15:03:05 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: prom.c,v 1.79 1999/10/08 01:56:32 paulus Exp $
- *
+ * BK Id: SCCS/s.prom.c 1.20 05/23/01 00:38:42 cort
+ */
+/*
  * Procedures for interfacing to the Open Firmware PROM on
  * Power Macintosh computers.
  *
@@ -31,7 +32,7 @@
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/bitops.h>
-/* for openpic_to_irq */
+#include <asm/bootinfo.h>
 #include "open_pic.h"
 
 #ifdef CONFIG_FB
@@ -182,26 +183,6 @@
 #endif
 unsigned long dev_tree_size;
 
-/*
- * prom_init() is called very early on, before the kernel text
- * and data have been mapped to KERNELBASE.  At this point the code
- * is running at whatever address it has been loaded at, so
- * references to extern and static variables must be relocated
- * explicitly.  The procedure reloc_offset() returns the address
- * we're currently running at minus the address we were linked at.
- * (Note that strings count as static variables.)
- *
- * Because OF may have mapped I/O devices into the area starting at
- * KERNELBASE, particularly on CHRP machines, we can't safely call
- * OF once the kernel has been mapped to KERNELBASE.  Therefore all
- * OF calls should be done within prom_init(), and prom_init()
- * and all routines called within it must be careful to relocate
- * references as necessary.
- */
-#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
-#define PTRUNRELOC(x)	((typeof(x))((unsigned long)(x) - offset))
-#define RELOC(x)	(*PTRRELOC(&(x)))
-
 #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
 
 /* Is boot-info compatible ? */
@@ -616,30 +597,10 @@
 	char *p, *d;
 	int prom_version = 0;
  	unsigned long phys;
-	extern char __bss_start, _end;
-
-	/* First zero the BSS -- use memset, some arches don't have
-	 * caches on yet */
-	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
 
  	/* Default */
  	phys = offset + KERNELBASE;
 
-	/* check if we're apus, return if we are */
-	if ( r3 == 0x61707573 )
-		return phys;
-
-	/* If we came here from BootX, clear the screen,
-	 * set up some pointers and return. */
-	if (r3 == 0x426f6f58 && pp == NULL) {
-		bootx_init(r4, phys);
-		return phys;
-	}
-
-	/* check if we're prep, return if we are */
-	if ( *(unsigned long *)(0) == 0xdeadc0de )
-		return phys;
-
 	/* First get a handle for the stdout device */
 	RELOC(prom) = pp;
 	RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1,
@@ -757,14 +718,9 @@
 		setup_disp_fake_bi(RELOC(prom_disp_node));
 #endif
 
-	/* If pmac, then use quiesce call. We can't rely on prom_version
-	 * since some old iMacs appear to have an incorrect /openprom/model
-	 * entry in the device tree
-	 */
-	if (!chrp) {
-		prom_print(RELOC("Calling quiesce ...\n"));
-		call_prom(RELOC("quiesce"), 0, 0);
-	}
+	/* Use quiesce call to get OF to shut down any devices it's using */
+	prom_print(RELOC("Calling quiesce ...\n"));
+	call_prom(RELOC("quiesce"), 0, 0);
 
 #ifdef CONFIG_BOOTX_TEXT
 	if (!chrp && RELOC(disp_bi)) {
@@ -839,7 +795,7 @@
 	    __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags));
 	    prom_drawhex(flags);
 	}
-	if (pvr == 8 || pvr == 12) {
+	if (pvr == 8 || pvr == 12 || pvr == 0x800c) {
 	    prom_drawstring(RELOC("\nICTC             : 0x"));
 	    __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags));
 	    prom_drawhex(flags);
@@ -986,9 +942,11 @@
 			prom_print(RELOC("... failed\n"));
 		} else {
 			prom_print(RELOC("... ok\n"));
-
-			/* Setup a useable color table when the appropriate
-			 * method is available. Should update this to set-colors */
+			/*
+			 * Setup a usable color table when the appropriate
+			 * method is available.
+			 * Should update this to use set-colors.
+			 */
 			for (i = 0; i < 32; i++)
 				if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
 						   RELOC(default_colors)[i*3+1],
@@ -1267,7 +1225,10 @@
 
 	np->name = get_property(np, "name", 0);
 	np->type = get_property(np, "device_type", 0);
-
+#if 0
+	np->n_addr_cells = naddrc;
+	np->n_size_cells = nsizec;
+#endif
 	/* get the device addresses and interrupts */
 	if (ifunc != NULL) {
 		mem_start = ifunc(np, mem_start, naddrc, nsizec);
@@ -1283,6 +1244,16 @@
 	ip = (int *) get_property(np, "#size-cells", 0);
 	if (ip != NULL)
 		nsizec = *ip;
+#if 0
+	if (np->parent == NULL) {
+		/*
+		 * Set the n_addr/size_cells on the root to its
+		 * own values, rather than 0.
+		 */
+		np->n_addr_cells = naddrc;
+		np->n_size_cells = nsizec;
+	}
+#endif	
 
 	/* the f50 sets the name to 'display' and 'compatible' to what we
 	 * expect for the name -- Cort
@@ -1497,6 +1468,34 @@
 	}
 }
 
+int
+prom_n_addr_cells(struct device_node* np)
+{
+	int* ip;
+	do {
+		if (np->parent)
+			np = np->parent;
+		ip = (int *) get_property(np, "#address-cells", 0);
+		if (ip != NULL)
+			return *ip;
+	} while(np->parent);
+	return 0;
+}
+
+int
+prom_n_size_cells(struct device_node* np)
+{
+	int* ip;
+	do {
+		if (np->parent)
+			np = np->parent;
+		ip = (int *) get_property(np, "#size-cells", 0);
+		if (ip != NULL)
+			return *ip;
+	} while(np->parent);
+	return 0;
+}
+
 __init
 static unsigned long
 interpret_pci_props(struct device_node *np, unsigned long mem_start,
@@ -1566,6 +1565,8 @@
 	}
 
 	ip = (int *) get_property(np, "AAPL,interrupts", &l);
+	if (ip == 0 && np->parent)
+		ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
 	if (ip == 0)
 		ip = (int *) get_property(np, "interrupts", &l);
 	if (ip != 0) {
@@ -1761,7 +1762,7 @@
 		i = 0;
 		adr = (struct address_range *) mem_start;
 		while ((l -= rpsize) >= 0) {
-			adr[i].space = 0;
+			adr[i].space = (naddrc >= 2? rp[naddrc-2]: 0);
 			adr[i].address = rp[naddrc - 1];
 			adr[i].size = rp[naddrc + nsizec - 1];
 			++i;
@@ -1978,12 +1979,13 @@
 {
 	struct property *pp;
 
-	for (pp = np->properties; pp != 0; pp = pp->next)
-		if (strcmp(pp->name, name) == 0) {
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		if (name && strcmp(pp->name, name) == 0) {
 			if (lenp != 0)
 				*lenp = pp->length;
 			return pp->value;
 		}
+	}
 	return 0;
 }
 
@@ -2161,9 +2163,10 @@
 {
 	if (disp_bi == 0)
 		return;
-	/* check it's the same frame buffer (within 16MB) */
-	if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xff000000)
+	/* check it's the same frame buffer (within 64MB) */
+	if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) {
 		return;
+	}
 
 	disp_bi->dispDeviceBase = (__u8 *) phys;
 	disp_bi->dispDeviceRect[0] = 0;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.4.4/linux/arch/ppc/kernel/ptrace.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/ptrace.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ptrace.c 1.5 05/17/01 18:14:22 cort
+ */
+/*
  *  linux/arch/ppc/kernel/ptrace.c
  *
  *  PowerPC version
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/qspan_pci.c linux/arch/ppc/kernel/qspan_pci.c
--- v2.4.4/linux/arch/ppc/kernel/qspan_pci.c	Tue May  2 13:05:40 2000
+++ linux/arch/ppc/kernel/qspan_pci.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.qspan_pci.c 1.5 05/17/01 18:14:22 cort
+ */
+/*
  * QSpan pci routines.
  * Most 8xx boards use the QSpan PCI bridge.  The config address register
  * is located 0x500 from the base of the bridge control/status registers.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- v2.4.4/linux/arch/ppc/kernel/residual.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/residual.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: residual.c,v 1.17 1999/09/27 18:40:23 cort Exp $
- *
+ * BK Id: SCCS/s.residual.c 1.7 05/17/01 18:14:22 cort
+ */
+/*
  * Code to deal with the PReP residual data.
  *
  * Written by: Cort Dougan (cort@cs.nmt.edu)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c
--- v2.4.4/linux/arch/ppc/kernel/semaphore.c	Tue Apr 17 17:19:25 2001
+++ linux/arch/ppc/kernel/semaphore.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: semaphore.c,v 1.1 1999/08/31 15:11:44 cort Exp $
- *
+ * BK Id: SCCS/s.semaphore.c 1.12 05/17/01 18:14:22 cort
+ */
+/*
  * PowerPC-specific semaphore code.
  *
  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
@@ -9,131 +10,122 @@
  * 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.
+ *
+ * April 2001 - Reworked by Paul Mackerras <paulus@samba.org>
+ * to eliminate the SMP races in the old version between the updates
+ * of `count' and `waking'.  Now we use negative `count' values to
+ * indicate that some process(es) are waiting for the semaphore.
  */
 
 #include <linux/sched.h>
-
+#include <asm/atomic.h>
 #include <asm/semaphore.h>
-#include <asm/semaphore-helper.h>
 
 /*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
  *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
- *
- * This routine adds one to the count of processes that need to
- * wake up and exit.  ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore.  The others will go back
- * to sleep.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
+ *	old_count = sem->count;
+ *	tmp = MAX(old_count, 0) + incr;
+ *	sem->count = tmp;
+ *	return old_count;
  */
+static inline int __sem_update_count(struct semaphore *sem, int incr)
+{
+	int old_count, tmp;
+
+	__asm__ __volatile__("\n"
+"1:	lwarx	%0,0,%3\n"
+"	srawi	%1,%0,31\n"
+"	andc	%1,%0,%1\n"
+"	add	%1,%1,%4\n"
+"	stwcx.	%1,0,%3\n"
+"	bne	1b"
+	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+	: "r" (&sem->count), "r" (incr), "m" (sem->count)
+	: "cc");
+
+	return old_count;
+}
+
 void __up(struct semaphore *sem)
 {
-	wake_one_more(sem);
+	/*
+	 * Note that we incremented count in up() before we came here,
+	 * but that was ineffective since the result was <= 0, and
+	 * any negative value of count is equivalent to 0.
+	 * This ends up setting count to 1, unless count is now > 0
+	 * (i.e. because some other cpu has called up() in the meantime),
+	 * in which case we just increment count.
+	 */
+	__sem_update_count(sem, 1);
 	wake_up(&sem->wait);
 }
 
 /*
- * Perform the "down" function.  Return zero for semaphore acquired,
- * return negative for signalled out of the function.
- *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible.  This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return.  If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
- *
- * Either form may be used in conjunction with "up()".
- *
+ * Note that when we come in to __down or __down_interruptible,
+ * we have already decremented count, but that decrement was
+ * ineffective since the result was < 0, and any negative value
+ * of count is equivalent to 0.
+ * Thus it is only when we decrement count from some value > 0
+ * that we have actually got the semaphore.
  */
+void __down(struct semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
 
-#define DOWN_VAR				\
-	struct task_struct *tsk = current;	\
-	wait_queue_t wait;			\
-	init_waitqueue_entry(&wait, tsk);
-
-#define DOWN_HEAD(task_state)						\
-									\
-									\
-	tsk->state = (task_state);					\
-	add_wait_queue(&sem->wait, &wait);				\
-									\
-	/*								\
-	 * Ok, we're set up.  sem->count is known to be less than zero	\
-	 * so we must wait.						\
-	 *								\
-	 * We can let go the lock for purposes of waiting.		\
-	 * We re-acquire it after awaking so as to protect		\
-	 * all semaphore operations.					\
-	 *								\
-	 * If "up()" is called before we call waking_non_zero() then	\
-	 * we will catch it right away.  If it is called later then	\
-	 * we will have to go through a wakeup cycle to catch it.	\
-	 *								\
-	 * Multiple waiters contend for the semaphore lock to see	\
-	 * who gets to gate through and who has to wait some more.	\
-	 */								\
-	for (;;) {
-
-#define DOWN_TAIL(task_state)			\
-		tsk->state = (task_state);	\
-	}					\
-	tsk->state = TASK_RUNNING;		\
+	tsk->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+	smp_wmb();
+
+	/*
+	 * Try to get the semaphore.  If the count is > 0, then we've
+	 * got the semaphore; we decrement count and exit the loop.
+	 * If the count is 0 or negative, we set it to -1, indicating
+	 * that we are asleep, and then sleep.
+	 */
+	while (__sem_update_count(sem, -1) <= 0) {
+		schedule();
+		tsk->state = TASK_UNINTERRUPTIBLE;
+	}
 	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
 
-void __down(struct semaphore * sem)
-{
-	DOWN_VAR
-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
-	if (waking_non_zero(sem))
-		break;
-	schedule();
-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+	/*
+	 * If there are any more sleepers, wake one of them up so
+	 * that it can either get the semaphore, or set count to -1
+	 * indicating that there are still processes sleeping.
+	 */
+	wake_up(&sem->wait);
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-	int ret = 0;
-	DOWN_VAR
-	DOWN_HEAD(TASK_INTERRUPTIBLE)
-
-	ret = waking_non_zero_interruptible(sem, tsk);
-	if (ret)
-	{
-		if (ret == 1)
-			/* ret != 0 only if we get interrupted -arca */
-			ret = 0;
-		break;
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	tsk->state = TASK_INTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+	smp_wmb();
+
+	while (__sem_update_count(sem, -1) <= 0) {
+		if (signal_pending(current)) {
+			/*
+			 * A signal is pending - give up trying.
+			 * Set sem->count to 0 if it is negative,
+			 * since we are no longer sleeping.
+			 */
+			__sem_update_count(sem, 0);
+			retval = -EINTR;
+			break;
+		}
+		schedule();
+		tsk->state = TASK_INTERRUPTIBLE;
 	}
-	schedule();
-	DOWN_TAIL(TASK_INTERRUPTIBLE)
-	return ret;
-}
-
-int __down_trylock(struct semaphore * sem)
-{
-	return waking_non_zero_trylock(sem);
+	tsk->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+	wake_up(&sem->wait);
+	return retval;
 }
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.4.4/linux/arch/ppc/kernel/setup.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/setup.c	Thu May 24 15:03:05 2001
@@ -1,5 +1,7 @@
 /*
- * $Id: setup.c,v 1.160 1999/10/08 01:56:38 paulus Exp $
+ * BK Id: SCCS/s.setup.c 1.32 05/23/01 00:38:42 cort
+ */
+/*
  * Common prep/pmac/chrp boot and setup code.
  */
 
@@ -73,6 +75,16 @@
                       unsigned long r6,
                       unsigned long r7);
 
+extern void gemini_init(unsigned long r3,
+                      unsigned long r4,
+                      unsigned long r5,
+                      unsigned long r6,
+                      unsigned long r7);
+
+
+extern void bootx_init(unsigned long r4, unsigned long phys);
+extern unsigned long reloc_offset(void);
+
 #ifdef CONFIG_XMON
 extern void xmon_map_scc(void);
 #endif
@@ -80,23 +92,16 @@
 extern boot_infos_t *boot_infos;
 char saved_command_line[256];
 unsigned char aux_device_present;
-struct int_control_struct int_control =
-{
-	__no_use_cli,
-	__no_use_sti,
-	__no_use_restore_flags,
-	__no_use_save_flags
-};
 struct ide_machdep_calls ppc_ide_md;
 int parse_bootinfo(void);
 
 unsigned long ISA_DMA_THRESHOLD;
 unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
 
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
 int _machine = 0;
 int have_of = 0;
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
 
 #ifdef CONFIG_MAGIC_SYSRQ
 unsigned long SYSRQ_KEY;
@@ -412,7 +417,7 @@
 	return len;
 }
 
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
 void __init
 intuit_machine_type(void)
 {
@@ -434,7 +439,80 @@
 		}
 	}
 }
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
+
+#ifdef CONFIG_6xx
+/*
+ * We're called here very early in the boot.  We determine the machine
+ * type and call the appropriate low-level setup functions.
+ *  -- Cort <cort@fsmlabs.com>
+ */
+__init
+unsigned long
+early_init(int r3, int r4, int r5)
+{
+	extern char __bss_start, _end;
+ 	unsigned long phys;
+	unsigned long offset = reloc_offset();
+	unsigned long local_have_of = 1, local_machine;
+	struct bi_record *rec;
+	
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
+	
+#if defined(CONFIG_APUS)
+	return phys;
+#endif	
+	
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+#if defined(CONFIG_ALL_PPC) || defined(CONFIG_GEMINI)
+	/* If we came here from BootX, clear the screen,
+	 * set up some pointers and return. */
+#if defined(CONFIG_ALL_PPC)	
+	if ((r3 == 0x426f6f58) && (r5 == 0)) {
+		bootx_init(r4, phys);
+		return phys;
+	}
+#endif
+
+	/* check if we're prep, return if we are */
+	if ( *(unsigned long *)(0) == 0xdeadc0de )
+		return phys;
+	
+	/*
+	 * See if we have any bootloader info passed along.  If we do,
+	 * get the machine type and find out if we have OF.
+	 *
+	 * The strategy here is to assume that we want to call prom_init()
+	 * unless the bootinfo data passed to us tell us that we don't
+	 * have OF.
+	 * -- Cort <cort@fsmlabs.com>
+	 */
+	rec = (struct bi_record *)_ALIGN((ulong)PTRRELOC(&__bss_start)+(1<<20)-1,(1<<20));
+	if ( rec->tag == BI_FIRST )
+	{
+		for ( ; rec->tag != BI_LAST ;
+		      rec = (struct bi_record *)((ulong)rec + rec->size) )
+		{
+			ulong *data = rec->data;
+			if ( rec->tag == BI_MACHTYPE )
+			{
+				local_machine = data[0];
+				local_have_of = data[1];
+			}
+		}
+	}
+
+	if ( local_have_of )
+		phys = prom_init( r3, r4, (prom_entry)r5);
+#endif	
+	
+	return phys;
+}
+#endif /* CONFIG_6xx */
 
 /*
  * Find out what kind of machine we're on and save any data we need
@@ -448,36 +526,26 @@
 
 	if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
 	
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
 	/* if we didn't get any bootinfo telling us what we are... */
 	if ( _machine == 0 )
 	{
-		/* boot loader will tell us if we're APUS */
-		if ( r3 == 0x61707573 )
-		{
-			_machine = _MACH_apus;
-			r3 = 0;
-		}
 		/* prep boot loader tells us if we're prep or not */
-		else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
+		if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
 		{
 			_machine = _MACH_prep;
 		} else
 			have_of = 1;
 	}
-#endif /* CONFIG_MACH_SPECIFIC */
 
 	if ( have_of )
 	{
 		/* prom_init has already been called from __start */
 		if (boot_infos)
 			relocate_nodes();
-#ifndef CONFIG_MACH_SPECIFIC
 		/* we need to set _machine before calling finish_device_tree */
 		if (_machine == 0)
 			intuit_machine_type();
-#endif /* CONFIG_MACH_SPECIFIC */
 		finish_device_tree();
 		/*
 		 * If we were booted via quik, r3 points to the physical
@@ -489,13 +557,12 @@
 		 * are used for initrd_start and initrd_size,
 		 * otherwise they contain 0xdeadbeef.  
 		 */
-		cmd_line[0] = 0;
 		if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
 			strncpy(cmd_line, (char *)r3 + KERNELBASE,
 				sizeof(cmd_line));
 		} else if (boot_infos != 0) {
 			/* booted by BootX - check for ramdisk */
-			if (boot_infos->kernelParamsOffset != 0)
+ 			if (boot_infos->kernelParamsOffset != 0)
 				strncpy(cmd_line, (char *) boot_infos
 					+ boot_infos->kernelParamsOffset,
 					sizeof(cmd_line));
@@ -526,13 +593,17 @@
 			chosen = find_devices("chosen");
 			if (chosen != NULL) {
 				p = get_property(chosen, "bootargs", NULL);
-				if (p != NULL)
+				if (p && *p) {
+					cmd_line[0] = 0;
 					strncpy(cmd_line, p, sizeof(cmd_line));
+				}
 			}
 		}
 		cmd_line[sizeof(cmd_line) - 1] = 0;
 	}
+#endif /* CONFIG_ALL_PPC */
 
+#if defined(CONFIG_ALL_PPC)
 	switch (_machine)
 	{
 	case _MACH_Pmac:
@@ -544,22 +615,14 @@
 	case _MACH_chrp:
                 chrp_init(r3, r4, r5, r6, r7);
 		break;
-#ifdef CONFIG_APUS
-	case _MACH_apus:
-                apus_init(r3, r4, r5, r6, r7);
-		break;
-#endif
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
-
-	/* Check for nobats option (used in mapin_ram). */
-	if (strstr(cmd_line, "nobats")) {
-		extern int __map_without_bats;
-		__map_without_bats = 1;
-	}
-#else
-#if defined(CONFIG_4xx)
+#elif defined(CONFIG_APUS)
+	apus_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_GEMINI)
+	gemini_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_4xx)
 	oak_init(r3, r4, r5, r6, r7);
 #elif defined(CONFIG_8xx)
         m8xx_init(r3, r4, r5, r6, r7);
@@ -567,8 +630,15 @@
         m8260_init(r3, r4, r5, r6, r7);
 #else
 #error "No board type has been defined for identify_machine()!"
-#endif /* CONFIG_4xx */
-#endif /* !CONFIG_4xx && !CONFIG_8xx */
+#endif
+
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
+	/* Check for nobats option (used in mapin_ram). */
+	if (strstr(cmd_line, "nobats")) {
+		extern int __map_without_bats;
+		__map_without_bats = 1;
+	}
+#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_8260 */
 
 	/* Look for mem= option on command line */
 	if (strstr(cmd_line, "mem=")) {
@@ -639,12 +709,12 @@
 			initrd_end = data[0] + rec->size;
 			break;
 #endif /* CONFIG_BLK_DEV_INITRD */
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
 		case BI_MACHTYPE:
 			_machine = data[0];
 			have_of = data[1];
 			break;
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
 		}
 	}
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.4.4/linux/arch/ppc/kernel/signal.c	Wed Jan 24 15:21:19 2001
+++ linux/arch/ppc/kernel/signal.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.signal.c 1.7 05/17/01 18:14:22 cort
+ */
+/*
  *  linux/arch/ppc/kernel/signal.c
  *
  *  PowerPC version 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S
--- v2.4.4/linux/arch/ppc/kernel/sleep.S	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/kernel/sleep.S	Mon May 21 17:04:47 2001
@@ -1,6 +1,9 @@
 /*
+ * BK Id: SCCS/s.sleep.S 1.7 05/17/01 18:14:22 cort
+ */
+/*
  * This file contains sleep low-level functions for PowerBook G3.
- *    Copyright (C) 1999 Benjamin Herrenschmidt (bh40@calva.net)
+ *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
  *    and Paul Mackerras (paulus@cs.anu.edu.au).
  *
  * This program is free software; you can redistribute it and/or
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.4.4/linux/arch/ppc/kernel/smp.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/smp.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.smp.c 1.23 05/17/01 18:14:22 cort
+ */
+/*
  * Smp support for ppc.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
@@ -40,6 +43,7 @@
 #include <asm/residual.h>
 #include <asm/feature.h>
 #include <asm/time.h>
+#include <asm/gemini.h>
 
 #include "open_pic.h"
 int smp_threads_ready;
@@ -55,7 +59,7 @@
 unsigned int prof_counter[NR_CPUS];
 cycles_t cacheflush_time;
 static int max_cpus __initdata = NR_CPUS;
-
+unsigned long cpu_online_map;
 int smp_hw_index[NR_CPUS];
 
 /* all cpu mappings are 1-1 -- Cort */
@@ -452,32 +456,48 @@
 static void
 smp_core99_kick_cpu(int nr)
 {
-	unsigned long save_int;
+	unsigned long save_vector, new_vector;
 	unsigned long flags;
+#if 1 /* New way... */
+	volatile unsigned long *vector
+		 = ((volatile unsigned long *)(KERNELBASE+0x100));
+	if (nr < 1 || nr > 3)
+		return;
+#else
 	volatile unsigned long *vector
 		 = ((volatile unsigned long *)(KERNELBASE+0x500));
-
 	if (nr != 1)
 		return;
+#endif
 	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
 
 	local_irq_save(flags);
 	local_irq_disable();
 	
-	/* Save EE vector */
-	save_int = *vector;
+	/* Save reset vector */
+	save_vector = *vector;
 	
-	/* Setup fake EE vector that does	  
+	/* Setup fake reset vector that does	  
 	 *   b __secondary_start_psurge - KERNELBASE
-	 */   
-	*vector = 0x48000002 +
-		((unsigned long)__secondary_start_psurge - KERNELBASE);
+	 */  
+	switch(nr) {
+		case 1:
+			new_vector = (unsigned long)__secondary_start_psurge;
+			break;
+		case 2:
+			new_vector = (unsigned long)__secondary_start_psurge2;
+			break;
+		case 3:
+			new_vector = (unsigned long)__secondary_start_psurge3;
+			break;
+	}
+	*vector = 0x48000002 + new_vector - KERNELBASE;
 	
 	/* flush data cache and inval instruction cache */
 	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
 	
 	/* Put some life in our friend */
-	feature_core99_kick_cpu1();
+	feature_core99_kick_cpu(nr);
 	
 	/* FIXME: We wait a bit for the CPU to take the exception, I should
 	 * instead wait for the entry code to set something for me. Well,
@@ -487,11 +507,11 @@
 	mdelay(1);
 	
 	/* Restore our exception vector */
-	*vector = save_int;
+	*vector = save_vector;
 	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
 	
 	local_irq_restore(flags);
-	if (ppc_md.progress) ppc_md.progress("smp_core99_probe done", 0x347);
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
 }
 
 static void
@@ -628,6 +648,43 @@
 		do_openpic_setup_cpu();
 }
 
+#ifdef CONFIG_GEMINI	
+static int
+smp_gemini_probe(void)
+{
+	int i, nr;
+
+        nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
+	if (nr == 0)
+		nr = 4;
+
+	if (nr > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < nr; ++i)
+			smp_hw_index[i] = i;
+	}
+
+	return nr;
+}
+
+static void
+smp_gemini_kick_cpu(int nr)
+{
+	openpic_init_processor( 1<<i );
+	openpic_init_processor( 0 );
+}
+
+static void
+smp_gemini_setup_cpu(void)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+	if (cpu_nr > 0)
+		gemini_init_l2();
+}
+#endif /* CONFIG_GEMINI */
+
+
 static struct smp_ops_t {
 	void  (*message_pass)(int target, int msg, unsigned long data, int wait);
 	int   (*probe)(void);
@@ -685,6 +742,16 @@
 	smp_prep_setup_cpu,
 };
 
+#ifdef CONFIG_GEMINI	
+/* Gemini */
+static struct smp_ops_t gemini_smp_ops = {
+	smp_openpic_message_pass,
+	smp_gemini_probe,
+	smp_gemini_kick_cpu,
+	smp_gemini_setup_cpu,
+};
+#endif /* CONFIG_GEMINI	*/
+
 /* 
  * Common functions
  */
@@ -925,6 +992,11 @@
 	case _MACH_prep:
 		smp_ops = &prep_smp_ops;
 		break;
+#ifdef CONFIG_GEMINI		
+	case _MACH_gemini:
+		smp_ops = &gemini_smp_ops;
+		break;
+#endif /* CONFIG_GEMINI	*/
 	default:
 		printk("SMP not supported on this machine.\n");
 		return;
@@ -946,6 +1018,19 @@
 		/* create a process for the processor */
 		/* we don't care about the values in regs since we'll
 		   never reschedule the forked task. */
+		/* We DO care about one bit in the pt_regs we
+		   pass to do_fork.  That is the MSR_FP bit in 
+		   regs.msr.  If that bit is on, then do_fork
+		   (via copy_thread) will call giveup_fpu.
+		   giveup_fpu will get a pointer to our (current's)
+		   last register savearea via current->thread.regs 
+		   and using that pointer will turn off the MSR_FP,
+		   MSR_FE0 and MSR_FE1 bits.  At this point, this 
+		   pointer is pointing to some arbitrary point within
+		   our stack. */
+
+		memset(&regs, 0, sizeof(struct pt_regs));
+		
 		if (do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0) < 0)
 			panic("failed fork for CPU %d", i);
 		p = init_task.prev_task;
@@ -1114,8 +1199,18 @@
 
 	init_idle();
 
+	/*
+	 * This cpu is now "online".  Only set them online
+	 * before they enter the loop below since write access
+	 * to the below variable is _not_ guaranteed to be
+	 * atomic.
+	 *   -- Cort <cort@fsmlabs.com>
+	 */
+	cpu_online_map |= 1UL << smp_processor_id();
+	
 	while(!smp_commenced)
 		barrier();
+
 	/* see smp_commence for more info */
 	if (!smp_tb_synchronized && smp_num_cpus == 2) {
 		smp_software_tb_sync(cpu);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.4.4/linux/arch/ppc/kernel/softemu8xx.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/softemu8xx.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.softemu8xx.c 1.8 05/17/01 18:14:22 cort
+ */
+/*
  * Software emulation of some PPC instructions for the 8xx core.
  *
  * Copyright (C) 1998 Dan Malek (dmalek@jlc.net)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.4.4/linux/arch/ppc/kernel/syscalls.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/ppc/kernel/syscalls.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.syscalls.c 1.8 05/17/01 18:14:22 cort
+ */
+/*
  * linux/arch/ppc/kernel/sys_ppc.c
  *
  *  PowerPC version 
@@ -185,9 +188,10 @@
 	return error;
 }
 
-unsigned long sys_mmap(unsigned long addr, size_t len,
-		       unsigned long prot, unsigned long flags,
-		       unsigned long fd, off_t offset)
+static inline unsigned long
+do_mmap2(unsigned long addr, size_t len,
+	 unsigned long prot, unsigned long flags,
+	 unsigned long fd, unsigned long pgoff)
 {
 	struct file * file = NULL;
 	int ret = -EBADF;
@@ -199,12 +203,33 @@
 	}
 	
 	down_write(&current->mm->mmap_sem);
-	ret = do_mmap(file, addr, len, prot, flags, offset);
+	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
 	if (file)
 		fput(file);
 out:
 	return ret;
+}
+
+unsigned long sys_mmap2(unsigned long addr, size_t len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff)
+{
+	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+unsigned long sys_mmap(unsigned long addr, size_t len,
+		       unsigned long prot, unsigned long flags,
+		       unsigned long fd, off_t offset)
+{
+	int err = -EINVAL;
+
+	if (offset & ~PAGE_MASK)
+		goto out;
+
+	err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+out:
+	return err;
 }
 
 extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.4.4/linux/arch/ppc/kernel/time.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/time.c	Mon May 21 17:04:47 2001
@@ -1,5 +1,7 @@
 /*
- * $Id: time.c,v 1.57 1999/10/21 03:08:16 cort Exp $
+ * BK Id: SCCS/s.time.c 1.15 05/17/01 18:14:22 cort
+ */
+/*
  * Common time routines among all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -50,6 +52,7 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/kernel_stat.h>
@@ -91,6 +94,10 @@
 
 static long time_offset;
 
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+
+EXPORT_SYMBOL(rtc_lock);
+
 /* Timer interrupt helper function */
 static inline int tb_delta(unsigned *jiffy_stamp) {
 	int delta;
@@ -144,14 +151,20 @@
 	int next_dec;
 	unsigned long cpu = smp_processor_id();
 	unsigned jiffy_stamp = last_jiffy_stamp(cpu);
+	extern void do_IRQ(struct pt_regs *);
+
+	if (atomic_read(&ppc_n_lost_interrupts) != 0)
+		do_IRQ(regs);
 
 	hardirq_enter(cpu);
 	
-	if (!user_mode(regs))
-		ppc_do_profile(instruction_pointer(regs));
-	do { 
+	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
-	  	if (smp_processor_id()) continue;
+		if (!user_mode(regs))
+			ppc_do_profile(instruction_pointer(regs));
+	  	if (smp_processor_id())
+			continue;
+
 		/* We are in an interrupt, no need to save/restore flags */
 		write_lock(&xtime_lock);
 		tb_last_stamp = jiffy_stamp;
@@ -184,7 +197,7 @@
 				last_rtc_update += 60;
 		}
 		write_unlock(&xtime_lock);
-	} while((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0);
+	}
 	if ( !disarm_decr[smp_processor_id()] )
 		set_dec(next_dec);
 	last_jiffy_stamp(cpu) = jiffy_stamp;
@@ -337,6 +350,8 @@
         	tz.tz_dsttime = 0;
         	do_sys_settimeofday(NULL, &tz);
         }
+
+       do_get_fast_time = do_gettimeofday;
 }
 
 #define TICK_SIZE tick
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.4.4/linux/arch/ppc/kernel/traps.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/traps.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.traps.c 1.11 05/17/01 18:14:22 cort
+ */
+/*
  *  linux/arch/ppc/kernel/traps.c
  *
  *  Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/walnut_setup.c linux/arch/ppc/kernel/walnut_setup.c
--- v2.4.4/linux/arch/ppc/kernel/walnut_setup.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/walnut_setup.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.walnut_setup.c 1.5 05/17/01 18:14:22 cort
+ */
+/*
  *
  *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/walnut_setup.h linux/arch/ppc/kernel/walnut_setup.h
--- v2.4.4/linux/arch/ppc/kernel/walnut_setup.h	Thu Feb 10 12:37:51 2000
+++ linux/arch/ppc/kernel/walnut_setup.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.walnut_setup.h 1.5 05/17/01 18:14:22 cort
+ */
+/*
  *
  *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/xics.c linux/arch/ppc/kernel/xics.c
--- v2.4.4/linux/arch/ppc/kernel/xics.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/xics.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.xics.c 1.5 05/17/01 18:14:22 cort
+ */
+/*
  * arch/ppc/kernel/xics.c
  *
  * Copyright 2000 IBM Corporation.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/kernel/xics.h linux/arch/ppc/kernel/xics.h
--- v2.4.4/linux/arch/ppc/kernel/xics.h	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/kernel/xics.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.xics.h 1.5 05/17/01 18:14:22 cort
+ */
+/*
  * arch/ppc/kernel/xics.h
  *
  * Copyright 2000 IBM Corporation.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile
--- v2.4.4/linux/arch/ppc/lib/Makefile	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/lib/Makefile	Mon May 21 17:04:47 2001
@@ -1,9 +1,10 @@
+# BK Id: SCCS/s.Makefile 1.7 05/17/01 18:14:22 cort
+#
 #
 # Makefile for ppc-specific library files..
 #
 
-.S.o:
-	$(CC) $(AFLAGS) -c $< -o $*.o
+USE_STANDARD_AS_RULE	:= true
 
 O_TARGET		:= lib.o
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/lib/checksum.S linux/arch/ppc/lib/checksum.S
--- v2.4.4/linux/arch/ppc/lib/checksum.S	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/lib/checksum.S	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.checksum.S 1.5 05/17/01 18:14:22 cort
+ */
+/*
  * This file contains assembly-language implementations
  * of IP-style 1's complement checksum routines.
  *	
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c
--- v2.4.4/linux/arch/ppc/lib/locks.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/lib/locks.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- * $Id: locks.c,v 1.25 1999/09/10 10:40:13 davem Exp $
- *
+ * BK Id: SCCS/s.locks.c 1.8 05/17/01 18:14:22 cort
+ */
+/*
  * Locks for smp ppc 
  * 
  * Written by Cort Dougan (cort@cs.nmt.edu)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/lib/strcase.c linux/arch/ppc/lib/strcase.c
--- v2.4.4/linux/arch/ppc/lib/strcase.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/lib/strcase.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.strcase.c 1.5 05/17/01 18:14:22 cort
+ */
 #include <linux/ctype.h>
 
 int strcasecmp(const char *s1, const char *s2)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- v2.4.4/linux/arch/ppc/lib/string.S	Tue Sep 19 08:31:53 2000
+++ linux/arch/ppc/lib/string.S	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.string.S 1.5 05/17/01 18:14:22 cort
+ */
+/*
  * String handling functions for PowerPC.
  *
  * Copyright (C) 1996 Paul Mackerras.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/Makefile linux/arch/ppc/math-emu/Makefile
--- v2.4.4/linux/arch/ppc/math-emu/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/math-emu/Makefile	Mon May 21 17:04:47 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:22 cort
+#
 #
 #
 #
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/double.h linux/arch/ppc/math-emu/double.h
--- v2.4.4/linux/arch/ppc/math-emu/double.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/double.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.double.h 1.5 05/17/01 18:14:22 cort
+ */
+/*
  * Definitions for IEEE Double Precision
  */
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fabs.c linux/arch/ppc/math-emu/fabs.c
--- v2.4.4/linux/arch/ppc/math-emu/fabs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fabs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fabs.c,v 1.1 1999/08/23 18:59:21 cort Exp $
+/*
+ * BK Id: SCCS/s.fabs.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fadd.c linux/arch/ppc/math-emu/fadd.c
--- v2.4.4/linux/arch/ppc/math-emu/fadd.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fadd.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fadd.c,v 1.1 1999/08/23 18:59:22 cort Exp $
+/*
+ * BK Id: SCCS/s.fadd.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fadds.c linux/arch/ppc/math-emu/fadds.c
--- v2.4.4/linux/arch/ppc/math-emu/fadds.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fadds.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fadds.c,v 1.1 1999/08/23 18:59:25 cort Exp $
+/*
+ * BK Id: SCCS/s.fadds.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fcmpo.c linux/arch/ppc/math-emu/fcmpo.c
--- v2.4.4/linux/arch/ppc/math-emu/fcmpo.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fcmpo.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fcmpo.c,v 1.1 1999/08/23 18:59:26 cort Exp $
+/*
+ * BK Id: SCCS/s.fcmpo.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fcmpu.c linux/arch/ppc/math-emu/fcmpu.c
--- v2.4.4/linux/arch/ppc/math-emu/fcmpu.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fcmpu.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fcmpu.c,v 1.1 1999/08/23 18:59:28 cort Exp $
+/*
+ * BK Id: SCCS/s.fcmpu.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fctiw.c linux/arch/ppc/math-emu/fctiw.c
--- v2.4.4/linux/arch/ppc/math-emu/fctiw.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fctiw.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fctiw.c,v 1.1 1999/08/23 18:59:30 cort Exp $
+/*
+ * BK Id: SCCS/s.fctiw.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fctiwz.c linux/arch/ppc/math-emu/fctiwz.c
--- v2.4.4/linux/arch/ppc/math-emu/fctiwz.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fctiwz.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fctiwz.c,v 1.1 1999/08/23 18:59:31 cort Exp $
+/*
+ * BK Id: SCCS/s.fctiwz.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fdiv.c linux/arch/ppc/math-emu/fdiv.c
--- v2.4.4/linux/arch/ppc/math-emu/fdiv.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fdiv.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fdiv.c,v 1.1 1999/08/23 18:59:33 cort Exp $
+/*
+ * BK Id: SCCS/s.fdiv.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fdivs.c linux/arch/ppc/math-emu/fdivs.c
--- v2.4.4/linux/arch/ppc/math-emu/fdivs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fdivs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fdivs.c,v 1.1 1999/08/23 18:59:35 cort Exp $
+/*
+ * BK Id: SCCS/s.fdivs.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmadd.c linux/arch/ppc/math-emu/fmadd.c
--- v2.4.4/linux/arch/ppc/math-emu/fmadd.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmadd.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmadd.c,v 1.1 1999/08/23 18:59:36 cort Exp $
+/*
+ * BK Id: SCCS/s.fmadd.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmadds.c linux/arch/ppc/math-emu/fmadds.c
--- v2.4.4/linux/arch/ppc/math-emu/fmadds.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmadds.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmadds.c,v 1.1 1999/08/23 18:59:38 cort Exp $
+/*
+ * BK Id: SCCS/s.fmadds.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmr.c linux/arch/ppc/math-emu/fmr.c
--- v2.4.4/linux/arch/ppc/math-emu/fmr.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmr.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmr.c,v 1.1 1999/08/23 18:59:40 cort Exp $
+/*
+ * BK Id: SCCS/s.fmr.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmsub.c linux/arch/ppc/math-emu/fmsub.c
--- v2.4.4/linux/arch/ppc/math-emu/fmsub.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmsub.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmsub.c,v 1.1 1999/08/23 18:59:41 cort Exp $
+/*
+ * BK Id: SCCS/s.fmsub.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmsubs.c linux/arch/ppc/math-emu/fmsubs.c
--- v2.4.4/linux/arch/ppc/math-emu/fmsubs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmsubs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmsubs.c,v 1.1 1999/08/23 18:59:42 cort Exp $
+/*
+ * BK Id: SCCS/s.fmsubs.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmul.c linux/arch/ppc/math-emu/fmul.c
--- v2.4.4/linux/arch/ppc/math-emu/fmul.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmul.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmul.c,v 1.1 1999/08/23 18:59:44 cort Exp $
+/*
+ * BK Id: SCCS/s.fmul.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fmuls.c linux/arch/ppc/math-emu/fmuls.c
--- v2.4.4/linux/arch/ppc/math-emu/fmuls.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fmuls.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fmuls.c,v 1.1 1999/08/23 18:59:45 cort Exp $
+/*
+ * BK Id: SCCS/s.fmuls.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fnabs.c linux/arch/ppc/math-emu/fnabs.c
--- v2.4.4/linux/arch/ppc/math-emu/fnabs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fnabs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fnabs.c,v 1.1 1999/08/23 18:59:47 cort Exp $
+/*
+ * BK Id: SCCS/s.fnabs.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fneg.c linux/arch/ppc/math-emu/fneg.c
--- v2.4.4/linux/arch/ppc/math-emu/fneg.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fneg.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fneg.c,v 1.1 1999/08/23 18:59:48 cort Exp $
+/*
+ * BK Id: SCCS/s.fneg.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fnmadd.c linux/arch/ppc/math-emu/fnmadd.c
--- v2.4.4/linux/arch/ppc/math-emu/fnmadd.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fnmadd.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fnmadd.c,v 1.1 1999/08/23 18:59:50 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmadd.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fnmadds.c linux/arch/ppc/math-emu/fnmadds.c
--- v2.4.4/linux/arch/ppc/math-emu/fnmadds.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fnmadds.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fnmadds.c,v 1.1 1999/08/23 18:59:51 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmadds.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fnmsub.c linux/arch/ppc/math-emu/fnmsub.c
--- v2.4.4/linux/arch/ppc/math-emu/fnmsub.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fnmsub.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fnmsub.c,v 1.1 1999/08/23 18:59:53 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmsub.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fnmsubs.c linux/arch/ppc/math-emu/fnmsubs.c
--- v2.4.4/linux/arch/ppc/math-emu/fnmsubs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fnmsubs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fnmsubs.c,v 1.1 1999/08/23 18:59:54 cort Exp $
+/*
+ * BK Id: SCCS/s.fnmsubs.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fres.c linux/arch/ppc/math-emu/fres.c
--- v2.4.4/linux/arch/ppc/math-emu/fres.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fres.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fres.c,v 1.1 1999/08/23 18:59:56 cort Exp $
+/*
+ * BK Id: SCCS/s.fres.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/frsp.c linux/arch/ppc/math-emu/frsp.c
--- v2.4.4/linux/arch/ppc/math-emu/frsp.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/frsp.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: frsp.c,v 1.1 1999/08/23 18:59:57 cort Exp $
+/*
+ * BK Id: SCCS/s.frsp.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/frsqrte.c linux/arch/ppc/math-emu/frsqrte.c
--- v2.4.4/linux/arch/ppc/math-emu/frsqrte.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/frsqrte.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: frsqrte.c,v 1.1 1999/08/23 18:59:58 cort Exp $
+/*
+ * BK Id: SCCS/s.frsqrte.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fsel.c linux/arch/ppc/math-emu/fsel.c
--- v2.4.4/linux/arch/ppc/math-emu/fsel.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fsel.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fsel.c,v 1.1 1999/08/23 18:59:59 cort Exp $
+/*
+ * BK Id: SCCS/s.fsel.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fsqrt.c linux/arch/ppc/math-emu/fsqrt.c
--- v2.4.4/linux/arch/ppc/math-emu/fsqrt.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fsqrt.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fsqrt.c,v 1.1 1999/08/23 19:00:01 cort Exp $
+/*
+ * BK Id: SCCS/s.fsqrt.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fsqrts.c linux/arch/ppc/math-emu/fsqrts.c
--- v2.4.4/linux/arch/ppc/math-emu/fsqrts.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fsqrts.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fsqrts.c,v 1.1 1999/08/23 19:00:03 cort Exp $
+/*
+ * BK Id: SCCS/s.fsqrts.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fsub.c linux/arch/ppc/math-emu/fsub.c
--- v2.4.4/linux/arch/ppc/math-emu/fsub.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fsub.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fsub.c,v 1.1 1999/08/23 19:00:05 cort Exp $
+/*
+ * BK Id: SCCS/s.fsub.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/fsubs.c linux/arch/ppc/math-emu/fsubs.c
--- v2.4.4/linux/arch/ppc/math-emu/fsubs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/fsubs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: fsubs.c,v 1.1 1999/08/23 19:00:07 cort Exp $
+/*
+ * BK Id: SCCS/s.fsubs.c 1.6 05/17/01 18:14:22 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/lfd.c linux/arch/ppc/math-emu/lfd.c
--- v2.4.4/linux/arch/ppc/math-emu/lfd.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/lfd.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: lfd.c,v 1.1 1999/08/23 19:00:08 cort Exp $
+/*
+ * BK Id: SCCS/s.lfd.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/lfs.c linux/arch/ppc/math-emu/lfs.c
--- v2.4.4/linux/arch/ppc/math-emu/lfs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/lfs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: lfs.c,v 1.1 1999/08/23 19:00:10 cort Exp $
+/*
+ * BK Id: SCCS/s.lfs.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/math.c linux/arch/ppc/math-emu/math.c
--- v2.4.4/linux/arch/ppc/math-emu/math.c	Mon Mar 27 22:30:30 2000
+++ linux/arch/ppc/math-emu/math.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
-/* $Id: math.c,v 1.1 1999/08/23 19:00:11 cort Exp $
+/*
+ * BK Id: SCCS/s.math.c 1.6 05/17/01 18:14:23 cort
+ */
+/*
  * arch/ppc/math-emu/math.c
  *
  * Copyright (C) 1999  Eddie C. Dost  (ecd@atecom.com)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/mcrfs.c linux/arch/ppc/math-emu/mcrfs.c
--- v2.4.4/linux/arch/ppc/math-emu/mcrfs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/mcrfs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: mcrfs.c,v 1.1 1999/08/23 19:00:13 cort Exp $
+/*
+ * BK Id: SCCS/s.mcrfs.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/mffs.c linux/arch/ppc/math-emu/mffs.c
--- v2.4.4/linux/arch/ppc/math-emu/mffs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/mffs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: mffs.c,v 1.1 1999/08/23 19:00:14 cort Exp $
+/*
+ * BK Id: SCCS/s.mffs.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/mtfsb0.c linux/arch/ppc/math-emu/mtfsb0.c
--- v2.4.4/linux/arch/ppc/math-emu/mtfsb0.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/mtfsb0.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: mtfsb0.c,v 1.1 1999/08/23 19:00:16 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsb0.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/mtfsb1.c linux/arch/ppc/math-emu/mtfsb1.c
--- v2.4.4/linux/arch/ppc/math-emu/mtfsb1.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/mtfsb1.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: mtfsb1.c,v 1.1 1999/08/23 19:00:17 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsb1.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/mtfsf.c linux/arch/ppc/math-emu/mtfsf.c
--- v2.4.4/linux/arch/ppc/math-emu/mtfsf.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/mtfsf.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: mtfsf.c,v 1.1 1999/08/23 19:00:19 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsf.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/mtfsfi.c linux/arch/ppc/math-emu/mtfsfi.c
--- v2.4.4/linux/arch/ppc/math-emu/mtfsfi.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/mtfsfi.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: mtfsfi.c,v 1.1 1999/08/23 19:00:20 cort Exp $
+/*
+ * BK Id: SCCS/s.mtfsfi.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/op-1.h linux/arch/ppc/math-emu/op-1.h
--- v2.4.4/linux/arch/ppc/math-emu/op-1.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/op-1.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.op-1.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Basic one-word fraction declaration and manipulation.
  */
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/op-2.h linux/arch/ppc/math-emu/op-2.h
--- v2.4.4/linux/arch/ppc/math-emu/op-2.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/op-2.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.op-2.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Basic two-word fraction declaration and manipulation.
  */
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/op-4.h linux/arch/ppc/math-emu/op-4.h
--- v2.4.4/linux/arch/ppc/math-emu/op-4.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/op-4.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.op-4.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Basic four-word fraction declaration and manipulation.
  *
  * When adding quadword support for 32 bit machines, we need
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/op-common.h linux/arch/ppc/math-emu/op-common.h
--- v2.4.4/linux/arch/ppc/math-emu/op-common.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/op-common.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.op-common.h 1.5 05/17/01 18:14:23 cort
+ */
 
 #define _FP_DECL(wc, X)			\
   _FP_I_TYPE X##_c, X##_s, X##_e;	\
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/sfp-machine.h linux/arch/ppc/math-emu/sfp-machine.h
--- v2.4.4/linux/arch/ppc/math-emu/sfp-machine.h	Mon Mar 27 22:30:29 2000
+++ linux/arch/ppc/math-emu/sfp-machine.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.sfp-machine.h 1.5 05/17/01 18:14:23 cort
+ */
 /* Machine-dependent software floating-point definitions.  PPC version.
    Copyright (C) 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/single.h linux/arch/ppc/math-emu/single.h
--- v2.4.4/linux/arch/ppc/math-emu/single.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/single.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.single.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Definitions for IEEE Single Precision
  */
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/soft-fp.h linux/arch/ppc/math-emu/soft-fp.h
--- v2.4.4/linux/arch/ppc/math-emu/soft-fp.h	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/soft-fp.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.soft-fp.h 1.5 05/17/01 18:14:23 cort
+ */
 #ifndef SOFT_FP_H
 #define SOFT_FP_H
 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/stfd.c linux/arch/ppc/math-emu/stfd.c
--- v2.4.4/linux/arch/ppc/math-emu/stfd.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/stfd.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: stfd.c,v 1.1 1999/08/23 19:00:33 cort Exp $
+/*
+ * BK Id: SCCS/s.stfd.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/stfiwx.c linux/arch/ppc/math-emu/stfiwx.c
--- v2.4.4/linux/arch/ppc/math-emu/stfiwx.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/stfiwx.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: stfiwx.c,v 1.1 1999/08/23 19:00:34 cort Exp $
+/*
+ * BK Id: SCCS/s.stfiwx.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/stfs.c linux/arch/ppc/math-emu/stfs.c
--- v2.4.4/linux/arch/ppc/math-emu/stfs.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/stfs.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,6 @@
-/* $Id: stfs.c,v 1.1 1999/08/23 19:00:35 cort Exp $
+/*
+ * BK Id: SCCS/s.stfs.c 1.6 05/17/01 18:14:23 cort
  */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/types.c linux/arch/ppc/math-emu/types.c
--- v2.4.4/linux/arch/ppc/math-emu/types.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/types.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.types.c 1.5 05/17/01 18:14:23 cort
+ */
 
 #include "soft-fp.h"
 #include "double.h"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/math-emu/udivmodti4.c linux/arch/ppc/math-emu/udivmodti4.c
--- v2.4.4/linux/arch/ppc/math-emu/udivmodti4.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/math-emu/udivmodti4.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.udivmodti4.c 1.5 05/17/01 18:14:23 cort
+ */
 /* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny.  */
 
 #include "soft-fp.h"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/Makefile linux/arch/ppc/mbxboot/Makefile
--- v2.4.4/linux/arch/ppc/mbxboot/Makefile	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/mbxboot/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,124 +0,0 @@
-#
-# arch/ppc/mbxboot/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Linus Torvalds
-# Adapted for PowerPC by Gary Thomas
-# modified by Cort (cort@cs.nmt.edu)
-#
-.c.s:
-	$(CC) $(CFLAGS) -S -o $*.s $<
-.s.o:
-	$(AS) -o $*.o $<
-.c.o:
-	$(CC) $(CFLAGS)  -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -c -o $*.o $<
-.S.s:
-	$(CPP) $(AFLAGS) -traditional -o $*.o $<
-.S.o:
-	$(CC) $(AFLAGS) -traditional -c -o $*.o $<
-
-ZOFF = 0
-ZSZ = 0
-IOFF = 0
-ISZ = 0
-
-TFTPIMAGE=/tftpboot/zImage.embedded
-
-ifdef CONFIG_8xx
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
-OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o
-CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx
-endif
-
-ifdef CONFIG_8260
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000
-OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o
-CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260
-endif
-
-OBJCOPY_ARGS = -O elf32-powerpc
-
-ifeq ($(CONFIG_MBX),y)
-OBJECTS += pci.o qspan_pci.o
-CFLAGS += -DCONFIG_MBX
-endif
-ifeq ($(CONFIG_RPXLITE),y)
-CFLAGS += -DCONFIG_RPXLITE
-OBJECTS += iic.o embed_config.o
-endif
-ifeq ($(CONFIG_RPXCLASSIC),y)
-CFLAGS += -DCONFIG_RPXCLASSIC
-OBJECTS += iic.o embed_config.o pci.o qspan_pci.o
-endif
-ifeq ($(CONFIG_BSEIP),y)
-CFLAGS += -DCONFIG_BSEIP
-OBJECTS += iic.o embed_config.o
-endif
-
-all:	zImage
-
-zvmlinux.initrd: zvmlinux
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp1 $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
-		--add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.initrd.tmp1 zvmlinux.initrd1
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 initrd` \
-		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 initrd` \
-		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 image` \
-		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 image` \
-		-c -o misc.o misc.c
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
-		--add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.initrd.tmp $@
-
-zImage: zvmlinux
-	ln -sf zvmlinux zImage
-
-zImage.initrd: zvmlinux.initrd
-	ln -sf zvmlinux.initrd zImage.initrd
-
-zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
-#
-# build the boot loader image and then compute the offset into it
-# for the kernel image
-#
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.tmp $@
-#
-# then with the offset rebuild the bootloader so we know where the kernel is
-#
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
-		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
-		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
-		-c -o misc.o misc.c
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.tmp $@
-	rm zvmlinux.tmp
-
-znetboot : zImage
-	cp zImage $(TFTPIMAGE)
-
-znetboot.initrd : zImage.initrd
-	cp zImage.initrd $(TFTPIMAGE)
-
-clean:
-	rm -f vmlinux* zvmlinux* zImage*
-
-fastdep:
-	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
-
-dep:
-	$(CPP) $(CPPFLAGS) -M *.S *.c > .depend
-
-# just here to match coffboot/Makefile
-vmlinux.coff:
-
-vmlinux.coff.initrd:
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/embed_config.c linux/arch/ppc/mbxboot/embed_config.c
--- v2.4.4/linux/arch/ppc/mbxboot/embed_config.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/mbxboot/embed_config.c	Wed Dec 31 16:00:00 1969
@@ -1,253 +0,0 @@
-
-/* Board specific functions for those embedded 8xx boards that do
- * not have boot monitor support for board information.
- */
-#include <sys/types.h>
-#include <linux/config.h>
-#ifdef CONFIG_8xx
-#include <asm/mpc8xx.h>
-#endif
-#ifdef CONFIG_8260
-#include <asm/mpc8260.h>
-#endif
-
-
-/* IIC functions.
- * These are just the basic master read/write operations so we can
- * examine serial EEPROM.
- */
-extern void	iic_read(uint devaddr, u_char *buf, uint offset, uint count);
-extern u_char	aschex_to_byte(u_char *cp);
-
-/* Supply a default Ethernet address for those eval boards that don't
- * ship with one.  This is an address from the MBX board I have, so
- * it is unlikely you will find it on your network.
- */
-static	ushort	def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
-
-#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
-
-static void	rpx_eth(bd_t *bd, u_char *cp);
-static void	rpx_brate(bd_t *bd, u_char *cp);
-static void	rpx_memsize(bd_t *bd, u_char *cp);
-static void	rpx_cpuspeed(bd_t *bd, u_char *cp);
-
-/* Read the EEPROM on the RPX-Lite board.
-*/
-void
-rpx_cfg(bd_t *bd)
-{
-	u_char	eebuf[256], *cp;
-
-	/* Read the first 256 bytes of the EEPROM.  I think this
-	 * is really all there is, and I hope if it gets bigger the
-	 * info we want is still up front.
-	 */
-#if 1
-	iic_read(0xa8, eebuf, 0, 128);
-	iic_read(0xa8, &eebuf[128], 128, 128);
-	{
-		int i;
-		cp = (u_char *)0xfa000000;
-
-		for (i=0; i<256; i++)
-			*cp++ = eebuf[i];
-	}
-
-	/* We look for two things, the Ethernet address and the
-	 * serial baud rate.  The records are separated by
-	 * newlines.
-	 */
-	cp = eebuf;
-	for (;;) {
-		if (*cp == 'E') {
-			cp++;
-			if (*cp == 'A') {
-				cp += 2;
-				rpx_eth(bd, cp);
-			}
-		}
-		if (*cp == 'S') {
-			cp++;
-			if (*cp == 'B') {
-				cp += 2;
-				rpx_brate(bd, cp);
-			}
-		}
-		if (*cp == 'D') {
-			cp++;
-			if (*cp == '1') {
-				cp += 2;
-				rpx_memsize(bd, cp);
-			}
-		}
-		if (*cp == 'H') {
-			cp++;
-			if (*cp == 'Z') {
-				cp += 2;
-				rpx_cpuspeed(bd, cp);
-			}
-		}
-
-		/* Scan to the end of the record.
-		*/
-		while ((*cp != '\n') && (*cp != 0xff))
-			cp++;
-
-		/* If the next character is a 0 or ff, we are done.
-		*/
-		cp++;
-		if ((*cp == 0) || (*cp == 0xff))
-			break;
-	}
-	bd->bi_memstart = 0;
-
-#else
-	/* For boards without initialized EEPROM.
-	*/
-	bd->bi_memstart = 0;
-	bd->bi_memsize = (8 * 1024 * 1024);
-	bd->bi_intfreq = 48;
-	bd->bi_busfreq = 48;
-	bd->bi_baudrate = 9600;
-#endif
-}
-
-static void
-rpx_eth(bd_t *bd, u_char *cp)
-{
-	int	i;
-
-	for (i=0; i<6; i++) {
-		bd->bi_enetaddr[i] = aschex_to_byte(cp);
-		cp += 2;
-	}
-}
-
-static void
-rpx_brate(bd_t *bd, u_char *cp)
-{
-	uint	rate;
-
-	rate = 0;
-
-	while (*cp != '\n') {
-		rate *= 10;
-		rate += (*cp) - '0';
-		cp++;
-	}
-
-	bd->bi_baudrate = rate * 100;
-}
-
-static void
-rpx_memsize(bd_t *bd, u_char *cp)
-{
-	uint	size;
-
-	size = 0;
-
-	while (*cp != '\n') {
-		size *= 10;
-		size += (*cp) - '0';
-		cp++;
-	}
-
-	bd->bi_memsize = size * 1024 * 1024;
-}
-
-static void
-rpx_cpuspeed(bd_t *bd, u_char *cp)
-{
-	uint	num, den;
-
-	num = den = 0;
-
-	while (*cp != '\n') {
-		num *= 10;
-		num += (*cp) - '0';
-		cp++;
-		if (*cp == '/') {
-			cp++;
-			den = (*cp) - '0';
-			break;
-		}
-	}
-
-	/* I don't know why the RPX just can't state the actual
-	 * CPU speed.....
-	 */
-	if (den) {
-		num /= den;
-		num *= den;
-	}
-	bd->bi_intfreq = bd->bi_busfreq = num;
-
-	/* The 8xx can only run a maximum 50 MHz bus speed (until
-	 * Motorola changes this :-).  Greater than 50 MHz parts
-	 * run internal/2 for bus speed.
-	 */
-	if (num > 50)
-		bd->bi_busfreq /= 2;
-}
-#endif /* RPXLITE || RPXCLASSIC */
-
-#ifdef CONFIG_BSEIP
-/* Build a board information structure for the BSE ip-Engine.
- * There is more to come since we will add some environment
- * variables and a function to read them.
- */
-void
-bseip_cfg(bd_t *bd)
-{
-	u_char	*cp;
-	int	i;
-
-	/* Baud rate and processor speed will eventually come
-	 * from the environment variables.
-	 */
-	bd->bi_baudrate = 9600;
-
-	/* Get the Ethernet station address from the Flash ROM.
-	*/
-	cp = (u_char *)0xfe003ffa;
-	for (i=0; i<6; i++) {
-		bd->bi_enetaddr[i] = *cp++;
-	}
-
-	/* The rest of this should come from the environment as well.
-	*/
-	bd->bi_memstart = 0;
-	bd->bi_memsize = (16 * 1024 * 1024);
-	bd->bi_intfreq = 48;
-	bd->bi_busfreq = 48;
-}
-#endif /* BSEIP */
-
-#ifdef CONFIG_EST8260
-void
-embed_config(bd_t *bd)
-{
-	u_char	*cp;
-	int	i;
-
-#if 0
-	/* This is actually provided by my boot rom.  I have it
-	 * here for those people that may load the kernel with
-	 * a JTAG/COP tool and not the rom monitor.
-	 */
-	bd->bi_baudrate = 115200;
-	bd->bi_intfreq = 200;
-	bd->bi_busfreq = 66;
-	bd->bi_cpmfreq = 66;
-	bd->bi_brgfreq = 33;
-	bd->bi_memsize = 16 * 1024 * 1024;
-#endif
-
-	cp = (u_char *)def_enet_addr;
-	for (i=0; i<6; i++) {
-		bd->bi_enetaddr[i] = *cp++;
-	}
-}
-#endif /* EST8260 */
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/gzimage.c linux/arch/ppc/mbxboot/gzimage.c
--- v2.4.4/linux/arch/ppc/mbxboot/gzimage.c	Mon May 15 14:53:30 2000
+++ linux/arch/ppc/mbxboot/gzimage.c	Wed Dec 31 16:00:00 1969
@@ -1,8 +0,0 @@
-/*
- * gzimage.c
- *
- * Dummy file to allow a compressed zImage to be added
- * into a linker section, accessed by the boot coode
- */
-
-char dummy_for_gzimage;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/head.S linux/arch/ppc/mbxboot/head.S
--- v2.4.4/linux/arch/ppc/mbxboot/head.S	Thu Oct  7 10:17:08 1999
+++ linux/arch/ppc/mbxboot/head.S	Wed Dec 31 16:00:00 1969
@@ -1,249 +0,0 @@
-#include <linux/config.h>
-#include "../kernel/ppc_defs.h"
-#include "../kernel/ppc_asm.tmpl"
-#include <asm/processor.h>
-#include <asm/cache.h>
-
-	.text
-
-/*
- * $Id: head.S,v 1.6 1999/09/15 00:02:25 dmalek Exp $
- *	
- * This code is loaded by the ROM loader at some arbitrary location.
- * Move it to high memory so that it can load the kernel at 0x0000.
- *
- * This is a three step process that will also work when booting from
- * a Flash PROM normally located in high memory.
- *
- * First, the entire image is loaded into some high memory address.
- * This is usually at or above 0x02000000.  This is done by a network
- * boot function supported by the board or a debugger over BDM port.
- *
- * Second, the start up function here will relocate the decompress
- * function to run at the link address of 0x01000000.
- *
- * Last, the decompression function will reloate the initrd, zImage, and
- * the residual data to locations under 8 Meg.  This is necessary because
- * the embedded kernel start up uses 8 Meg translations to access physical
- * space before the MMU is enabled.  Finally, the zImage is uncompressed
- * to location 0 and we jump to it.
- *
- * On the MBX,
- *              R1 - Stack pointer at a high memory address.
- *              R3 - Pointer to Board Information Block.
- *              R4 - Pointer to argument string.
- *              Interrupts masked, cache and MMU disabled.
- *
- *		...and the first and second functions listed above are
- *			done for us (it knows ELF images).
- *
- * For other embedded boards we build the Board Information Block.
- */
-
-	.globl	start
-start:
-	bl	start_
-start_:
-#ifndef CONFIG_MBX
-	lis	r11, local_bd_info@h
-	ori	r11, r11, local_bd_info@l
-#else
-	mr	r11, r3
-#endif
-
-	mfmsr	r3		/* Turn off interrupts  */
-	li	r4,0
-	ori	r4,r4,MSR_EE
-	andc	r3,r3,r4
-	mtmsr	r3
-
-/* check if we need to relocate ourselves to the link addr or were we
-   loaded there to begin with -- Cort */
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	mflr	r3
-	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
-	mr	r8,r3
-#if 0
-	cmp	0,r3,r4
-	beq	start_ldr	/* Branch if loaded OK */
-#endif
-
-/* 
- * no matter where we're loaded, move ourselves to -Ttext address
- * This computes the sizes we need to determine other things.
- */
-	lis	r5,end@h
-	ori	r5,r5,end@l
-	addi	r5,r5,3			/* Round up - just in case */
-	sub	r5,r5,r4		/* Compute # longwords to move */
-	srwi	r5,r5,2
-	mtctr	r5
-	mr	r7,r5
-	li	r6,0
-	subi	r3,r3,4			/* Set up for loop */
-	subi	r4,r4,4
-00:	lwzu	r5,4(r3)
-	stwu	r5,4(r4)
-	xor	r6,r6,r5
-	bdnz	00b
-
-  	lis	r3,start_ldr@h
-	ori	r3,r3,start_ldr@l
-	mtlr	r3			/* Easiest way to do an absolute jump */
-	blr
-
-start_ldr:
-/* Most 8xx boards don't boot up with the I-cache enabled.  Do that
- * now because the decompress runs much faster that way.
- */
-	lis	r3, IDC_INVALL@h
-	mtspr	IC_CST, r3
-	lis	r3, IDC_ENABLE@h
-	mtspr	IC_CST, r3
-
-/* Clear all of BSS */
-	lis	r3,edata@h
-	ori	r3,r3,edata@l
-	lis	r4,end@h
-	ori	r4,r4,end@l
-	subi	r3,r3,4
-	subi	r4,r4,4
-	li	r0,0
-50:	stwu	r0,4(r3)
-	cmp	0,r3,r4
-	bne	50b
-
-	lis	r1,.stack@h
-	ori	r1,r1,.stack@l
-	addi	r1,r1,4096*2
-	subi	r1,r1,256
-	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
-	andc	r1,r1,r2
-
-	/* Perform configuration of the various boards.  This is done
-	 * by reading some configuration data from EEPROM and building
-	 * the board information structure.
-	 */
-	mr	r3, r11
-        mr      r21, r11
-	mr	r22, r8
-	mr	r23, r7
-	mr	r24, r6
-
-#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
-	bl	rpx_cfg
-	mr	r3, r21
-#endif
-#ifdef CONFIG_BSEIP
-	bl	bseip_cfg
-	mr	r3, r21
-#endif
-	bl      serial_init		/* Init MBX serial port */
-
-	mr      r11, r21
-	mr	r8, r22
-	mr	r7, r23
-	mr	r6, r24
-
-#ifdef CONFIG_MBX
-	lis	r18, 0xfa200000@h	/* Disable Ethernet SCC */
-	li	r0, 0
-	stw	r0, 0x0a00(r18)
-
-	/* On the MBX (or anything that will TFTP load an ELF image),
-	 * we have to find the intermediate address.  The ELF loader
-	 * only moves the Linux boostrap/decompress, not the zImage.
-	 */
-#define ILAP_ADDRESS    0xfa000020
-        lis     r8, ILAP_ADDRESS@h
-        lwz     r8, ILAP_ADDRESS@l(r8)
-        addis   r8, r8, 1               /* Add 64K */
-#endif
-
-	mr	r3,r8			/* Load point */
-	mr	r4,r7			/* Program length */
-	mr	r5,r6			/* Checksum */
-	mr	r6,r11			/* Residual data */
-	bl	decompress_kernel
-
-	/* changed to use r3 (as firmware does) for kernel
-	   as ptr to residual -- Cort*/
-	lis	r6,cmd_line@h
-	ori	r6,r6,cmd_line@l
-	lwz	r6, 0(r6)
-	subi	r7,r6,1
-00:	lbzu	r2,1(r7)
-	cmpi	0,r2,0
-	bne	00b
-
-	/* r4,r5 have initrd_start, size */
-	lis	r2,initrd_start@h
-	ori	r2,r2,initrd_start@l
-	lwz	r4,0(r2)
-	lis	r2,initrd_end@h
-	ori	r2,r2,initrd_end@l
-	lwz	r5,0(r2)
-	
-	/* The world starts from the beginning.
-	*/
-	li	r9,0x0
-	mtlr	r9
-
-	/* Invalidate the instruction cache because we just copied a
-	 * bunch of kernel instructions.
-	 */
-	lis	r9, IDC_INVALL@h
-	mtspr	IC_CST, r9
-
-	blr
-hang:
-	b	hang	
-
-/*
- * Delay for a number of microseconds
- * -- Use the BUS timer (assumes 66MHz)
- */
-	.globl	udelay
-udelay:		
-	mulli	r4,r3,1000	/* nanoseconds */
-	addi	r4,r4,59
-	li	r5,60
-	divw	r4,r4,r5	/* BUS ticks */
-1:	mftbu	r5
-	mftb	r6
-	mftbu	r7
-	cmp	0,r5,r7
-	bne	1b		/* Get [synced] base time */
-	addc	r9,r6,r4	/* Compute end time */
-	addze	r8,r5
-2:	mftbu	r5
-	cmp	0,r5,r8
-	blt	2b
-	bgt	3f
-	mftb	r6
-	cmp	0,r6,r9
-	blt	2b
-3:	blr		
-
-.globl _get_MSR
-_get_MSR:		
-	mfmsr	r3
-	blr
-	
-.globl _put_MSR
-_put_MSR:		
-	mtmsr	r3
-	blr
-
-	.comm	.stack,4096*2,4
-#ifndef CONFIG_MBX
-local_bd_info:
-	.long	0
-	.long	0x01000000
-	.long	64
-	.long	64
-	.long	0
-	.long	0
-	.long	0
-#endif
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/head_8260.S linux/arch/ppc/mbxboot/head_8260.S
--- v2.4.4/linux/arch/ppc/mbxboot/head_8260.S	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/mbxboot/head_8260.S	Wed Dec 31 16:00:00 1969
@@ -1,258 +0,0 @@
-#include "../kernel/ppc_defs.h"
-#include "../kernel/ppc_asm.tmpl"
-#include <asm/processor.h>
-#include <asm/cache.h>
-
-	.text
-
-/*
- * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
- *	
- * Boot loader philosophy:
- *
- *      ROM loads us to some arbitrary location
- *      ROM loads these registers:
- *	
- *          R3 = Pointer to the board configuration data
- *          R5 = Pointer to Open Firmware data 	
- *		 	
- *      ROM jumps to start/start_
- *      Move the boot code to the link address (4 MB)
- *      Call decompress_kernel()
- *         Relocate the initrd, zimage and residual data to 4 MB
- *         Decompress the kernel to 0
- *      Jump to the kernel entry
- *            -- Cort
- */
-	.globl	start
-start:
-	bl	start_
-start_:
-	mr	r11,r3		/* Save pointer to residual/board data */
-	mr      r25,r5          /* Save OFW pointer */
-	li	r3,MSR_IP	/* Establish default MSR value */
-	mtmsr	r3
-
-/* check if we need to relocate ourselves to the link addr or were we
-   loaded there to begin with -- Cort */
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	mflr	r3
-	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
-	mr	r8,r3
-	cmp	0,r3,r4
-	bne	1010f
-/* compute size of whole image in words.  this should be moved to
- * start_ldr() -- Cort
- */
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	lis	r5,end@h
-	ori	r5,r5,end@l
-	addi	r5,r5,3		/* round up */
-	sub	r5,r5,r4
-	srwi	r5,r5,2
-	mr	r7,r5
-	b	start_ldr
-1010:
-/* 
- * no matter where we're loaded, move ourselves to -Ttext address
- */
-relocate:
-	mflr	r3		/* Compute code bias */
-	subi	r3,r3,4
-	mr	r8,r3
-	lis	r4,start@h
-	ori	r4,r4,start@l
-	lis	r5,end@h
-	ori	r5,r5,end@l
-	addi	r5,r5,3			/* Round up - just in case */
-	sub	r5,r5,r4		/* Compute # longwords to move */
-	srwi	r5,r5,2
-	mtctr	r5
-	mr	r7,r5
-	li	r6,0
-	subi	r3,r3,4			/* Set up for loop */
-	subi	r4,r4,4
-00:	lwzu	r5,4(r3)
-	stwu	r5,4(r4)
-	xor	r6,r6,r5
-	bdnz	00b
-  	lis	r3,start_ldr@h
-	ori	r3,r3,start_ldr@l
-	mtlr	r3			/* Easiest way to do an absolute jump */
-	blr
-start_ldr:
-/* Clear all of BSS */
-	lis	r3,edata@h
-	ori	r3,r3,edata@l
-	lis	r4,end@h
-	ori	r4,r4,end@l
-	subi	r3,r3,4
-	subi	r4,r4,4
-	li	r0,0
-50:	stwu	r0,4(r3)
-	cmp	0,r3,r4
-	bne	50b
-90:	mr	r9,r1			/* Save old stack pointer (in case it matters) */
-	lis	r1,.stack@h
-	ori	r1,r1,.stack@l
-	addi	r1,r1,4096*2
-	subi	r1,r1,256
-	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
-	andc	r1,r1,r2
-
-	/* Speed us up a little.
-	*/
-	bl	flush_instruction_cache
-
-/* Run loader */
-	mr	r3,r8			/* Load point */
-	mr	r4,r7			/* Program length */
-	mr	r5,r6			/* Checksum */
-	mr	r6,r11			/* Residual data */
-	mr      r7,r25                  /* OFW interfaces */
-	bl	decompress_kernel
-	
-	/* changed to use r3 (as firmware does) for kernel
-	   as ptr to residual -- Cort*/
-	lis	r6,cmd_line@h
-	ori	r6,r6,cmd_line@l
-	lwz	r6, 0(r6)
-	subi	r7,r6,1
-00:	lbzu	r2,1(r7)
-	cmpi	0,r2,0
-	bne	00b
-
-	/* r4,r5 have initrd_start, size */
-	lis	r2,initrd_start@h
-	ori	r2,r2,initrd_start@l
-	lwz	r4,0(r2)
-	lis	r2,initrd_end@h
-	ori	r2,r2,initrd_end@l
-	lwz	r5,0(r2)
-	
-	/* tell kernel we're prep */
-	/* 
-	 * get start address of kernel code which is stored as a coff
-	 * entry.  see boot/head.S -- Cort 
-	 */
-	li	r9,0x4
-	mtlr	r9
-	lis	r10,0xdeadc0de@h
-	ori	r10,r10,0xdeadc0de@l
-	li	r9,0
-	stw	r10,0(r9)
-/*
- * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
- * so disable BATs before setting this to avoid a clash
- */
-	li      r8,0
-	mtspr   DBAT0U,r8
-	mtspr   DBAT1U,r8
-	mtspr   DBAT2U,r8
-	mtspr   DBAT3U,r8
-	mtspr   IBAT0U,r8
-	mtspr   IBAT1U,r8
-	mtspr   IBAT2U,r8
-	mtspr   IBAT3U,r8
-
-	blr
-hang:
-	b	hang	
-
-/*
- * Delay for a number of microseconds
- * -- Use the BUS timer (assumes 66MHz)
- */
-	.globl	udelay
-udelay:		
-	mfspr	r4,PVR
-	srwi	r4,r4,16
-	cmpi	0,r4,1		/* 601 ? */
-	bne	.udelay_not_601
-00:	li	r0,86	/* Instructions / microsecond? */
-	mtctr	r0
-10:	addi	r0,r0,0 /* NOP */
-	bdnz	10b
-	subic.	r3,r3,1
-	bne	00b
-	blr
-
-.udelay_not_601:		
-	mulli	r4,r3,1000	/* nanoseconds */
-	addi	r4,r4,59
-	li	r5,60
-	divw	r4,r4,r5	/* BUS ticks */
-1:	mftbu	r5
-	mftb	r6
-	mftbu	r7
-	cmp	0,r5,r7
-	bne	1b		/* Get [synced] base time */
-	addc	r9,r6,r4	/* Compute end time */
-	addze	r8,r5
-2:	mftbu	r5
-	cmp	0,r5,r8
-	blt	2b
-	bgt	3f
-	mftb	r6
-	cmp	0,r6,r9
-	blt	2b
-3:	blr		
-
-.globl _get_HID0
-_get_HID0:		
-	mfspr	r3,HID0
-	blr
-
-.globl _put_HID0
-_put_HID0:		
-	mtspr	HID0,r3
-	blr
-		
-.globl _get_MSR
-_get_MSR:		
-	mfmsr	r3
-	blr
-	
-.globl _put_MSR
-_put_MSR:		
-	mtmsr	r3
-	blr
-
-/*
- * Flush instruction cache
- * *** I'm really paranoid here!
- */
-_GLOBAL(flush_instruction_cache)
-	mflr	r5
-	bl	flush_data_cache
-	mfspr	r3,HID0	/* Caches are controlled by this register */
-	li	r4,0
-	ori	r4,r4,(HID0_ICE|HID0_ICFI)
-	or	r3,r3,r4	/* Need to enable+invalidate to clear */
-	mtspr	HID0,r3
-	andc	r3,r3,r4
-	ori	r3,r3,HID0_ICE	/* Enable cache */
-	mtspr	HID0,r3
-	mtlr	r5
-	blr
-	
-#define NUM_CACHE_LINES 128*8
-#define CACHE_LINE_SIZE 32 
-#define cache_flush_buffer 0x1000
-
-/*
- * Flush data cache
- * *** I'm really paranoid here!
- */
-_GLOBAL(flush_data_cache)
-	lis	r3,cache_flush_buffer@h
-	ori	r3,r3,cache_flush_buffer@l
-	li	r4,NUM_CACHE_LINES
-	mtctr	r4
-00:	lwz	r4,0(r3)
-	addi	r3,r3,CACHE_LINE_SIZE	/* Next line, please */
-	bdnz	00b	
-10:	blr
-	.comm	.stack,4096*2,4
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/iic.c linux/arch/ppc/mbxboot/iic.c
--- v2.4.4/linux/arch/ppc/mbxboot/iic.c	Tue May  2 13:05:40 2000
+++ linux/arch/ppc/mbxboot/iic.c	Wed Dec 31 16:00:00 1969
@@ -1,259 +0,0 @@
-
-/* Minimal support functions to read configuration from IIC EEPROMS
- * on MPC8xx boards.  Originally written for RPGC RPX-Lite.
- * Dan Malek (dmalek@jlc.net).
- */
-#include <linux/types.h>
-#include <asm/uaccess.h>
-#include "asm/mpc8xx.h"
-#include "../8xx_io/commproc.h"
-
-
-/* IIC functions.
- * These are just the basic master read/write operations so we can
- * examine serial EEPROM.
- */
-void	iic_read(uint devaddr, u_char *buf, uint offset, uint count);
-u_char	aschex_to_byte(u_char *cp);
-
-static	int	iic_init_done;
-
-static void
-iic_init()
-{
-	volatile iic_t *iip;
-	volatile i2c8xx_t *i2c;
-	volatile cbd_t	*tbdf, *rbdf;
-	volatile cpm8xx_t	*cp;
-	volatile immap_t	*immap;
-	uint	dpaddr;
-
-	immap = (immap_t *)IMAP_ADDR;
-	cp = (cpm8xx_t *)&(immap->im_cpm);
-
-	/* Reset the CPM.  This is necessary on the 860 processors
-	 * that may have started the SCC1 ethernet without relocating
-	 * the IIC.
-	 * This also stops the Ethernet in case we were loaded by a
-	 * BOOTP rom monitor.
-	 */
-	cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
-
-	/* Wait for it.
-	*/
-	while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG));
-
-	/* Remove any microcode patches.  We will install our own
-	 * later.
-	 */
-	cp->cp_cpmcr1 = 0;
-	cp->cp_cpmcr2 = 0;
-	cp->cp_cpmcr3 = 0;
-	cp->cp_cpmcr4 = 0;
-	cp->cp_rccr = 0;
-
-	iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
-	i2c = (i2c8xx_t *)&(immap->im_i2c);
-
-	/* Initialize Port B IIC pins.
-	*/
-	cp->cp_pbpar |= 0x00000030;
-	cp->cp_pbdir |= 0x00000030;
-	cp->cp_pbodr |= 0x00000030;
-
-	/* Initialize the parameter ram.
-	*/
-
-	/* Allocate space for a two transmit and one receive buffer
-	 * descriptor in the DP ram.
-	 * For now, this address seems OK, but it may have to
-	 * change with newer versions of the firmware.
-	 */
-	dpaddr = 0x0840;
-
-	/* Set up the IIC parameters in the parameter ram.
-	*/
-	iip->iic_tbase = dpaddr;
-	iip->iic_rbase = dpaddr + (2 * sizeof(cbd_t));
-
-	iip->iic_tfcr = SMC_EB;
-	iip->iic_rfcr = SMC_EB;
-
-	/* This should really be done by the reader/writer.
-	*/
-	iip->iic_mrblr = 128;
-
-	/* Initialize Tx/Rx parameters.
-	*/
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	/* Select an arbitrary address.  Just make sure it is unique.
-	*/
-	i2c->i2c_i2add = 0x34;
-
-	/* Make clock run maximum slow.
-	*/
-	i2c->i2c_i2brg = 7;
-
-	/* Disable interrupts.
-	*/
-	i2c->i2c_i2cmr = 0;
-	i2c->i2c_i2cer = 0xff;
-
-	/* Enable SDMA.
-	*/
-	immap->im_siu_conf.sc_sdcr = 1;
-
-	iic_init_done = 1;
-}
-
-/* Read from IIC.
- * Caller provides device address, memory buffer, and byte count.
- */
-static	u_char	iitemp[32];
-
-void
-iic_read(uint devaddr, u_char *buf, uint offset, uint count)
-{
-	volatile iic_t *iip;
-	volatile i2c8xx_t *i2c;
-	volatile cbd_t	*tbdf, *rbdf;
-	volatile cpm8xx_t	*cp;
-	volatile immap_t	*immap;
-	u_char			*tb;
-	uint	dpaddr, temp;
-
-	/* If the interface has not been initialized, do that now.
-	*/
-	if (!iic_init_done)
-		iic_init();
-
-	immap = (immap_t *)IMAP_ADDR;
-	cp = (cpm8xx_t *)&(immap->im_cpm);
-
-	iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
-	i2c = (i2c8xx_t *)&(immap->im_i2c);
-
-	tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
-	rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
-
-	/* Send a "dummy write" operation.  This is a write request with
-	 * only the offset sent, followed by another start condition.
-	 * This will ensure we start reading from the first location
-	 * of the EEPROM.
-	 */
-	tb = iitemp;
-	tb = (u_char *)(((uint)tb + 15) & ~15);
-	tbdf->cbd_bufaddr = tb;
-	*tb = devaddr & 0xfe;	/* Device address */
-	*(tb+1) = offset;		/* Offset */
-	tbdf->cbd_datlen = 2;		/* Length */
-	tbdf->cbd_sc =
-	      BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
-
-	i2c->i2c_i2mod = 1;	/* Enable */
-	i2c->i2c_i2cer = 0xff;
-	i2c->i2c_i2com = 0x81;	/* Start master */
-
-	/* Wait for IIC transfer.
-	*/
-#if 0
-	while ((i2c->i2c_i2cer & 3) == 0);
-
-	if (tbdf->cbd_sc & BD_SC_READY)
-		printf("IIC ra complete but tbuf ready\n");
-#else
-	temp = 10000000;
-	while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
-		temp--;
-#if 0
-	/* We can't do this...there is no serial port yet!
-	*/
-	if (temp == 0) {
-		printf("Timeout reading EEPROM\n");
-		return;
-	}
-#endif
-#endif
-	
-	/* Chip errata, clear enable.
-	*/
-	i2c->i2c_i2mod = 0;
-
-	/* To read, we need an empty buffer of the proper length.
-	 * All that is used is the first byte for address, the remainder
-	 * is just used for timing (and doesn't really have to exist).
-	 */
-	tbdf->cbd_bufaddr = tb;
-	*tb = devaddr | 1;	/* Device address */
-	rbdf->cbd_bufaddr = (uint)buf;		/* Desination buffer */
-	tbdf->cbd_datlen = rbdf->cbd_datlen = count + 1;	/* Length */
-	tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
-	rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
-
-	/* Chip bug, set enable here.
-	*/
-	i2c->i2c_i2mod = 1;	/* Enable */
-	i2c->i2c_i2cer = 0xff;
-	i2c->i2c_i2com = 0x81;	/* Start master */
-
-	/* Wait for IIC transfer.
-	*/
-#if 0
-	while ((i2c->i2c_i2cer & 1) == 0);
-
-	if (rbdf->cbd_sc & BD_SC_EMPTY)
-		printf("IIC read complete but rbuf empty\n");
-#else
-	temp = 10000000;
-	while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
-		temp--;
-#endif
-	
-	/* Chip errata, clear enable.
-	*/
-	i2c->i2c_i2mod = 0;
-}
-
-/* Because I didn't find anything that would do this.......
-*/
-u_char
-aschex_to_byte(u_char *cp)
-{
-	u_char	byte, c;
-
-	c = *cp++;
-
-	if ((c >= 'A') && (c <= 'F')) {
-		c -= 'A';
-		c += 10;
-	}
-	else if ((c >= 'a') && (c <= 'f')) {
-		c -= 'a';
-		c += 10;
-	}
-	else {
-		c -= '0';
-	}
-	
-	byte = c * 16;
-
-	c = *cp;
-
-	if ((c >= 'A') && (c <= 'F')) {
-		c -= 'A';
-		c += 10;
-	}
-	else if ((c >= 'a') && (c <= 'f')) {
-		c -= 'a';
-		c += 10;
-	}
-	else {
-		c -= '0';
-	}
-	
-	byte += c;
-
-	return(byte);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/m8260_tty.c linux/arch/ppc/mbxboot/m8260_tty.c
--- v2.4.4/linux/arch/ppc/mbxboot/m8260_tty.c	Mon Jun 19 17:59:36 2000
+++ linux/arch/ppc/mbxboot/m8260_tty.c	Wed Dec 31 16:00:00 1969
@@ -1,201 +0,0 @@
-
-
-/* Minimal serial functions needed to send messages out the serial
- * port on SMC1.
- */
-#include <linux/types.h>
-#include "asm/mpc8260.h"
-#include "asm/cpm_8260.h"
-
-uint	no_print;
-extern char	*params[];
-extern int	nparams;
-static		u_char	cons_hold[128], *sgptr;
-static		int	cons_hold_cnt;
-
-void
-serial_init(bd_t *bd)
-{
-	volatile smc_t		*sp;
-	volatile smc_uart_t	*up;
-	volatile cbd_t	*tbdf, *rbdf;
-	volatile immap_t	*ip;
-	volatile iop8260_t	*io;
-	volatile cpm8260_t	*cp;
-	uint	dpaddr, memaddr;
-
-	ip = (immap_t *)IMAP_ADDR;
-
-	sp = (smc_t*)&(ip->im_smc[0]);
-	*(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
-	up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
-
-	cp = &ip->im_cpm;
-	io = &ip->im_ioport;
-
-	/* Disable transmitter/receiver.
-	*/
-	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-
-	/* Use Port D for SMC1 instead of other functions.
-	*/
-	io->iop_ppard |= 0x00c00000;
-	io->iop_pdird |= 0x00400000;
-	io->iop_pdird &= ~0x00800000;
-	io->iop_psord &= ~0x00c00000;
-
-	/* Allocate space for two buffer descriptors in the DP ram.
-	 * For now, this address seems OK, but it may have to
-	 * change with newer versions of the firmware.
-	 */
-	dpaddr = 0x0800;
-
-	/* Grab a few bytes from the top of memory.
-	 */
-#if 1
-	memaddr = (bd->bi_memsize - 256) & ~15;
-#else
-	memaddr = 0x0f002c00;
-#endif
-
-	/* Set the physical address of the host memory buffers in
-	 * the buffer descriptors.
-	 */
-	rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
-	rbdf->cbd_bufaddr = memaddr;
-	rbdf->cbd_sc = 0;
-	tbdf = rbdf + 1;
-	tbdf->cbd_bufaddr = memaddr+128;
-	tbdf->cbd_sc = 0;
-
-	/* Set up the uart parameters in the parameter ram.
-	*/
-	up->smc_rbase = dpaddr;
-	up->smc_tbase = dpaddr+sizeof(cbd_t);
-	up->smc_rfcr = CPMFCR_EB;
-	up->smc_tfcr = CPMFCR_EB;
-	up->smc_brklen = 0;
-	up->smc_brkec = 0;
-	up->smc_brkcr = 0;
-
-	/* Set UART mode, 8 bit, no parity, one stop.
-	 * Enable receive and transmit.
-	 */
-	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
-
-	/* Mask all interrupts and remove anything pending.
-	*/
-	sp->smc_smcm = 0;
-	sp->smc_smce = 0xff;
-
-	/* Set up the baud rate generator.
-	 */
-	ip->im_clkrst.car_sccr = 0;	/* DIV 4 BRG */
-	ip->im_cpmux.cmx_smr = 0;
-	ip->im_brgc1 =
-		((((bd->bi_brgfreq * 1000000)/16) / bd->bi_baudrate) << 1) |
-								CPM_BRG_EN;
-
-	/* Make the first buffer the only buffer.
-	*/
-	tbdf->cbd_sc |= BD_SC_WRAP;
-	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
-
-#if 0
-	/* Single character receive.
-	*/
-	up->smc_mrblr = 1;
-	up->smc_maxidl = 0;
-#else
-	up->smc_mrblr = 128;
-	up->smc_maxidl = 8;
-#endif
-
-	/* Initialize Tx/Rx parameters.
-	*/
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	/* Enable transmitter/receiver.
-	*/
-	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-}
-
-void
-serial_putchar(const char c)
-{
-	volatile cbd_t		*tbdf;
-	volatile char		*buf;
-	volatile smc_uart_t	*up;
-	volatile immap_t	*ip;
-	extern bd_t		*board_info;
-
-	ip = (immap_t *)IMAP_ADDR;
-	up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
-	tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
-
-	/* Wait for last character to go.
-	*/
-	buf = (char *)tbdf->cbd_bufaddr;
-	while (tbdf->cbd_sc & BD_SC_READY);
-
-	*buf = c;
-	tbdf->cbd_datlen = 1;
-	tbdf->cbd_sc |= BD_SC_READY;
-}
-
-char
-serial_getc()
-{
-	char	c;
-
-	if (cons_hold_cnt <= 0) {
-		cons_hold_cnt = serial_readbuf(cons_hold);
-		sgptr = cons_hold;
-	}
-	c = *sgptr++;
-	cons_hold_cnt--;
-
-	return(c);
-}
-
-int
-serial_readbuf(u_char *cbuf)
-{
-	volatile cbd_t		*rbdf;
-	volatile char		*buf;
-	volatile smc_uart_t	*up;
-	volatile immap_t	*ip;
-	int	i, nc;
-
-	ip = (immap_t *)IMAP_ADDR;
-
-	up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
-	rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
-
-	/* Wait for character to show up.
-	*/
-	buf = (char *)rbdf->cbd_bufaddr;
-	while (rbdf->cbd_sc & BD_SC_EMPTY);
-	nc = rbdf->cbd_datlen;
-	for (i=0; i<nc; i++)
-		*cbuf++ = *buf++;
-	rbdf->cbd_sc |= BD_SC_EMPTY;
-
-	return(nc);
-}
-
-int
-serial_tstc()
-{
-	volatile cbd_t		*rbdf;
-	volatile smc_uart_t	*up;
-	volatile immap_t	*ip;
-
-	ip = (immap_t *)IMAP_ADDR;
-	up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
-	rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
-
-	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/m8xx_tty.c linux/arch/ppc/mbxboot/m8xx_tty.c
--- v2.4.4/linux/arch/ppc/mbxboot/m8xx_tty.c	Thu Jul 13 09:42:51 2000
+++ linux/arch/ppc/mbxboot/m8xx_tty.c	Wed Dec 31 16:00:00 1969
@@ -1,276 +0,0 @@
-
-
-/* Minimal serial functions needed to send messages out the serial
- * port on the MBX console.
- *
- * The MBX uxes SMC1 for the serial port.  We reset the port and use
- * only the first BD that EPPC-Bug set up as a character FIFO.
- *
- * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug
- * use COM1 instead of SMC1 as the console port.  This kinda sucks
- * for the rest of the kernel, so here we force the use of SMC1 again.
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <asm/uaccess.h>
-#include <asm/mpc8xx.h>
-#include "../8xx_io/commproc.h"
-
-#ifdef CONFIG_MBX
-#define MBX_CSR1	((volatile u_char *)0xfa100000)
-#define CSR1_COMEN	(u_char)0x02
-#endif
-
-#ifdef TQM_SMC2_CONSOLE
-#define PROFF_CONS	PROFF_SMC2
-#define CPM_CR_CH_CONS	CPM_CR_CH_SMC2
-#define SMC_INDEX	1
-static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport);
-#else
-#define PROFF_CONS	PROFF_SMC1
-#define CPM_CR_CH_CONS	CPM_CR_CH_SMC1
-#define SMC_INDEX	0
-#endif
-
-static cpm8xx_t	*cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
-
-void
-serial_init(bd_t *bd)
-{
-	volatile smc_t		*sp;
-	volatile smc_uart_t	*up;
-	volatile cbd_t	*tbdf, *rbdf;
-	volatile cpm8xx_t	*cp;
-	uint	dpaddr, memaddr;
-
-	cp = cpmp;
-	sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]);
-	up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS];
-
-	/* Disable transmitter/receiver.
-	*/
-	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-
-#ifndef CONFIG_MBX
-	{
-	/* Initialize SMCx and use it for the console port.
-	 */
-
-	/* Enable SDMA.
-	*/
-	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
-
-#ifdef TQM_SMC2_CONSOLE
-	/* Use Port A for SMC2 instead of other functions.
-	*/
-	iopp->iop_papar |=  0x00c0;
-	iopp->iop_padir &= ~0x00c0;
-	iopp->iop_paodr &= ~0x00c0;
-#else
-	/* Use Port B for SMCs instead of other functions.
-	*/
-	cp->cp_pbpar |= 0x00000cc0;
-	cp->cp_pbdir &= ~0x00000cc0;
-	cp->cp_pbodr &= ~0x00000cc0;
-#endif
-
-	/* Allocate space for two buffer descriptors in the DP ram.
-	 * For now, this address seems OK, but it may have to
-	 * change with newer versions of the firmware.
-	 */
-	dpaddr = 0x0800;
-
-	/* Grab a few bytes from the top of memory for SMC FIFOs.
-	 */
-	memaddr = (bd->bi_memsize - 32) & ~15;
-
-	/* Set the physical address of the host memory buffers in
-	 * the buffer descriptors.
-	 */
-	rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
-	rbdf->cbd_bufaddr = memaddr;
-	rbdf->cbd_sc = 0;
-	tbdf = rbdf + 1;
-	tbdf->cbd_bufaddr = memaddr+4;
-	tbdf->cbd_sc = 0;
-
-	/* Set up the uart parameters in the parameter ram.
-	*/
-	up->smc_rbase = dpaddr;
-	up->smc_tbase = dpaddr+sizeof(cbd_t);
-	up->smc_rfcr = SMC_EB;
-	up->smc_tfcr = SMC_EB;
-
-	/* Set UART mode, 8 bit, no parity, one stop.
-	 * Enable receive and transmit.
-	 */
-	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
-
-	/* Mask all interrupts and remove anything pending.
-	*/
-	sp->smc_smcm = 0;
-	sp->smc_smce = 0xff;
-
-	/* Set up the baud rate generator.
-	 * See 8xx_io/commproc.c for details.
-	 * This wires BRG1 to SMC1 and BRG2 to SMC2;
-	 */
-	cp->cp_simode = 0x10000000;
-#ifdef TQM_SMC2_CONSOLE
-	cp->cp_brgc2 =
-#else
-	cp->cp_brgc1 =
-#endif
-		((((bd->bi_intfreq * 1000000)/16) / bd->bi_baudrate) << 1) | CPM_BRG_EN;
-
-#else /* CONFIG_MBX */
-	if (*MBX_CSR1 & CSR1_COMEN) {
-		/* COM1 is enabled.  Initialize SMC1 and use it for
-		 * the console port.
-		 */
-
-		/* Enable SDMA.
-		*/
-		((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
-
-		/* Use Port B for SMCs instead of other functions.
-		*/
-		cp->cp_pbpar |= 0x00000cc0;
-		cp->cp_pbdir &= ~0x00000cc0;
-		cp->cp_pbodr &= ~0x00000cc0;
-
-		/* Allocate space for two buffer descriptors in the DP ram.
-		 * For now, this address seems OK, but it may have to
-		 * change with newer versions of the firmware.
-		 */
-		dpaddr = 0x0800;
-
-		/* Grab a few bytes from the top of memory.  EPPC-Bug isn't
-		 * running any more, so we can do this.
-		 */
-		memaddr = (bd->bi_memsize - 32) & ~15;
-
-		/* Set the physical address of the host memory buffers in
-		 * the buffer descriptors.
-		 */
-		rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
-		rbdf->cbd_bufaddr = memaddr;
-		rbdf->cbd_sc = 0;
-		tbdf = rbdf + 1;
-		tbdf->cbd_bufaddr = memaddr+4;
-		tbdf->cbd_sc = 0;
-
-		/* Set up the uart parameters in the parameter ram.
-		*/
-		up->smc_rbase = dpaddr;
-		up->smc_tbase = dpaddr+sizeof(cbd_t);
-		up->smc_rfcr = SMC_EB;
-		up->smc_tfcr = SMC_EB;
-
-		/* Set UART mode, 8 bit, no parity, one stop.
-		 * Enable receive and transmit.
-		 */
-		sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
-
-		/* Mask all interrupts and remove anything pending.
-		*/
-		sp->smc_smcm = 0;
-		sp->smc_smce = 0xff;
-
-		/* Set up the baud rate generator.
-		 * See 8xx_io/commproc.c for details.
-		 */
-		cp->cp_simode = 0x10000000;
-		cp->cp_brgc1 =
-			((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN;
-
-		/* Enable SMC1 for console output.
-		*/
-		*MBX_CSR1 &= ~CSR1_COMEN;
-	}
-	else {
-#endif /* ndef CONFIG_MBX */
-		/* SMCx is used as console port.
-		*/
-		tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
-		rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase];
-
-		/* Issue a stop transmit, and wait for it.
-		*/
-		cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS,
-					CPM_CR_STOP_TX) | CPM_CR_FLG;
-		while (cp->cp_cpcr & CPM_CR_FLG);
-	}
-
-	/* Make the first buffer the only buffer.
-	*/
-	tbdf->cbd_sc |= BD_SC_WRAP;
-	rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
-
-	/* Single character receive.
-	*/
-	up->smc_mrblr = 1;
-	up->smc_maxidl = 0;
-
-	/* Initialize Tx/Rx parameters.
-	*/
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	/* Enable transmitter/receiver.
-	*/
-	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-}
-
-void
-serial_putchar(const char c)
-{
-	volatile cbd_t		*tbdf;
-	volatile char		*buf;
-	volatile smc_uart_t	*up;
-
-	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
-	tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
-
-	/* Wait for last character to go.
-	*/
-	buf = (char *)tbdf->cbd_bufaddr;
-	while (tbdf->cbd_sc & BD_SC_READY);
-
-	*buf = c;
-	tbdf->cbd_datlen = 1;
-	tbdf->cbd_sc |= BD_SC_READY;
-}
-
-char
-serial_getc()
-{
-	volatile cbd_t		*rbdf;
-	volatile char		*buf;
-	volatile smc_uart_t	*up;
-	char			c;
-
-	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
-	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
-
-	/* Wait for character to show up.
-	*/
-	buf = (char *)rbdf->cbd_bufaddr;
-	while (rbdf->cbd_sc & BD_SC_EMPTY);
-	c = *buf;
-	rbdf->cbd_sc |= BD_SC_EMPTY;
-
-	return(c);
-}
-
-int
-serial_tstc()
-{
-	volatile cbd_t		*rbdf;
-	volatile smc_uart_t	*up;
-
-	up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
-	rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
-
-	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/misc.c linux/arch/ppc/mbxboot/misc.c
--- v2.4.4/linux/arch/ppc/mbxboot/misc.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/mbxboot/misc.c	Wed Dec 31 16:00:00 1969
@@ -1,476 +0,0 @@
-/*
- * misc.c
- *
- * $Id: misc.c,v 1.2 1999/09/14 05:55:29 dmalek Exp $
- * 
- * Adapted for PowerPC by Gary Thomas
- *
- * Rewritten by Cort Dougan (cort@cs.nmt.edu)
- * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
- */
-
-#include <linux/types.h>
-#include "../coffboot/zlib.h"
-#include "asm/residual.h"
-#include <linux/elf.h>
-#include <linux/config.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/mmu.h>
-#ifdef CONFIG_8xx
-#include <asm/mpc8xx.h>
-#endif
-#ifdef CONFIG_8260
-#include <asm/mpc8260.h>
-#endif
-
-/*
- * The following references are needed to cause the linker to pull in the
- * gzimage.o and rdimage.o files.  These object files are special,
- * since they get placed into the .gzimage and .rdimage ELF sections 
- * of the zvmlinux and zvmlinux.initrd files.
- */
-extern char dummy_for_gzimage;
-extern char dummy_for_rdimage;
-
-/*
- * Please send me load/board info and such data for hardware not
- * listed here so I can keep track since things are getting tricky
- * with the different load addrs with different firmware.  This will
- * help to avoid breaking the load/boot process.
- * -- Cort
- */
-char *avail_ram;
-char *end_avail;
-
-/* See comment below.....
-*/
-unsigned int initrd_offset, initrd_size;
-
-/* Because of the limited amount of memory on embedded, it presents
- * loading problems.  The biggest is that we load this boot program
- * into a relatively low memory address, and the Linux kernel Bss often
- * extends into this space when it get loaded.  When the kernel starts
- * and zeros the BSS space, it also writes over the information we
- * save here and pass to the kernel (command line and board info).
- * On these boards, we grab some known memory holes to hold this information.
- */
-char	cmd_buf[256];
-char	*cmd_line = cmd_buf;
-
-char	*root_string = "root=/dev/nfs rw";
-char	*nfsaddrs_string = "nfsaddrs=";
-char	*nfsroot_string = "nfsroot=";
-char	*defroot_string = "/sys/mbxroot";
-char	*ramroot_string = "root=/dev/ram";
-int	do_ipaddrs(char **cmd_cp, int echo);
-void	do_nfsroot(char **cmd_cp, char *dp);
-int	strncmp(const char * cs,const char * ct,size_t count);
-char	*strrchr(const char * s, int c);
-
-bd_t hold_resid_buf;
-bd_t *hold_residual = &hold_resid_buf;
-unsigned long initrd_start = 0, initrd_end = 0;
-char *zimage_start;
-int zimage_size;
-
-void puts(const char *);
-void putc(const char c);
-void puthex(unsigned long val);
-void _bcopy(char *src, char *dst, int len);
-void * memcpy(void * __dest, __const void * __src,
-			    int __n);
-void gunzip(void *, int, unsigned char *, int *);
-
-void pause()
-{
-	puts("pause\n");
-}
-
-void exit()
-{
-	puts("exit\n");
-	while(1); 
-}
-
-/* The MPC8xx is just the serial port.
-*/
-tstc(void)
-{
-        return (serial_tstc());
-}
-
-getc(void)
-{
-        while (1) {
-                if (serial_tstc()) return (serial_getc());
-        }
-}
-
-void 
-putc(const char c)
-{
-        serial_putchar(c);
-}
-
-void puts(const char *s)
-{
-        char c;
-
-        while ( ( c = *s++ ) != '\0' ) {
-                serial_putchar(c);
-                if ( c == '\n' )
-                        serial_putchar('\r');
-        }
-}
-
-void * memcpy(void * __dest, __const void * __src,
-			    int __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++) d[i] = s[i];
-}
-
-int memcmp(__const void * __dest, __const void * __src,
-			    int __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++, d++, s++)
-	{
-		if (*d != *s)
-		{
-			return (*s - *d);
-		}
-	}
-	return (0);
-}
-
-void error(char *x)
-{
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
-
-	while(1);	/* Halt */
-}
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-	void *p = avail_ram;
-	
-	size *= items;
-	size = (size + 7) & -8;
-	avail_ram += size;
-	if (avail_ram > end_avail) {
-		puts("oops... out of memory\n");
-		pause();
-	}
-	return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-	z_stream s;
-	int r, i, flags;
-	
-	/* skip header */
-	i = 10;
-	flags = src[3];
-	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-		puts("bad gzipped data\n");
-		exit();
-	}
-	if ((flags & EXTRA_FIELD) != 0)
-		i = 12 + src[10] + (src[11] << 8);
-	if ((flags & ORIG_NAME) != 0)
-		while (src[i++] != 0)
-			;
-	if ((flags & COMMENT) != 0)
-		while (src[i++] != 0)
-			;
-	if ((flags & HEAD_CRC) != 0)
-		i += 2;
-	if (i >= *lenp) {
-		puts("gunzip: ran out of data in header\n");
-		exit();
-	}
-	
-	s.zalloc = zalloc;
-	s.zfree = zfree;
-	r = inflateInit2(&s, -MAX_WBITS);
-	if (r != Z_OK) {
-		puts("inflateInit2 returned %d\n");
-		exit();
-	}
-	s.next_in = src + i;
-	s.avail_in = *lenp - i;
-	s.next_out = dst;
-	s.avail_out = dstlen;
-	r = inflate(&s, Z_FINISH);
-	if (r != Z_OK && r != Z_STREAM_END) {
-		puts("inflate returned ");
-		puthex(r);
-		puts("\n");
-		exit();
-	}
-	*lenp = s.next_out - (unsigned char *) dst;
-	inflateEnd(&s);
-}
-
-unsigned char sanity[0x2000];
-
-unsigned long
-decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
-{
-	int timer;
-	extern unsigned long start;
-	char *cp, ch;
-	unsigned long i;
-	char	*dp;
-
-#ifdef CONFIG_8260
-	/* I don't know why I didn't do it this way on the 8xx.......
-	*/
-	embed_config(bp);
-	serial_init(bp);
-#endif
-
-	/* These values must be variables.  If not, the compiler optimizer
-	 * will remove some code, causing the size of the code to vary
-	 * when these values are zero.  This is bad because we first
-	 * compile with these zero to determine the size and offsets
-	 * in an image, than compile again with these set to the proper
-	 * discovered value.....Ya know, we used to read these from the
-	 * header a long time ago.....
-	 */
-	initrd_offset = INITRD_OFFSET;
-	initrd_size = INITRD_SIZE;
-
-	/* Grab some space for the command line and board info.  Since
-	 * we no longer use the ELF header, but it was loaded, grab
-	 * that space.
-	 */
-#ifdef CONFIG_MBX
-	cmd_line = (char *)(load_addr - 0x10000);
-
-	/* To be like everyone else, we need one too, although this
-	 * board information is passed from the boot rom.
-	 */
-	bp->bi_baudrate = 9600;
-#else
-	cmd_line = (char *)(0x200000);
-#endif
-	hold_residual = (bd_t *)(cmd_line + sizeof(cmd_buf));
-	/* copy board data */
-	if (bp)
-		memcpy(hold_residual,bp,sizeof(bd_t));
-
-	/* Set end of memory available to us.  It is always the highest
-	 * memory address provided by the board information.
-	 */
-	end_avail = (char *)(bp->bi_memsize);
-
-	puts("loaded at:     "); puthex(load_addr);
-	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
-	if ( (unsigned long)load_addr != (unsigned long)&start )
-	{
-		puts("relocated to:  "); puthex((unsigned long)&start);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
-		puts("\n");
-	}
-
-	if ( bp )
-	{
-		puts("board data at: "); puthex((unsigned long)bp);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)bp + sizeof(bd_t)));
-		puts("\n");
-		puts("relocated to:  ");
-		puthex((unsigned long)hold_residual);
-		puts(" ");
-		puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
-		puts("\n");
-	}
-
-	/* we have to subtract 0x10000 here to correct for objdump including the
-	   size of the elf header which we strip -- Cort */
-	zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
-	zimage_size = ZIMAGE_SIZE;
-
-	if ( initrd_offset )
-		initrd_start = load_addr - 0x10000 + initrd_offset;
-	else
-		initrd_start = 0;
-	initrd_end = initrd_size + initrd_start;
-
-	/*
-	 * setup avail_ram - this is the first part of ram usable
-	 * by the uncompress code. -- Cort
-	 */
-	avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
-	if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
-		&& (load_addr <= 0x01000000) )
-		avail_ram = (char *)(load_addr+(num_words*4));
-	if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
-		&& (load_addr <= 0x01000000) )
-		avail_ram = (char *)((unsigned long)&start+(num_words*4));
-	
-	/* relocate zimage */
-	puts("zimage at:     "); puthex((unsigned long)zimage_start);
-	puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
-	/*
-	 * There is no reason (yet) to relocate zImage for embedded boards.
-	 * To support boot from flash rom on 8xx embedded boards, I
-	 * assume if zimage start is over 16M we are booting from flash.
-	 * In this case, avilable ram will start just above the space we
-	 * have allocated for the command buffer and board information.
-	 */
-	if ((unsigned long)zimage_start > 0x01000000)
-		avail_ram = (char *)PAGE_ALIGN((unsigned long)hold_residual + sizeof(bd_t));
-
-	/* relocate initrd */
-	if ( initrd_start )
-	{
-		puts("initrd at:     "); puthex(initrd_start);
-		puts(" "); puthex(initrd_end); puts("\n");
-
-		/* We only have to relocate initrd if we find it is in Flash
-		 * rom.  This is because the kernel thinks it can toss the
-		 * pages into the free memory pool after it is done.  Use
-		 * the same 16M test.
-		 */
-		if ((unsigned long)initrd_start > 0x01000000) {
-			memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
-				(void *)initrd_start,
-				initrd_size );
-			initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE);
-			initrd_end = initrd_start + initrd_size;
-			end_avail = (char *)initrd_start;
-			puts("relocated to:  "); puthex(initrd_start);
-			puts(" "); puthex(initrd_end); puts("\n");
-		}
-		else {
-			avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end);
-		}
-	}
-
-
-	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
-	puthex((unsigned long)end_avail); puts("\n");
-
-	puts("\nLinux/PPC load: ");
-	timer = 0;
-	cp = cmd_line;
-
-	while (timer++ < 5*1000) {
-		if (tstc()) {
-			while ((ch = getc()) != '\n' && ch != '\r') {
-				if (ch == '\b') {
-					if (cp != cmd_line) {
-						cp--;
-						puts("\b \b");
-					}
-				} else {
-					*cp++ = ch;
-					putc(ch);
-				}
-			}
-			break;  /* Exit 'timer' loop */
-		}
-		udelay(1000);  /* 1 msec */
-	}
-	*cp = 0;
-
-	/* If the command line is not filled in, we will automatically
-	 * create the default boot.
-	 */
-	if (cmd_line[0] == 0) {
-
-		/* An initrd on these boards means we booted from Flash
-		 * ROM and want to use the ramdisk as the root file system.
-		 * Otherwise, we perform a diskless NFS boot.
-		 */
-		if (initrd_start)
-			dp = ramroot_string;
-		else
-			dp = root_string;
-		while (*dp != 0)
-			*cp++ = *dp++;
-		*cp = 0;
-	}
-
-	puts("\n");
-
-	puts("Uncompressing Linux...");
-
-	gunzip(0, 0x400000, zimage_start, &zimage_size);
-	puts("done.\n");
-	puts("Now booting the kernel\n");
-	return (unsigned long)hold_residual;
-}
-
-void puthex(unsigned long val)
-{
-	unsigned char buf[10];
-	int i;
-	for (i = 7;  i >= 0;  i--)
-	{
-		buf[i] = "0123456789ABCDEF"[val & 0x0F];
-		val >>= 4;
-	}
-	buf[8] = '\0';
-	puts(buf);
-}
-
-/*
- * PCI/ISA I/O support
- */
-
-volatile unsigned char *ISA_io  = (unsigned char *)0x80000000;
-volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
-
-void
-outb(int port, char val)
-{
-	/* Ensure I/O operations complete */
-	__asm__ volatile("eieio");
-	ISA_io[port] = val;
-}
-
-unsigned char
-inb(int port)
-{
-	/* Ensure I/O operations complete */
-	__asm__ volatile("eieio");
-	return (ISA_io[port]);
-}
-
-unsigned long
-local_to_PCI(unsigned long addr)
-{
-	return ((addr & 0x7FFFFFFF) | 0x80000000);
-}
-
-void
-_bcopy(char *src, char *dst, int len)
-{
-	while (len--) *dst++ = *src++;
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/offset linux/arch/ppc/mbxboot/offset
--- v2.4.4/linux/arch/ppc/mbxboot/offset	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/mbxboot/offset	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux| awk '{print $6}'`
-echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/pci.c linux/arch/ppc/mbxboot/pci.c
--- v2.4.4/linux/arch/ppc/mbxboot/pci.c	Tue May  2 13:05:40 2000
+++ linux/arch/ppc/mbxboot/pci.c	Wed Dec 31 16:00:00 1969
@@ -1,252 +0,0 @@
-/* Stand alone funtions for QSpan Tundra support.
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <asm/mpc8xx.h>
-
-/* To map PCI devices, you first write 0xffffffff into the device
- * base address registers.  When the register is read back, the
- * number of most significant '1' bits describes the amount of address
- * space needed for mapping.  If the most significant bit is not set,
- * either the device does not use that address register, or it has
- * a fixed address that we can't change.  After the address is assigned,
- * the command register has to be written to enable the card.
- */
-typedef struct {
-	u_char	pci_bus;
-	u_char	pci_devfn;
-	ushort	pci_command;
-	uint	pci_addrs[6];
-} pci_map_t;
-
-/* We should probably dynamically allocate these structures.
-*/
-#define MAX_PCI_DEVS	32
-int	pci_dev_cnt;
-pci_map_t	pci_map[MAX_PCI_DEVS];
-
-void pci_conf_write(int bus, int device, int func, int reg, uint writeval);
-void pci_conf_read(int bus, int device, int func, int reg, void *readval);
-void probe_addresses(int bus, int devfn);
-void map_pci_addrs(void);
-
-/* This is a really stripped version of PCI bus scan.  All we are
- * looking for are devices that exist.
- */
-pci_scanner(int addr_probe)
-{
-	unsigned int devfn, l, max, class, bus_number;
-	unsigned char cmd, irq, tmp, hdr_type, is_multi;
-	int reg;
-
-	is_multi = 0;
-	bus_number = 0;
-	for (devfn = 0; devfn < 0xff; ++devfn) {
-		/* The device numbers are comprised of upper 5 bits of
-		 * device number and lower 3 bits of multi-function number.
-		 */
-		if ((devfn & 7) && !is_multi) {
-			/* Don't scan multifunction addresses if this is
-			 * not a multifunction device.
-			 */
-			continue;
-		}
-
-		/* Read the header to determine card type.
-		*/
-		qs_pci_read_config_byte(bus_number, devfn, PCI_HEADER_TYPE,
-								&hdr_type);
-
-		/* If this is a base device number, check the header to
-		 * determine if it is mulifunction.
-		 */
-		if ((devfn & 7) == 0)
-			is_multi = hdr_type & 0x80;
-
-		/* Check to see if the board is really in the slot.
-		*/
-		qs_pci_read_config_dword(bus_number, devfn, PCI_VENDOR_ID, &l);
-		/* some broken boards return 0 if a slot is empty: */
-		if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff ||
-							l == 0xffff0000) {
-			/* Nothing there.
-			*/
-			is_multi = 0;
-			continue;
-		}
-
-		/* If we are not performing an address probe,
-		 * just simply print out some information.
-		 */
-		if (!addr_probe) {
-			qs_pci_read_config_dword(bus_number, devfn,
-						PCI_CLASS_REVISION, &class);
-
-			class >>= 8;	    /* upper 3 bytes */
-
-#if 0
-			printf("Found (%3d:%d): vendor 0x%04x, device 0x%04x, class 0x%06x\n",
-				(devfn >> 3), (devfn & 7),
-				(l & 0xffff),  (l >> 16) & 0xffff, class);
-#else
-			puts("Found ("); puthex(devfn >> 3);
-			puts(":"); puthex(devfn & 7);
-			puts("): vendor "); puthex(l & 0xffff);
-			puts(", device "); puthex((l >> 16) & 0xffff);
-			puts(", class "); puthex(class); puts("\n");
-#endif
-		}
-		else {
-			/* If this is a "normal" device, build address list.
-			*/
-			if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL)
-				probe_addresses(bus_number, devfn);
-		}
-	}
-
-	/* Now map the boards.
-	*/
-	if (addr_probe)
-		map_pci_addrs();
-}
-
-/* Probe addresses for the specified device.  This is a destructive
- * operation because it writes the registers.
- */
-void
-probe_addresses(bus, devfn)
-{
-	int	i;
-	uint	pciaddr;
-	ushort	pcicmd;
-	pci_map_t	*pm;
-
-	if (pci_dev_cnt >= MAX_PCI_DEVS) {
-		puts("Too many PCI devices\n");
-		return;
-	}
-
-	pm = &pci_map[pci_dev_cnt++];
-
-	pm->pci_bus = bus;
-	pm->pci_devfn = devfn;
-
-	for (i=0; i<6; i++) {
-		qs_pci_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), -1);
-		qs_pci_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4),
-								&pciaddr);
-		pm->pci_addrs[i] = pciaddr;
-		qs_pci_read_config_word(bus, devfn, PCI_COMMAND, &pcicmd);
-		pm->pci_command = pcicmd;
-	}
-}
-
-/* Map the cards into the PCI space.  The PCI has separate memory
- * and I/O spaces.  In addition, some memory devices require mapping
- * below 1M.  The least significant 4 bits of the address register
- * provide information.  If this is an I/O device, only the LS bit
- * is used to indicate that, so I/O devices can be mapped to a two byte
- * boundard.  Memory addresses can be mapped to a 32 byte boundary.
- * The QSpan implementations usually have a 1Gbyte space for each
- * memory and I/O spaces.
- *
- * This isn't a terribly fancy algorithm.  I just map the spaces from
- * the top starting with the largest address space.  When finished,
- * the registers are written and the card enabled.
- *
- * While the Tundra can map a large address space on most boards, we
- * need to be careful because it may overlap other devices (like IMMR).
- */
-#define MEMORY_SPACE_SIZE	0x20000000
-#define IO_SPACE_SIZE		0x20000000
-
-void
-map_pci_addrs()
-{
-	uint	pci_mem_top, pci_mem_low;
-	uint	pci_io_top;
-	uint	addr_mask, reg_addr, space;
-	int	i, j;
-	pci_map_t *pm;
-
-	pci_mem_top = MEMORY_SPACE_SIZE;
-	pci_io_top = IO_SPACE_SIZE;
-	pci_mem_low = (1 * 1024 * 1024);	/* Below one meg addresses */
-
-	/* We can't map anything more than the maximum space, but test
-	 * for it anyway to catch devices out of range.
-	 */
-	addr_mask = 0x80000000;
-
-	do {
-		space = (~addr_mask) + 1;	/* Size of the space */
-		for (i=0; i<pci_dev_cnt; i++) {
-			pm = &pci_map[i];
-			for (j=0; j<6; j++) {
-				/* If the MS bit is not set, this has either
-				 * already been mapped, or is not used.
-				 */
-				reg_addr = pm->pci_addrs[j];
-				if ((reg_addr & 0x80000000) == 0)
-					continue;
-				if (reg_addr & PCI_BASE_ADDRESS_SPACE_IO) {
-					if ((reg_addr & PCI_BASE_ADDRESS_IO_MASK) != addr_mask)
-						continue;
-					if (pci_io_top < space) {
-						puts("Out of PCI I/O space\n");
-					}
-					else {
-						pci_io_top -= space;
-						pm->pci_addrs[j] = pci_io_top;
-						pm->pci_command |= PCI_COMMAND_IO;
-					}
-				}
-				else {
-					if ((reg_addr & PCI_BASE_ADDRESS_MEM_MASK) != addr_mask)
-						continue;
-
-					/* Memory space.  Test if below 1M.
-					*/
-					if (reg_addr & PCI_BASE_ADDRESS_MEM_TYPE_1M) {
-						if (pci_mem_low < space) {
-							puts("Out of PCI 1M space\n");
-						}
-						else {
-							pci_mem_low -= space;
-							pm->pci_addrs[j] = pci_mem_low;
-						}
-					}
-					else {
-						if (pci_mem_top < space) {
-							puts("Out of PCI Mem space\n");
-						}
-						else {
-							pci_mem_top -= space;
-							pm->pci_addrs[j] = pci_mem_top;
-						}
-					}
-					pm->pci_command |= PCI_COMMAND_MEMORY;
-				}
-			}
-		}
-		addr_mask >>= 1;
-		addr_mask |= 0x80000000;
-	} while (addr_mask != 0xfffffffe);
-	
-	/* Now, run the list one more time and map everything.
-	*/
-	for (i=0; i<pci_dev_cnt; i++) {
-		pm = &pci_map[i];
-		for (j=0; j<6; j++) {
-			qs_pci_write_config_dword(pm->pci_bus, pm->pci_devfn,
-				PCI_BASE_ADDRESS_0 + (j * 4), pm->pci_addrs[j]);
-		}
-
-		/* Enable memory or address mapping.
-		*/
-		qs_pci_write_config_word(pm->pci_bus, pm->pci_devfn, PCI_COMMAND,
-			pm->pci_command);
-	}
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/qspan_pci.c linux/arch/ppc/mbxboot/qspan_pci.c
--- v2.4.4/linux/arch/ppc/mbxboot/qspan_pci.c	Tue May  2 13:05:40 2000
+++ linux/arch/ppc/mbxboot/qspan_pci.c	Wed Dec 31 16:00:00 1969
@@ -1,268 +0,0 @@
-/*
- * LinuxPPC arch/ppc/kernel/qspan_pci.c   Dan Malek (dmalek@jlc.net)
- *
- * QSpan Motorola bus to PCI bridge.  The config address register
- * is located 0x500 from the base of the bridge control/status registers.
- * The data register is located at 0x504.
- * This is a two step operation.  First, the address register is written,
- * then the data register is read/written as required.
- * I don't know what to do about interrupts (yet).
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <asm/mpc8xx.h>
-
-/*
- * When reading the configuration space, if something does not respond
- * the bus times out and we get a machine check interrupt.  So, the
- * good ol' exception tables come to mind to trap it and return some
- * value.
- *
- * On an error we just return a -1, since that is what the caller wants
- * returned if nothing is present.  I copied this from __get_user_asm,
- * with the only difference of returning -1 instead of EFAULT.
- * There is an associated hack in the machine check trap code.
- *
- * The QSPAN is also a big endian device, that is it makes the PCI
- * look big endian to us.  This presents a problem for the Linux PCI
- * functions, which assume little endian.  For example, we see the
- * first 32-bit word like this:
- *	------------------------
- *	| Device ID | Vendor ID |
- *	------------------------
- * If we read/write as a double word, that's OK.  But in our world,
- * when read as a word, device ID is at location 0, not location 2 as
- * the little endian PCI would believe.  We have to switch bits in
- * the PCI addresses given to us to get the data to/from the correct
- * byte lanes.
- *
- * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5.
- * It always forces the MS bit to zero.  Therefore, dev_fn values
- * greater than 128 are returned as "no device found" errors.
- *
- * The QSPAN can only perform long word (32-bit) configuration cycles.
- * The "offset" must have the two LS bits set to zero.  Read operations
- * require we read the entire word and then sort out what should be
- * returned.  Write operations other than long word require that we
- * read the long word, update the proper word or byte, then write the
- * entire long word back.
- *
- * PCI Bridge hack.  We assume (correctly) that bus 0 is the primary
- * PCI bus from the QSPAN.  If we are called with a bus number other
- * than zero, we create a Type 1 configuration access that a downstream
- * PCI bridge will interpret.
- */
-
-#define __get_pci_config(x, addr, op)		\
-	__asm__ __volatile__(				\
-		"1:	"op" %0,0(%1)\n"		\
-		"	eieio\n"			\
-		"2:\n"					\
-		".section .fixup,\"ax\"\n"		\
-		"3:	li %0,-1\n"			\
-		"	b 2b\n"				\
-		".section __ex_table,\"a\"\n"		\
-		"	.align 2\n"			\
-		"	.long 1b,3b\n"			\
-		".text"					\
-		: "=r"(x) : "r"(addr))
-
-#define QS_CONFIG_ADDR	((volatile uint *)(PCI_CSR_ADDR + 0x500))
-#define QS_CONFIG_DATA	((volatile uint *)(PCI_CSR_ADDR + 0x504))
-
-#define mk_config_addr(bus, dev, offset) \
-	(((bus)<<16) | ((dev)<<8) | (offset & 0xfc))
-
-#define mk_config_type1(bus, dev, offset) \
-	mk_config_addr(bus, dev, offset) | 1;
-
-/* Initialize the QSpan device registers after power up.
-*/
-qspan_init()
-{
-	uint	*qptr;
-
-
-
-	qptr = (uint *)PCI_CSR_ADDR;
-
-	/* PCI Configuration/status.  Upper bits written to clear
-	 * pending interrupt or status.  Lower bits enable QSPAN as
-	 * PCI master, enable memory and I/O cycles, and enable PCI
-	 * parity error checking.
-	 * IMPORTANT:  The last two bits of this word enable PCI
-	 * master cycles into the QBus.  The QSpan is broken and can't
-	 * meet the timing specs of the PQ bus for this to work.  Therefore,
-	 * if you don't have external bus arbitration, you can't use
-	 * this function.
-	 */
-#ifdef EXTERNAL_PQ_ARB
-	qptr[1] = 0xf9000147;
-#else
-	qptr[1] = 0xf9000144;
-#endif
-
-	/* PCI Misc configuration.  Set PCI latency timer resolution
-	 * of 8 cycles, set cache size to 4 x 32.
-	 */
-	qptr[3] = 0;
-
-	/* Set up PCI Target address mapping.  Enable, Posted writes,
-	 * 2Gbyte space (processor memory controller determines actual size).
-	 */
-	qptr[64] = 0x8f000080;
-
-	/* Map processor 0x80000000 to PCI 0x00000000.
-	 * Processor address bit 1 determines I/O type access (0x80000000)
-	 * or memory type access (0xc0000000).
-	 */
-	qptr[65] = 0x80000000;
-
-	/* Enable error logging and clear any pending error status.
-	*/
-	qptr[80] = 0x90000000;
-
-	qptr[512] = 0x000c0003;
-
-	/* Set up Qbus slave image.
-	*/
-	qptr[960] = 0x01000000;
-	qptr[961] = 0x000000d1;
-	qptr[964] = 0x00000000;
-	qptr[965] = 0x000000d1;
-
-}
-
-/* Functions to support PCI bios-like features to read/write configuration
- * space.  If the function fails for any reason, a -1 (0xffffffff) value
- * must be returned.
- */
-#define DEVICE_NOT_FOUND	(-1)
-#define SUCCESSFUL		0
-
-int qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned char *val)
-{
-	uint	temp;
-	u_char	*cp;
-
-	if ((bus > 7) || (dev_fn > 127)) {
-		*val = 0xff;
-		return DEVICE_NOT_FOUND;
-	}
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	__get_pci_config(temp, QS_CONFIG_DATA, "lwz");
-
-	offset ^= 0x03;
-	cp = ((u_char *)&temp) + (offset & 0x03);
-	*val = *cp;
-	return SUCCESSFUL;
-}
-
-int qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned short *val)
-{
-	uint	temp;
-	ushort	*sp;
-
-	if ((bus > 7) || (dev_fn > 127)) {
-		*val = 0xffff;
-		return DEVICE_NOT_FOUND;
-	}
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	__get_pci_config(temp, QS_CONFIG_DATA, "lwz");
-	offset ^= 0x02;
-
-	sp = ((ushort *)&temp) + ((offset >> 1) & 1);
-	*val = *sp;
-	return SUCCESSFUL;
-}
-
-int qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned int *val)
-{
-	if ((bus > 7) || (dev_fn > 127)) {
-		*val = 0xffffffff;
-		return DEVICE_NOT_FOUND;
-	}
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	__get_pci_config(*val, QS_CONFIG_DATA, "lwz");
-	return SUCCESSFUL;
-}
-
-int qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned char val)
-{
-	uint	temp;
-	u_char	*cp;
-
-	if ((bus > 7) || (dev_fn > 127))
-		return DEVICE_NOT_FOUND;
-
-	qs_pci_read_config_dword(bus, dev_fn, offset, &temp);
-
-	offset ^= 0x03;
-	cp = ((u_char *)&temp) + (offset & 0x03);
-	*cp = val;
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	*QS_CONFIG_DATA = temp;
-
-	return SUCCESSFUL;
-}
-
-int qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned short val)
-{
-	uint	temp;
-	ushort	*sp;
-
-	if ((bus > 7) || (dev_fn > 127))
-		return DEVICE_NOT_FOUND;
-
-	qs_pci_read_config_dword(bus, dev_fn, offset, &temp);
-
-	offset ^= 0x02;
-	sp = ((ushort *)&temp) + ((offset >> 1) & 1);
-	*sp = val;
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	*QS_CONFIG_DATA = temp;
-
-	return SUCCESSFUL;
-}
-
-int qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned int val)
-{
-	if ((bus > 7) || (dev_fn > 127))
-		return DEVICE_NOT_FOUND;
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	*(unsigned int *)QS_CONFIG_DATA = val;
-
-	return SUCCESSFUL;
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/rdimage.c linux/arch/ppc/mbxboot/rdimage.c
--- v2.4.4/linux/arch/ppc/mbxboot/rdimage.c	Mon May 15 14:53:30 2000
+++ linux/arch/ppc/mbxboot/rdimage.c	Wed Dec 31 16:00:00 1969
@@ -1,8 +0,0 @@
-/*
- * rdimage.c
- *
- * Dummy file to allow a compressed initrd to be added
- * into a linker section, accessed by the boot coode
- */
-
-char dummy_for_rdimage;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mbxboot/size linux/arch/ppc/mbxboot/size
--- v2.4.4/linux/arch/ppc/mbxboot/size	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/mbxboot/size	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux | awk '{print $3}'`
-echo "0x"$OFFSET
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/4xx_tlb.c linux/arch/ppc/mm/4xx_tlb.c
--- v2.4.4/linux/arch/ppc/mm/4xx_tlb.c	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/mm/4xx_tlb.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.4xx_tlb.c 1.5 05/17/01 18:14:23 cort
+ */
+/*
  *
  *    Copyright (c) 1998-1999 TiVo, Inc.
  *      Original implementation.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/4xx_tlb.h linux/arch/ppc/mm/4xx_tlb.h
--- v2.4.4/linux/arch/ppc/mm/4xx_tlb.h	Mon Jan 10 18:25:32 2000
+++ linux/arch/ppc/mm/4xx_tlb.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.4xx_tlb.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile
--- v2.4.4/linux/arch/ppc/mm/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/mm/Makefile	Mon May 21 17:04:47 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+#
 #
 # Makefile for the linux ppc-specific parts of the memory manager.
 #
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/extable.c linux/arch/ppc/mm/extable.c
--- v2.4.4/linux/arch/ppc/mm/extable.c	Tue Sep 19 08:31:53 2000
+++ linux/arch/ppc/mm/extable.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.extable.c 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * linux/arch/ppc/mm/extable.c
  *
  * from linux/arch/i386/mm/extable.c
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.4.4/linux/arch/ppc/mm/fault.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/ppc/mm/fault.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.fault.c 1.10 05/17/01 18:14:23 cort
+ */
+/*
  *  arch/ppc/mm/fault.c
  *
  *  PowerPC version 
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.4.4/linux/arch/ppc/mm/init.c	Mon Mar 26 15:29:44 2001
+++ linux/arch/ppc/mm/init.c	Mon May 21 17:04:47 2001
@@ -1,6 +1,7 @@
 /*
- *  $Id: init.c,v 1.195 1999/10/15 16:39:39 cort Exp $
- *
+ * BK Id: SCCS/s.init.c 1.22 05/17/01 18:14:23 cort
+ */
+/*
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *
@@ -46,7 +47,6 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/residual.h>
 #include <asm/uaccess.h>
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
@@ -61,6 +61,7 @@
 #include <asm/machdep.h>
 #include <asm/setup.h>
 #include <asm/amigahw.h>
+#include <asm/gemini.h>
 
 #include "mem_pieces.h"
 
@@ -93,7 +94,6 @@
 extern char __pmac_begin, __pmac_end;
 extern char __apus_begin, __apus_end;
 extern char __openfirmware_begin, __openfirmware_end;
-struct device_node *memory_node;
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
 unsigned long avail_start;
@@ -111,19 +111,6 @@
 
 void MMU_init(void);
 void *early_get_page(void);
-unsigned long prep_find_end_of_memory(void);
-unsigned long pmac_find_end_of_memory(void);
-unsigned long apus_find_end_of_memory(void);
-extern unsigned long find_end_of_memory(void);
-#ifdef CONFIG_8xx
-unsigned long m8xx_find_end_of_memory(void);
-#endif /* CONFIG_8xx */
-#ifdef CONFIG_4xx
-unsigned long oak_find_end_of_memory(void);
-#endif
-#ifdef CONFIG_8260
-unsigned long m8260_find_end_of_memory(void);
-#endif /* CONFIG_8260 */
 static void mapin_ram(void);
 int map_page(unsigned long va, unsigned long pa, int flags);
 void set_phys_avail(unsigned long total_ram);
@@ -436,11 +423,9 @@
 	 * Should check if it is a candidate for a BAT mapping
 	 */
 
-	spin_lock(&init_mm.page_table_lock);
 	err = 0;
 	for (i = 0; i < size && err == 0; i += PAGE_SIZE)
 		err = map_page(v+i, p+i, flags);
-	spin_unlock(&init_mm.page_table_lock);
 	if (err) {
 		if (mem_init_done)
 			vfree((void *)v);
@@ -487,17 +472,21 @@
 {
 	pmd_t *pd;
 	pte_t *pg;
+	int err = -ENOMEM;
 
+	spin_lock(&init_mm.page_table_lock);
 	/* Use upper 10 bits of VA to index the first level map */
 	pd = pmd_offset(pgd_offset_k(va), va);
 	/* Use middle 10 bits of VA to index the second-level map */
 	pg = pte_alloc(&init_mm, pd, va);
-	if (pg == 0)
-		return -ENOMEM;
-	set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
-	if (mem_init_done)
-		flush_hash_page(0, va);
-	return 0;
+	if (pg != 0) {
+		err = 0;
+		set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
+		if (mem_init_done)
+			flush_hash_page(0, va);
+	}
+	spin_unlock(&init_mm.page_table_lock);
+	return err;
 }
 
 #ifndef CONFIG_8xx
@@ -668,33 +657,6 @@
 }
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-static void get_mem_prop(char *, struct mem_pieces *);
-
-#if defined(CONFIG_ALL_PPC)
-/*
- * Read in a property describing some pieces of memory.
- */
-
-static void __init get_mem_prop(char *name, struct mem_pieces *mp)
-{
-	struct reg_property *rp;
-	int s;
-
-	rp = (struct reg_property *) get_property(memory_node, name, &s);
-	if (rp == NULL) {
-		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
-		       name);
-		abort();
-	}
-	mp->n_regions = s / sizeof(mp->regions[0]);
-	memcpy(mp->regions, rp, s);
-
-	/* Make sure the pieces are sorted. */
-	mem_pieces_sort(mp);
-	mem_pieces_coalesce(mp);
-}
-#endif /* CONFIG_ALL_PPC */
-
 /*
  * Set up one of the I/D BAT (block address translation) register pairs.
  * The parameters are not checked; in particular size must be a power
@@ -877,14 +839,13 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-
 	for (; start < end; start += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(start));
 		set_page_count(virt_to_page(start), 1);
 		free_page(start);
 		totalram_pages++;
 	}
+	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
 
@@ -904,27 +865,28 @@
 	/*
 	 * The Zone Protection Register (ZPR) defines how protection will
 	 * be applied to every page which is a member of a given zone. At
-	 * present, we utilize only two of the 4xx's zones. The first, zone
-	 * 0, is set at '00b and only allows access in supervisor-mode based
-	 * on the EX and WR bits. No user-mode access is allowed. The second,
-	 * zone 1, is set at '10b and in supervisor-mode allows access
-	 * without regard to the EX and WR bits. In user-mode, access is
-	 * allowed based on the EX and WR bits.
+	 * present, we utilize only two of the 4xx's zones.
+	 * The zone index bits (of ZSEL) in the PTE are used for software
+	 * indicators, except the LSB.  For user access, zone 15 is used,
+	 * for kernel access, zone 14 is used.  We set all but zone 15
+	 * to zero, allowing only kernel access as indicated in the PTE.
+	 * For zone 15, we set a 10 binary (I guess a 01 would work too)
+	 * to allow user access as indicated in the PTE.  This also allows
+	 * kernel access as indicated in the PTE.
 	 */
 
-        mtspr(SPRN_ZPR, 0x2aaaaaaa);
-
-	/* Hardwire any TLB entries necessary here. */
+        mtspr(SPRN_ZPR, 0x00000002);
 
-	PPC4xx_tlb_pin(KERNELBASE, 0, TLB_PAGESZ(PAGESZ_16M), 1);
+	flush_instruction_cache();
 
 	/*
 	 * Find the top of physical memory and map all of it in starting
 	 * at KERNELBASE.
 	 */
 
-        total_memory = total_lowmem = oak_find_end_of_memory();
-	end_of_DRAM = __va(total_memory);
+        total_memory = total_lowmem = ppc_md.find_end_of_memory();
+	end_of_DRAM = __va(total_lowmem);
+	set_phys_avail(total_lowmem);
         mapin_ram();
 
 	/*
@@ -943,70 +905,13 @@
         mtspr(SPRN_ICCR, 0x80000000);	/* 128 MB of instr. space at 0x0. */
 }
 
-#elif defined(CONFIG_8xx)
+#else /* !CONFIG_4xx */
 void __init MMU_init(void)
 {
 	if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
 
-	total_memory = total_lowmem = m8xx_find_end_of_memory();
-#ifdef CONFIG_HIGHMEM
-	if (total_lowmem > MAX_LOW_MEM) {
-		total_lowmem = MAX_LOW_MEM;
-		mem_pieces_remove(&phys_avail, total_lowmem,
-				  total_memory - total_lowmem, 0);
-	}
-#endif /* CONFIG_HIGHMEM */
-	end_of_DRAM = __va(total_lowmem);
-	set_phys_avail(total_lowmem);
-
-        /* Map in all of RAM starting at KERNELBASE */
-        mapin_ram();
-
-        /* Now map in some of the I/O space that is generically needed
-         * or shared with multiple devices.
-         * All of this fits into the same 4Mbyte region, so it only
-         * requires one page table page.
-         */
-        ioremap(IMAP_ADDR, IMAP_SIZE);
-#ifdef CONFIG_MBX
-        ioremap(NVRAM_ADDR, NVRAM_SIZE);
-        ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
-        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
-
-	/* Map some of the PCI/ISA I/O space to get the IDE interface.
-	*/
-        ioremap(PCI_ISA_IO_ADDR, 0x4000);
-        ioremap(PCI_IDE_ADDR, 0x4000);
-#endif
-#ifdef CONFIG_RPXLITE
-	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
-	ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE);
-#endif
-#ifdef CONFIG_RPXCLASSIC
-        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
-	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
-#endif
-	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
-}
-
-#else /* not 4xx or 8xx */
-void __init MMU_init(void)
-{
-	if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
+	total_memory = ppc_md.find_end_of_memory();
 
-	if (have_of)
-		total_memory = pmac_find_end_of_memory();
-#ifdef CONFIG_APUS
-	else if (_machine == _MACH_apus )
-		total_memory = apus_find_end_of_memory();
-#endif
-#if defined(CONFIG_8260)
-	else
-		total_memory = m8260_find_end_of_memory();
-#else
-	else /* prep */
-		total_memory = prep_find_end_of_memory();
-#endif
 	if (__max_memory && total_memory > __max_memory)
 		total_memory = __max_memory;
 	total_lowmem = total_memory;
@@ -1019,6 +924,7 @@
 	end_of_DRAM = __va(total_lowmem);
 	set_phys_avail(total_lowmem);
 
+#if !defined(CONFIG_8xx)
 	if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
         hash_init();
 #ifndef CONFIG_PPC64BRIDGE
@@ -1026,16 +932,49 @@
 #endif
 	
 	ioremap_base = 0xf8000000;
+#endif /* CONFIG_8xx */
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:mapin", 0x301);
 	/* Map in all of RAM starting at KERNELBASE */
 	mapin_ram();
 
-#ifdef CONFIG_POWER4
+#if defined(CONFIG_POWER4)
 	ioremap_base = ioremap_bot = 0xfffff000;
 	isa_io_base = (unsigned long) ioremap(0xffd00000, 0x200000) + 0x100000;
 
-#else /* CONFIG_POWER4 */
+#elif defined(CONFIG_8xx)
+        /* Now map in some of the I/O space that is generically needed
+         * or shared with multiple devices.
+         * All of this fits into the same 4Mbyte region, so it only
+         * requires one page table page.
+         */
+        ioremap(IMAP_ADDR, IMAP_SIZE);
+#ifdef CONFIG_MBX
+        ioremap(NVRAM_ADDR, NVRAM_SIZE);
+        ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
+        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+
+	/* Map some of the PCI/ISA I/O space to get the IDE interface.
+	*/
+        ioremap(PCI_ISA_IO_ADDR, 0x4000);
+        ioremap(PCI_IDE_ADDR, 0x4000);
+#endif
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
+#if !defined(CONFIG_PCI)
+	ioremap(_IO_BASE,_IO_BASE_SIZE);
+#endif
+#endif
+#ifdef CONFIG_HTDMSOUND
+	ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE);
+#endif
+#ifdef CONFIG_FADS
+	ioremap(BCSR_ADDR, BCSR_SIZE);
+#endif
+#ifdef CONFIG_PCI
+        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+#endif
+#else /* !CONFIG_POWER4 && !CONFIG_8xx */
 	/*
 	 * Setup the bat mappings we're going to load that cover
 	 * the io areas.  RAM was mapped by mapin_ram().
@@ -1069,6 +1008,10 @@
 		/* Map chip and ZorroII memory */
 		setbat(1, zTwoBase,   0x00000000, 0x01000000, IO_PAGE);
 		break;
+	case _MACH_gemini:
+		setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
+		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+		break;
 	case _MACH_8260:
 		/* Map the IMMR, plus anything else we can cover
 		 * in that upper space according to the memory controller
@@ -1081,7 +1024,7 @@
 		break;
 	}
 	ioremap_bot = ioremap_base;
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_POWER4 || CONFIG_8xx */
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 #ifdef CONFIG_BOOTX_TEXT
@@ -1257,155 +1200,6 @@
 }
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-#if defined(CONFIG_ALL_PPC)
-/*
- * On systems with Open Firmware, collect information about
- * physical RAM and which pieces are already in use.
- * At this point, we have (at least) the first 8MB mapped with a BAT.
- * Our text, data, bss use something over 1MB, starting at 0.
- * Open Firmware may be using 1MB at the 4MB point.
- */
-unsigned long __init pmac_find_end_of_memory(void)
-{
-	unsigned long a, total;
-	struct mem_pieces phys_mem;
-
-	memory_node = find_devices("memory");
-	if (memory_node == NULL) {
-		printk(KERN_ERR "can't find memory node\n");
-		abort();
-	}
-
-	/*
-	 * Find out where physical memory is, and check that it
-	 * starts at 0 and is contiguous.  It seems that RAM is
-	 * always physically contiguous on Power Macintoshes.
-	 *
-	 * Supporting discontiguous physical memory isn't hard,
-	 * it just makes the virtual <-> physical mapping functions
-	 * more complicated (or else you end up wasting space
-	 * in mem_map).
-	 */
-	get_mem_prop("reg", &phys_mem);
-	if (phys_mem.n_regions == 0)
-		panic("No RAM??");
-	a = phys_mem.regions[0].address;
-	if (a != 0)
-		panic("RAM doesn't start at physical address 0");
-	total = phys_mem.regions[0].size;
-
-	if (phys_mem.n_regions > 1) {
-		printk("RAM starting at 0x%x is not contiguous\n",
-		       phys_mem.regions[1].address);
-		printk("Using RAM from 0 to 0x%lx\n", total-1);
-	}
-
-	return total;
-}
-#endif /* CONFIG_ALL_PPC */
-
-#if defined(CONFIG_ALL_PPC)
-/*
- * This finds the amount of physical ram and does necessary
- * setup for prep.  This is pretty architecture specific so
- * this will likely stay separate from the pmac.
- * -- Cort
- */
-unsigned long __init prep_find_end_of_memory(void)
-{
-	unsigned long total;
-#ifdef CONFIG_PREP_RESIDUAL
-	total = res->TotalMemory;
-#else
-	total = 0;
-#endif
-
-	if (total == 0 )
-	{
-		/*
-		 * I need a way to probe the amount of memory if the residual
-		 * data doesn't contain it. -- Cort
-		 */
-		printk("Ramsize from residual data was 0 -- Probing for value\n");
-		total = 0x02000000;
-		printk("Ramsize default to be %ldM\n", total>>20);
-	}
-
-	return (total);
-}
-#endif /* defined(CONFIG_ALL_PPC) */
-
-#ifdef CONFIG_8260
-/*
- * Same hack as 8xx.
- */
-unsigned long __init m8260_find_end_of_memory(void)
-{
-	bd_t	*binfo;
-	extern unsigned char __res[];
-	
-	binfo = (bd_t *)__res;
-
-	return binfo->bi_memsize;
-}
-#endif /* CONFIG_8260 */
-
-#ifdef CONFIG_APUS
-#define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long __init apus_find_end_of_memory(void)
-{
-	int shadow = 0;
-	unsigned long total;
-
-	/* The memory size reported by ADOS excludes the 512KB
-	   reserved for PPC exception registers and possibly 512KB
-	   containing a shadow of the ADOS ROM. */
-	{
-		unsigned long size = memory[0].size;
-
-		/* If 2MB aligned, size was probably user
-                   specified. We can't tell anything about shadowing
-                   in this case so skip shadow assignment. */
-		if (0 != (size & 0x1fffff)){
-			/* Align to 512KB to ensure correct handling
-			   of both memfile and system specified
-			   sizes. */
-			size = ((size+0x0007ffff) & 0xfff80000);
-			/* If memory is 1MB aligned, assume
-                           shadowing. */
-			shadow = !(size & 0x80000);
-		}
-
-		/* Add the chunk that ADOS does not see. by aligning
-                   the size to the nearest 2MB limit upwards.  */
-		memory[0].size = ((size+0x001fffff) & 0xffe00000);
-	}
-
-	total = memory[0].size;
-
-	/* Remove the memory chunks that are controlled by special
-           Phase5 hardware. */
-
-	/* Remove the upper 512KB if it contains a shadow of
-	   the ADOS ROM. FIXME: It might be possible to
-	   disable this shadow HW. Check the booter
-	   (ppc_boot.c) */
-	if (shadow)
-		total -= HARDWARE_MAPPED_SIZE;
-
-	/* Remove the upper 512KB where the PPC exception
-	   vectors are mapped. */
-	total -= HARDWARE_MAPPED_SIZE;
-
-	/* Linux/APUS only handles one block of memory -- the one on
-	   the PowerUP board. Other system memory is horrible slow in
-	   comparison. The user can use other memory for swapping
-	   using the z2ram device. */
-	ram_phys_base = memory[0].addr;
-	return total;
-}
-#endif /* CONFIG_APUS */
-
 /*
  * Initialize the hash table and patch the instructions in head.S.
  */
@@ -1514,43 +1308,7 @@
 	}
 	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
-#elif defined(CONFIG_8xx)
-/*
- * This is a big hack right now, but it may turn into something real
- * someday.
- *
- * For the 8xx boards (at this time anyway), there is nothing to initialize
- * associated the PROM.  Rather than include all of the prom.c
- * functions in the image just to get prom_init, all we really need right
- * now is the initialization of the physical memory region.
- */
-unsigned long __init m8xx_find_end_of_memory(void)
-{
-	bd_t	*binfo;
-	extern unsigned char __res[];
-	
-	binfo = (bd_t *)__res;
-
-	return binfo->bi_memsize;
-}
 #endif /* !CONFIG_4xx && !CONFIG_8xx */
-
-#ifdef CONFIG_OAK
-/*
- * Return the virtual address representing the top of physical RAM
- * on the Oak board.
- */
-unsigned long __init
-oak_find_end_of_memory(void)
-{
-	extern unsigned char __res[];
-
-	unsigned long *ret;
-	bd_t *bip = (bd_t *)__res;
-	
-	return bip->bi_memsize;
-}
-#endif
 
 /*
  * Set phys_avail to the amount of physical memory,
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/mem_pieces.c linux/arch/ppc/mm/mem_pieces.c
--- v2.4.4/linux/arch/ppc/mm/mem_pieces.c	Mon Jun 19 17:59:37 2000
+++ linux/arch/ppc/mm/mem_pieces.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mem_pieces.c 1.5 05/17/01 18:14:23 cort
+ */
+/*
  *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  *      Changes to accomodate Power Macintoshes.
  *    Cort Dougan <cort@cs.nmt.edu>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/mm/mem_pieces.h linux/arch/ppc/mm/mem_pieces.h
--- v2.4.4/linux/arch/ppc/mm/mem_pieces.h	Mon Jun 19 17:59:37 2000
+++ linux/arch/ppc/mm/mem_pieces.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mem_pieces.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  *      Changes to accomodate Power Macintoshes.
  *    Cort Dougan <cort@cs.nmt.edu>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/Makefile linux/arch/ppc/treeboot/Makefile
--- v2.4.4/linux/arch/ppc/treeboot/Makefile	Wed Mar  8 09:18:02 2000
+++ linux/arch/ppc/treeboot/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,57 +0,0 @@
-#
-#    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
-#
-#    Module name: Makefile
-#
-#    Description:
-#      Makefile for the IBM "tree" evaluation board Linux kernel
-#      boot loaders.
-#
-
-HOSTCFLAGS = -O -I$(TOPDIR)/include
-
-GZIP	= gzip -vf9
-RM	= rm -f
-MKEVIMG	= mkevimg -l
-MKIRIMG	= mkirimg
-
-CFLAGS	= -O -fno-builtin -I$(TOPDIR)/include
-LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic
-
-OBJS	= crt0.o main.o misc.o irSect.o ../coffboot/string.o ../coffboot/zlib.o 
-LIBS	=
-
-treeboot: $(OBJS) ld.script
-	$(LD) -o $@ $(LD_ARGS) $(OBJS) $(LIBS)
-
-zImage:	vmlinux.img
-
-zImage.initrd: vmlinux.initrd.img
-
-treeboot.image: treeboot vmlinux.gz
-	$(OBJCOPY) --add-section=image=vmlinux.gz treeboot $@
-
-treeboot.initrd: treeboot.image ramdisk.image.gz
-	$(OBJCOPY) --add-section=initrd=ramdisk.image.gz treeboot.image $@
-
-vmlinux.img: treeboot.image
-	$(OBJDUMP) --syms treeboot.image | grep irSectStart > irSectStart.txt
-	$(MKIRIMG) treeboot.image treeboot.image.out irSectStart.txt
-	$(MKEVIMG) treeboot.image.out $@
-	$(RM) treeboot.image treeboot.image.out irSectStart.txt
-
-vmlinux.initrd.img: treeboot.initrd
-	$(OBJDUMP) --all-headers treeboot.initrd | grep irSectStart > irSectStart.txt
-	$(MKIRIMG) treeboot.initrd treeboot.initrd.out irSectStart.txt
-	$(MKEVIMG) treeboot.initrd.out $@
-	$(RM) treeboot.initrd treeboot.initrd.out irSectStart.txt
-
-vmlinux.gz: $(TOPDIR)/vmlinux
-	$(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux
-	$(GZIP) vmlinux
-
-clean:
-	rm -f treeboot treeboot.image treeboot.initrd irSectStart.txt vmlinux.* *.o
-
-fastdep:
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/crt0.S linux/arch/ppc/treeboot/crt0.S
--- v2.4.4/linux/arch/ppc/treeboot/crt0.S	Mon Jan 10 18:25:32 2000
+++ linux/arch/ppc/treeboot/crt0.S	Wed Dec 31 16:00:00 1969
@@ -1,70 +0,0 @@
-/*
- *    Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
- *      Initial Power Macintosh COFF version.
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *      Modifications for IBM PowerPC 400-class processor evaluation
- *      boards.
- *
- *    Module name: crt0.S
- *
- *    Description:
- *      Boot loader execution entry point. Clears out .bss section as per
- *      ANSI C requirements. Invalidates and flushes the caches over the
- *      range covered by the boot loader's .text section. Sets up a stack
- *      below the .text section entry point.
- *
- *    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 "../kernel/ppc_asm.tmpl"
-
-	.text
-
-	.globl	_start
-_start:	
-        ## Clear out the BSS as per ANSI C requirements
-
-        lis     r7,_end@ha		# 
-        addi    r7,r7,_end@l		# r7 = &_end
-        lis     r8,__bss_start@ha	# 
-        addi    r8,r8,__bss_start@l	# r8 = &_bss_start
-
-	## Determine how large an area, in number of words, to clear
-	
-        subf    r7,r8,r7		# r7 = &_end - &_bss_start + 1 
-        addi    r7,r7,3			# r7 += 3
-        srwi.   r7,r7,2			# r7 = size in words.
-        beq     2f			# If the size is zero, do not bother
-        addi    r8,r8,-4		# r8 -= 4
-        mtctr   r7			# SPRN_CTR = number of words to clear
-        li      r0,0			# r0 = 0
-1:      stwu    r0,4(r8)		# Clear out a word
-        bdnz    1b			# If we are not done yet, keep clearing
-	
-	## Flush and invalidate the caches for the range in memory covering
-	## the .text section of the boot loader
-	
-2:	lis	r9,_start@h		# r9 = &_start
-	lis	r8,_etext@ha		# 
-	addi	r8,r8,_etext@l		# r8 = &_etext
-3:	dcbf	r0,r9			# Flush the data cache
-	icbi	r0,r9			# Invalidate the instruction cache
-	addi	r9,r9,0x10		# Increment by one cache line
-	cmplwi	cr0,r9,r8		# Are we at the end yet?
-	blt	3b			# No, keep flushing and invalidating
-
-	## Set up the stack
-
-	lis	r9,_start@h		# r9 = &_start (text section entry)
-	addi	r9,r9,_start@l
-	subi	r1,r9,64		# Start the stack 64 bytes below _start
-	clrrwi	r1,r1,4			# Make sure it is aligned on 16 bytes.
-	li	r0,0
-	stwu	r0,-16(r1)
-	mtlr	r9
-	
-	b	start			# All done, start the real work.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/elf.pl linux/arch/ppc/treeboot/elf.pl
--- v2.4.4/linux/arch/ppc/treeboot/elf.pl	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/treeboot/elf.pl	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-#
-# ELF header field numbers
-#
-
-$e_ident	=  0;	# Identification bytes / magic number
-$e_type		=  1;	# ELF file type
-$e_machine	=  2;	# Target machine type
-$e_version	=  3;	# File version
-$e_entry	=  4;	# Start address
-$e_phoff	=  5;	# Program header file offset
-$e_shoff	=  6;	# Section header file offset
-$e_flags	=  7;	# File flags
-$e_ehsize	=  8;	# Size of ELF header
-$e_phentsize	=  9;	# Size of program header
-$e_phnum	= 10;	# Number of program header entries
-$e_shentsize	= 11;	# Size of section header
-$e_shnum	= 12;	# Number of section header entries
-$e_shstrndx	= 13;	# Section header table string index
-
-#
-# Section header field numbers
-#
-
-$sh_name	=  0;	# Section name
-$sh_type	=  1;	# Section header type
-$sh_flags	=  2;	# Section header flags
-$sh_addr	=  3;	# Virtual address
-$sh_offset	=  4;	# File offset
-$sh_size	=  5;	# Section size
-$sh_link	=  6;	# Miscellaneous info
-$sh_info	=  7;	# More miscellaneous info
-$sh_addralign	=  8;	# Memory alignment
-$sh_entsize	=  9;	# Entry size if this is a table
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/irSect.c linux/arch/ppc/treeboot/irSect.c
--- v2.4.4/linux/arch/ppc/treeboot/irSect.c	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/treeboot/irSect.c	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-/*
- *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: irSect.c
- *
- *    Description:
- *      Defines variables to hold the absolute starting address and size
- *      of the Linux kernel "image" and the initial RAM disk "initrd"
- *      sections within the boot loader.
- *
- */
-
-#include "irSect.h"
-
-
-/*
- * The order of globals below must not change. If more globals are added,
- * you must change the script 'mkirimg' accordingly.
- *
- */
-
-/* 
- * irSectStart must be at beginning of file 
- */
-unsigned int irSectStart = 0xdeadbeaf;
-
-unsigned int imageSect_start	= 0;
-unsigned int imageSect_size	= 0;
-unsigned int initrdSect_start	= 0;
-unsigned int initrdSect_size	= 0;
-
-/* 
- * irSectEnd must be at end of file 
- */
-unsigned int irSectEnd   = 0xdeadbeaf;
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/irSect.h linux/arch/ppc/treeboot/irSect.h
--- v2.4.4/linux/arch/ppc/treeboot/irSect.h	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/treeboot/irSect.h	Wed Dec 31 16:00:00 1969
@@ -1,32 +0,0 @@
-/*
- *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: irSect.h
- *    
- *    Description:
- *      Defines variables to hold the absolute starting address and size
- *      of the Linux kernel "image" and the initial RAM disk "initrd"   
- *      sections within the boot loader.
- *      
- */
-
-#ifndef __IRSECT_H__
-#define __IRSECT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned int imageSect_start;
-extern unsigned int imageSect_size;
-
-extern unsigned int initrdSect_start;
-extern unsigned int initrdSect_size;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __IRSECT_H__ */
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/ld.script linux/arch/ppc/treeboot/ld.script
--- v2.4.4/linux/arch/ppc/treeboot/ld.script	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/treeboot/ld.script	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-OUTPUT_ARCH(powerpc)
-SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
-/* Do we need any of these for elf?
-   __DYNAMIC = 0;    */
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = + SIZEOF_HEADERS;
-  .interp : { *(.interp) }
-  .hash          : { *(.hash)		}
-  .dynsym        : { *(.dynsym)		}
-  .dynstr        : { *(.dynstr)		}
-  .rel.text      : { *(.rel.text)		}
-  .rela.text     : { *(.rela.text) 	}
-  .rel.data      : { *(.rel.data)		}
-  .rela.data     : { *(.rela.data) 	}
-  .rel.rodata    : { *(.rel.rodata) 	}
-  .rela.rodata   : { *(.rela.rodata) 	}
-  .rel.got       : { *(.rel.got)		}
-  .rela.got      : { *(.rela.got)		}
-  .rel.ctors     : { *(.rel.ctors)	}
-  .rela.ctors    : { *(.rela.ctors)	}
-  .rel.dtors     : { *(.rel.dtors)	}
-  .rela.dtors    : { *(.rela.dtors)	}
-  .rel.bss       : { *(.rel.bss)		}
-  .rela.bss      : { *(.rela.bss)		}
-  .rel.plt       : { *(.rel.plt)		}
-  .rela.plt      : { *(.rela.plt)		}
-  .init          : { *(.init)	} =0
-  .plt : { *(.plt) }
-  .text      :
-  {
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    *(.got1)
-  }
-  .fini      : { *(.fini)    } =0
-  .ctors     : { *(.ctors)   }
-  .dtors     : { *(.dtors)   }
-  _etext = .;
-  PROVIDE (etext = .);
-  /* Read-write section, merged into data segment: */
-  . = (. + 0x0FFF) & 0xFFFFF000;
-  .data    :
-  {
-    *(.data)
-    *(.data1)
-    *(.sdata)
-    *(.sdata2)
-    *(.got.plt) *(.got)
-    *(.dynamic)
-    CONSTRUCTORS
-  }
-  _edata  =  .;
-  PROVIDE (edata = .);
-  __bss_start = .;
-  .bss       :
-  {
-   *(.sbss) *(.scommon)
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  }
-  _end = . ;
-  PROVIDE (end = .);
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/main.c linux/arch/ppc/treeboot/main.c
--- v2.4.4/linux/arch/ppc/treeboot/main.c	Mon Jan 10 18:25:32 2000
+++ linux/arch/ppc/treeboot/main.c	Wed Dec 31 16:00:00 1969
@@ -1,240 +0,0 @@
-/*
- *    Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
- *      Initial Power Macintosh COFF version.
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *      Modifications for an ELF-based IBM evaluation board version.
- *
- *    Module name: main.c
- *
- *    Description:
- *      This module does most of the real work for the boot loader. It
- *      checks the variables holding the absolute start address and size
- *      of the Linux kernel "image" and initial RAM disk "initrd" sections
- *      and if they are present, moves them to their "proper" locations.
- *
- *      For the Linux kernel, "proper" is physical address 0x00000000.
- *      For the RAM disk, "proper" is the image's size below the top
- *      of physical memory. The Linux kernel may be in either raw
- *      binary form or compressed with GNU zip (aka gzip).
- *
- *    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 <asm/board.h>
-
-#include "../coffboot/nonstdio.h"
-#include "../coffboot/zlib.h"
-#include "irSect.h"
-
-
-/* Preprocessor Defines */
-
-/*
- * Location of the IBM boot ROM function pointer address for retrieving
- * the board information structure.
- */
-
-#define	BOARD_INFO_VECTOR	0xFFFE0B50
-
-#define	RAM_SIZE	(4 * 1024 * 1024)
-
-#define	RAM_PBASE	0x00000000
-#define	RAM_PEND	(RAM_PBASE + RAM_SIZE)
-
-#define	RAM_VBASE	0xC0000000
-#define	RAM_VEND	(RAM_VBASE + RAM_SIZE)
-
-#define	RAM_START	RAM_PBASE
-#define	RAM_END		RAM_PEND
-#define	RAM_FREE	(imageSect_start + imageSect_size + initrdSect_size)
-
-#define	PROG_START	RAM_START
-
-
-/* Function Macros */
-
-#define	ALIGN_UP(x, align)	(((x) + ((align) - 1)) & ~((align) - 1))
-
-
-/* Global Variables */
-
-/* Needed by zalloc and zfree for allocating memory */
-
-char *avail_ram;	/* Indicates start of RAM available for heap */
-char *end_avail;	/* Indicates end of RAM available for heap */
-
-bd_t	board_info;
-
-/*
- * XXX - Until either the IBM boot ROM provides a way of passing arguments to
- *       the program it launches or until I/O is working in the boot loader,
- *       this is a good spot to pass in command line arguments to the kernel
- *       (e.g. console=tty0).
- */
-
-static char *cmdline = "";
-
-
-/* Function Prototypes */
-
-void *zalloc(void *x, unsigned items, unsigned size);
-void zfree(void *x, void *addr, unsigned nb);
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp);
-
-void printf () {}
-void pause () {}
-void exit () {}
-
-
-void start(void)
-{
-    void *options;
-    int ns, oh, i;
-    unsigned long sa, len;
-    void *dst;
-    unsigned char *im;
-    unsigned long initrd_start, initrd_size;
-    bd_t *(*get_board_info)(void) = 
-	    (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
-    bd_t *bip = NULL;
-
-    if ((bip = get_board_info()) != NULL)
-	    memcpy(&board_info, bip, sizeof(bd_t));
-
-    /* setup_bats(RAM_START); */
-
-    /* Init RAM disk (initrd) section */
-
-    if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) {
-        initrd_start = (RAM_END - initrd_size) & ~0xFFF;
-
-	printf("Initial RAM disk at 0x%08x (%u bytes)\n",
-	       initrd_start, initrd_size);
-
-	memcpy((char *)initrd_start,
-	       (char *)(initrdSect_start),
-	       initrdSect_size);
-
-	end_avail = (char *)initrd_start;
-    } else {
-	initrd_start = initrd_size = 0;
-	end_avail = (char *)RAM_END;
-    }
-
-    /* Linux kernel image section */
-	
-    im = (unsigned char *)(imageSect_start);
-    len = imageSect_size;
-    dst = (void *)PROG_START;
-
-    /* Check for the gzip archive magic numbers */
-
-    if (im[0] == 0x1f && im[1] == 0x8b) {
-
-        /* The gunzip routine needs everything nice and aligned */
-
-	void *cp = (void *)ALIGN_UP(RAM_FREE, 8);
-	avail_ram = (void *)(cp + ALIGN_UP(len, 8));
-	memcpy(cp, im, len);
-
-	/* I'm not sure what the 0x200000 parameter is for, but it works. */
-
-	gunzip(dst, 0x200000, cp, (int *)&len);
-    } else {
-	memmove(dst, im, len);
-    }
-
-    flush_cache(dst, len);
-
-    sa = (unsigned long)dst;
-
-    (*(void (*)())sa)(&board_info,
-		      initrd_start,
-		      initrd_start + initrd_size,
-		      cmdline,
-		      cmdline + strlen(cmdline));
-
-    pause();
-}
-
-void *zalloc(void *x, unsigned items, unsigned size)
-{
-    void *p = avail_ram;
-
-    size *= items;
-    size = ALIGN_UP(size, 8);
-    avail_ram += size;
-    if (avail_ram > end_avail) {
-	printf("oops... out of memory\n");
-	pause();
-    }
-    return p;
-}
-
-void zfree(void *x, void *addr, unsigned nb)
-{
-
-}
-
-#define HEAD_CRC	2
-#define EXTRA_FIELD	4
-#define ORIG_NAME	8
-#define COMMENT		0x10
-#define RESERVED	0xe0
-
-#define DEFLATED	8
-
-void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
-{
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n");
-	exit();
-    }
-    printf("done 1\n");
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    printf("doing inflate\n");
-    r = inflate(&s, Z_FINISH);
-    printf("done inflate\n");
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d\n", r);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    printf("doing end\n");
-    inflateEnd(&s);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/misc.S linux/arch/ppc/treeboot/misc.S
--- v2.4.4/linux/arch/ppc/treeboot/misc.S	Mon Jan 10 18:25:05 2000
+++ linux/arch/ppc/treeboot/misc.S	Wed Dec 31 16:00:00 1969
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 "../kernel/ppc_asm.tmpl"
-
-	.text
-
-/*
- * Flush the dcache and invalidate the icache for a range of addresses.
- *
- * flush_cache(addr, len)
- */
-	.global	flush_cache
-flush_cache:
-	mfpvr	r5			# Get processor version register
-	extrwi	r5,r5,16,0		# Get the version bits
-	cmpwi	cr0,r5,0x0020		# Is this a 403-based processor?
-	beq	1f			# Yes, it is
-	li	r5,32			# It is not a 403, set to 32 bytes
-	addi	r4,r4,32-1		# len += line_size - 1
-	srwi.	r4,r4,5			# Convert from bytes to lines
-	b	2f
-1:	li	r5,16			# It is a 403, set to 16 bytes
-	addi	r4,r4,16-1		# len += line_size - 1
-	srwi.	r4,r4,4			# Convert from bytes to lines
-2:	mtctr	r4			# Set-up the counter register
-	beqlr				# If it is 0, we are done
-3:	dcbf	r0,r3			# Flush and invalidate the data line
-	icbi	r0,r3			# Invalidate the instruction line
-	add	r3,r3,r5		# Move to the next line
-	bdnz	3b			# Are we done yet?
-	sync
-	isync
-	blr				# Return to the caller
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/mkevimg linux/arch/ppc/treeboot/mkevimg
--- v2.4.4/linux/arch/ppc/treeboot/mkevimg	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/treeboot/mkevimg	Wed Dec 31 16:00:00 1969
@@ -1,437 +0,0 @@
-#!/usr/bin/perl
-
-#
-#    Copyright (c) 1998-1999 TiVo, Inc.
-#    All rights reserved.
-#
-#    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
-#      Major syntactic and usability rework.
-#
-#    Module name: mkevimg
-#
-#    Description:
-#      Converts an ELF output file from the linker into the format used by
-#      the IBM evaluation board ROM Monitor to load programs from a host
-#      onto the evaluation board. The ELF file must be an otherwise execut-
-#      able file (with the text and data addresses bound at link time) and
-#      have space reserved after the entry point for the load information
-#      block:
-#
-#      typedef struct boot_block {
-#        unsigned long magic;	        0x0052504F
-#	 unsigned long dest;	        Target address of the image
-#	 unsigned long num_512blocks;   Size, rounded-up, in 512 byte blocks
-#	 unsigned long debug_flag;      Run the debugger or image after load
-#        unsigned long entry_point;	The image address to jump to after load
-#	 unsigned long reserved[3];
-#      } boot_block_t;
-#
-#   
-
-use File::Basename;
-use Getopt::Std;
-
-#
-# usage()
-#
-# Description:
-#   This routine prints out the proper command line usage for this program
-#
-# Input(s):
-#   status - Flag determining what usage information will be printed and what
-#            the exit status of the program will be after the information is
-#            printed.
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   This subroutine does not return.
-#
-
-sub usage {
-  my($status);
-  $status = $_[0];
-
-  printf("Usage: %s [-hlvV] <ELF input file> <Evaluation board output file>\n",
-	$program);
-
-  if ($status != 0) {
-    printf("Try `%s -h' for more information.\n", $program);
-  }
-
-  if ($status != 1) {
-    print("  -h         Print out this message and exit.\n");
-    print("  -l         Linux mode; if present, copy 'image' and 'initrd' sections.\n");
-    print("  -v         Verbose. Print out lots of ELF information.\n");
-    print("  -V         Print out version information and exit.\n");
-  }
-
-  exit($status);
-}
-
-#
-# version()
-#
-# Description:
-#   This routine prints out program version information
-#
-# Input(s):
-#   N/A
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   This subroutine does not return.
-#
-
-sub version {
-  print("mkevimg Version 1.1.0\n");
-  print("Copyright (c) 1998-1999 TiVo, Inc.\n");
-  print("Copyright (c) 1999 Grant Erickson <grant\@lcse.umn.edu>\n");
-
-  exit (0);
-}
-
-#
-# file_check()
-#
-# Description:
-#   This routine checks an input file to ensure that it exists, is a
-#   regular file, and is readable.
-#
-# Input(s):
-#   file - Input file to be checked.
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   0 if the file exists, is a regular file, and is readable, otherwise -1.
-#
-
-sub file_check {
-  my($file);
-  $file = $_[0];
-
-  if (!(-e $file)) {
-    printf("The file \"%s\" does not exist.\n", $file);
-    return (-1);
-  } elsif (!(-f $file)) {
-    printf("The file \"%s\" is not a regular file.\n", $file);
-    return (-1);
-  } elsif (!(-r $file)) {
-    printf("The file \"%s\" is not readable.\n", $file);
-    return (-1);
-  }
-
-  return (0);
-}
-
-#
-# decode_options()
-#
-# Description:
-#   This routine steps through the command-line arguments, parsing out
-#   recognzied options.
-#
-# Input(s):
-#   N/A
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   N/A
-#
-
-sub decode_options {
-
-  if (!getopts("hlvV")) {
-    usage(1);
-  }
-
-  if ($opt_h) {
-    usage(0);
-  }
-
-  if ($opt_l) {
-    $linux = 1;
-  }
-
-  if ($opt_V) {
-    version();
-    exit (0);
-  }
-
-  if ($opt_v) {
-    $verbose = 1;
-  }
-
-  if (!($ifile = shift(@ARGV))) {
-    usage(1);
-  }
-
-  if (!($ofile = shift(@ARGV))) {
-    usage (1);
-  }
-
-  if (file_check($ifile)) {
-    exit(1);
-  }
-
-}
-
-#
-# ELF file and section header field numbers
-#
-
-require 'elf.pl';
-
-#
-# Main program body
-#
-
-{
-  $program = basename($0);
-
-  decode_options();
-
-  open(ELF, "<$ifile") || die "Cannot open input file";
-
-  $ifilesize = (-s $ifile);
-
-  if ($verbose) {
-    print("Output file: $ofile\n");
-    print("Input file: $ifile, $ifilesize bytes.\n");
-  }
-
-  if (read(ELF, $ibuf, $ifilesize) != $ifilesize) {
-    print("Failed to read input file!\n");
-    exit(1);
-  }
-
-  # 
-  # Parse ELF header
-  #
-
-  @eh = unpack("a16n2N5n6", $ibuf);
-
-  #
-  # Make sure this is actually a PowerPC ELF file.
-  #
-
-  if (substr($eh[$e_ident], 0, 4) ne "\177ELF") {
-    printf("The file \"%s\" is not an ELF file.\n", $ifile);
-    exit (1);
-  } elsif ($eh[$e_machine] != 20) {
-    printf("The file \"%s\" is not a PowerPC ELF file.\n", $ifile);
-    exit (1);
-  }
-
-  if ($verbose) {
-    print("File header:\n");
-    printf("  Identifier:            %s\n",	$eh[$e_ident]);
-    printf("  Type:                  %d\n",	$eh[$e_type]);
-    printf("  Machine:               %d\n",	$eh[$e_machine]);
-    printf("  Version:               %d\n",	$eh[$e_version]);
-    printf("  Entry point:           0x%08x\n", $eh[$e_entry]);
-    printf("  Program header offset: 0x%x\n",	$eh[$e_phoff]);
-    printf("  Section header offset: 0x%x\n",	$eh[$e_shoff]);
-    printf("  Flags:                 0x%08x\n", $eh[$e_flags]);
-    printf("  Header size:           %d\n", $eh[$e_ehsize]);
-    printf("  Program entry size:    %d\n", $eh[$e_phentsize]);
-    printf("  Program table entries: %d\n", $eh[$e_phnum]);
-    printf("  Section header size:   %d\n", $eh[$e_shentsize]);
-    printf("  Section table entries: %d\n", $eh[$e_shnum]);
-    printf("  String table section:  %d\n", $eh[$e_shstrndx]);
-  }
-
-  #
-  # Find the section header for the string table.
-  #
-
-  $strtable_section_offset =  $eh[$e_shoff] +
-    $eh[$e_shstrndx] * $eh[$e_shentsize];
-
-  if ($verbose) {
-    printf("String table section header offset: 0x%x\n",
-	   $strtable_section_offset);
-  }
-  
-  #
-  # Find the start of the string table.
-  #
-
-  @strh = unpack("N10", substr($ibuf, $strtable_section_offset, 
-			       $eh[$e_shentsize]));
-
-  if ($verbose) {
-    printf("Section name strings start at: 0x%x, %d bytes.\n",
-	   $strh[$sh_offset], $strh[$sh_size]);
-  }
-
-  $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
-
-  # Grab each section header and find '.text' and '.bss' sections in
-  # particular.
-
-  if ($verbose) {
-  print("Section headers:\n");
-  print("Idx  Name                      Size      Address   File off  Algn\n");
-  print("---  ------------------------  --------  --------  --------  ----\n");
-  }
-
-  $off = $eh[$e_shoff];
-
-  for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
-    @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
-
-    # Take the first section name from the array returned by split.
-
-    ($name) = split(/\000/, substr($names, $sh[$sh_name]));
-    
-    if ($verbose) {
-      printf("%3d  %-24s  %8x  %08x  %08x  %4d\n", 
-	     $i, $name, $sh[$sh_size], $sh[$sh_addr], 
-	     $sh[$sh_offset], $sh[$sh_addralign]);
-    }
-
-    # Attempt to find the .text and .bss sections
-
-    if ($name =~ /^\.bss$/) {
-      ($bss_addr, $bss_offset, $bss_size) =
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-
-    } elsif ($name =~ /^\.text$/) {
-      ($text_addr, $text_offset, $text_size) = 
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-
-    } elsif ($linux && ($name =~ /^\image$/)) {
-      $image_found = 1;
-
-      ($image_addr, $image_offset, $image_size) = 
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-
-    } elsif ($linux && ($name =~ /^\initrd$/)) {
-      $initrd_found = 1;
-
-      ($initrd_addr, $initrd_offset, $initrd_size) = 
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-
-    }
-  }
-
-  printf("Text section   - Address: 0x%08x, Size: 0x%08x\n",
-	 $text_addr, $text_size);
-  printf("Bss  section   - Address: 0x%08x, Size: 0x%08x\n",
-	 $bss_addr, $bss_size);
-
-  if ($linux) {
-    if ($image_found) {
-      printf("Image section  - Address: 0x%08x, Size: 0x%08x\n",
-	     $image_addr, $image_size);
-    }
-
-    if ($initrd_found) {
-      printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n",
-	     $initrd_addr, $initrd_size);
-    }
-  }
-
-  #
-  # Open output file
-  #
-
-  open(BOOT, ">$ofile") || die "Cannot open output file";
-
-  #
-  # Compute image size
-  #
-
-  $output_size = $bss_offset - $text_offset + $bss_size;
-
-  if ($linux && $image_found) {
-    $output_size += $image_size;
-  }
-
-  if ($linux && $initrd_found) {
-    $output_size += $initrd_size;
-  }
-
-  $num_blocks = $output_size / 512 + 1;
-
-  #
-  # Write IBM PowerPC evaluation board boot_block_t header
-  #
-
-  $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0,
-		 $text_addr, 0, 0, 0);
-
-  $bytes = length($header);
-  
-  if (($resid = syswrite(BOOT, $header, $bytes)) != $bytes) {
-    die("Could not write boot image header to output file.");
-  }
-
-  printf("Entry point = 0x%08x\n", $text_addr);
-  printf("Image size  = 0x%08x (%d bytes) (%d blocks).\n", 
-	 $output_size, $output_size, $num_blocks);
-
-  #
-  # Write image starting after ELF and program headers and 
-  # continuing to beginning of bss
-  #
-
-  $bytes = $bss_offset - $text_offset + $bss_size;
-
-  if (($resid = syswrite(BOOT, $ibuf, $bytes, $text_offset)) != $bytes) {
-    die("Could not write boot image to output file.\n");
-  }
-
-  #
-  # If configured, write out the image and initrd sections as well
-  #
-
-  if ($linux) {
-    if ($image_found) {
-      $bytes = $image_size;
-      if (($resid = syswrite(BOOT, $ibuf, $bytes, $image_offset)) != $bytes) {
-	die("Could not write boot image to output file.\n");
-      }
-    }
-
-    if ($initrd_found) {
-      $bytes = $initrd_size;
-      if (($resid = syswrite(BOOT, $ibuf, $bytes, $initrd_offset)) != $bytes) {
-	die("Could not write boot image to output file.\n");
-      }
-    }
-  }
-
-  #
-  # Pad to a multiple of 512 bytes
-  #
-
-  $pad_size = 512 - (length($header) + $output_size) % 512;
-
-  if ($verbose) {
-    print("Padding boot image by an additional $pad_size bytes.\n");
-  }
-
-  $pad_string = pack(("H8","deadbeef") x 128);
-
-  syswrite(BOOT, $pad_string, $pad_size) or
-    die "Could not pad boot image in output file.\n";
-
-  #
-  # Clean-up and leave
-  #
-
-  close(BOOT);
-
-  print("\nBoot image file \"$ofile\" built successfully.\n\n");
-
-  exit(0);
-}
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/treeboot/mkirimg linux/arch/ppc/treeboot/mkirimg
--- v2.4.4/linux/arch/ppc/treeboot/mkirimg	Mon May 15 14:53:30 2000
+++ linux/arch/ppc/treeboot/mkirimg	Wed Dec 31 16:00:00 1969
@@ -1,367 +0,0 @@
-#!/usr/bin/perl
-#
-#    Copyright (c) 1998-1999 TiVo, Inc.
-#      Original ELF parsing code.
-#
-#    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
-#      Original code from 'mkevimg'.
-#
-#    Module name: mkirimg
-#
-#    Description:
-#      Reads an ELF file and assigns global variables 'imageSect_start',
-#      'imageSect_size', 'initrdSect_start', and 'initrdSect_size' from
-#      the "image" and "initrd" section header information. It then
-#      rewrites the input ELF file with assigned globals to an output
-#      file.
-#
-#      An input file, "irSectStart.txt" has the memory address of
-#      'irSectStart'. The irSectStart memory address is used to find
-#      the global variables in the ".data" section of the ELF file.
-#      The 'irSectStart' and the above global variables are defined
-#      in "irSect.c".
-#
-#
-
-use File::Basename;
-use Getopt::Std;
-
-#
-# usage()
-#
-# Description:
-#   This routine prints out the proper command line usage for this program
-#
-# Input(s):
-#   status - Flag determining what usage information will be printed and what
-#            the exit status of the program will be after the information is
-#            printed.
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   This subroutine does not return.
-#
-
-sub usage {
-  my($status);
-  $status = $_[0];
-
-  printf("Usage: %s [-hvV] <ELF input file> <Evaluation board output file> <irSectStart.txt file>\n",
-	 $program);
-
-  if ($status != 0) {
-    printf("Try `%s -h' for more information.\n", $program);
-  }
-
-  if ($status != 1) {
-    print("  -h             Print out this message and exit.\n");
-    print("  -v             Verbose. Print out lots of ELF information.\n");
-    print("  -V             Print out version information and exit.\n");
-  }
-
-  exit($status);
-}
-
-#
-# version()
-#
-# Description:
-#   This routine prints out program version information
-#
-# Input(s):
-#   N/A
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   This subroutine does not return.
-#
-
-sub version {
-  print("mkirimg Version 1.1.0\n");
-  print("Copyright (c) 1998-1999 TiVo, Inc.\n");
-  print("Copyright (c) 1999 Grant Erickson <grant\@lcse.umn.edu>\n");
-
-  exit (0);
-}
-
-#
-# file_check()
-#
-# Description:
-#   This routine checks an input file to ensure that it exists, is a
-#   regular file, and is readable.
-#
-# Input(s):
-#   file - Input file to be checked.
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   0 if the file exists, is a regular file, and is readable, otherwise -1.
-#
-
-sub file_check {
-  my($file);
-  $file = $_[0];
-
-  if (!(-e $file)) {
-     printf("The file \"%s\" does not exist.\n", $file);
-     return (-1);
-  } elsif (!(-f $file)) {
-     printf("The file \"%s\" is not a regular file.\n", $file);
-     return (-1);
-  } elsif (!(-r $file)) {
-     printf("The file \"%s\" is not readable.\n", $file);
-     return (-1);
-  }
-
-  return (0);
-}
-
-#
-# decode_options()
-#
-# Description:
-#   This routine steps through the command-line arguments, parsing out
-#   recognzied options.
-#
-# Input(s):
-#   N/A
-#
-# Output(s):
-#   N/A
-#
-# Returns:
-#   N/A
-#
-
-sub decode_options {
-
-  if (!getopts("hvV")) {
-      usage(1);
-  }
-
-  if ($opt_h) {
-      usage(0);
-  }
-
-  if ($opt_V) {
-      version();
-      exit (0);
-  }
-
-  if ($opt_v) {
-      $verbose = 1;
-  }
-
-  if (!($ElfFile = shift(@ARGV))) {
-      usage(1);
-  }
-
-  if (!($OutputFile = shift(@ARGV))) {
-      usage (1);
-  }
-
-  if (!($IrFile = shift(@ARGV))) {
-      usage (1);
-  }
-
-  if (file_check($ElfFile)) {
-      exit(1);
-  }
-
-  if (file_check($IrFile)) {
-      exit(1);
-  }
-}
-
-#
-# ELF file and section header field numbers
-#
-
-require 'elf.pl';
-
-#
-# Main program body
-#
-
-{
-  $program = basename($0);
-  decode_options();
-
-  open(ELF, "<$ElfFile") || die "Cannot open input file";
-  open(OUTPUT, ">$OutputFile") || die "Cannot open output file";
-  open(IR, "$IrFile") || die "Cannot open input file";
-
-  $ElfFilesize = (-s $ElfFile);
-
-  if (read(ELF, $ibuf, $ElfFilesize) != $ElfFilesize) {
-    print("Failed to read ELF input file!\n");
-    exit(1);
-  }
-
-  if (read(IR, $irbuf, 8) != 8) {
-      print("Failed to read Ir input file!\n");
-      exit(1);
-  }
-
-  #
-  # Parse ELF header
-  #
-
-  @eh = unpack("a16n2N5n6", $ibuf);
-
-  #
-  # Make sure this is actually a PowerPC ELF file.
-  #
-
-  if (substr($eh[$e_ident], 0, 4) ne "\177ELF") {
-      printf("The file \"%s\" is not an ELF file.\n", $ElfFile);
-      exit (1);
-  } elsif ($eh[$e_machine] != 20) {
-      printf("The file \"%s\" is not a PowerPC ELF file.\n", $ElfFile);
-      exit (1);
-  }
-
-  #
-  # Find the section header for the string table.
-  #
-
-  $strtable_section_offset =  $eh[$e_shoff] +
-
-  $eh[$e_shstrndx] * $eh[$e_shentsize];
-
-  if ($verbose) {
-     printf("String table section header offset: 0x%x\n",
-     $strtable_section_offset);
-  }
-
-  #
-  # Find the start of the string table.
-  #
-
-  @strh = unpack("N10", substr($ibuf, $strtable_section_offset,
-			       $eh[$e_shentsize]));
-
-  if ($verbose) {
-     printf("Section name strings start at: 0x%x, %d bytes.\n",
-     $strh[$sh_offset], $strh[$sh_size]);
-  }
-
-  $names = substr($ibuf, $strh[$sh_offset], $strh[$sh_size]);
-
-  # Grab each section header and find '.data', 'image', and 
-  # 'initrd' sections in particular.
-
-  $off = $eh[$e_shoff];
-  $imageFound = 0;
-  $initrdFound = 0;
-  
-  for($i = 0; $i < $eh[$e_shnum]; $i++, $off += $eh[$e_shentsize]) {
-    @sh = unpack("N10", substr($ibuf, $off, $eh[$e_shentsize]));
-
-    # Take the first section name from the array returned by split.
-
-    ($name) = split(/\000/, substr($names, $sh[$sh_name]));
-
-    # Attempt to find the .data, image, and initrd sections
-
-    if ($name =~ /^\image$/) {
-      ($image_addr, $image_offset, $image_size) =
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-      $imageFound = 1;
-
-    } elsif ($name =~ /^\initrd$/) {
-      ($initrd_addr, $initrd_offset, $initrd_size) =
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-      $initrdFound = 1;
-
-    } elsif ($name =~ /^\.data$/) {
-      ($data_addr, $data_offset, $data_size) =
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-
-    } elsif ($name =~ /^\.bss$/) {
-      ($bss_addr, $bss_offset, $bss_size) =
-	($sh[$sh_addr], $sh[$sh_offset], $sh[$sh_size]);
-
-    }
-   }
-
-  if ($verbose) {
-    printf("Data section   - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
-	   $data_addr, $data_size, $data_offset);
-    printf("Bss  section   - Address: 0x%08x, Size: 0x%08x, File Offset 0x%08x\n",
-	 $bss_addr, $bss_size, $bss_offset);
-   }
-
-  if ($verbose) {
-    if ($imageFound) {
-      printf("Image section  - Address: 0x%08x, Size: 0x%08x\n",
-	     $image_addr, $image_size);
-    } else {
-      printf("Image section not found in file: $ElfFile\n");
-    }
-
-    if ($initrdFound) {
-      printf("Initrd section - Address: 0x%08x, Size: 0x%08x\n",
-	     $initrd_addr, $initrd_size);
-    } else {
-      printf("Initrd section not found in file: $ElfFile\n");
-    }
-  }
-
-  # get file offset of irSectStart
-
-  $irSectStartoffset = hex ($irbuf);
-
-  if ($verbose) {
-    printf("irSectStartOffset Address: 0x%08x\n", $irSectStartoffset);
-  }
-
-  # get the offset of global variables 
-
-  $initialOffset = ($irSectStartoffset - $data_addr) + $data_offset + 4;
-
-  # write modified values to OUTPUT file
-
-  syswrite(OUTPUT, $ibuf, $initialOffset);
-
-  if ($imageFound) {
-    $testN = pack ("N2", $bss_addr + $bss_size, $image_size);
-    syswrite(OUTPUT, $testN, length($testN));
-    printf("Updated symbol \"imageSect_start\" to 0x%08x\n",
-	   $bss_addr + $bss_size);
-    printf("Updated symbol \"imageSect_size\" to 0x%08x\n", $image_size);
-  } else {
-    syswrite(OUTPUT, $ibuf, 8, $initialOffset);
-  }
-
-  if ($initrdFound) {
-    $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
-    syswrite(OUTPUT, $testN, length($testN));
-    printf("Updated symbol \"initrdSect_start\" to 0x%08x\n",
-	   $bss_addr + $bss_size + $image_size);
-    printf("Updated symbol \"initrdSect_size\" to 0x%08x\n", $initrd_size);
-  } else {
-    syswrite(OUTPUT, $ibuf,8, $initialOffset + 8);
-  }
-
-  syswrite(OUTPUT, $ibuf, $ElfFilesize - ($initialOffset + 16),
-	   $initialOffset + 16);
-
-  #
-  # Clean-up and leave
-  #
-
-  close (ELF);
-  close (OUTPUT);
-  close (IR);
-
-  exit (0);
-}
-
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/Makefile linux/arch/ppc/xmon/Makefile
--- v2.4.4/linux/arch/ppc/xmon/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/ppc/xmon/Makefile	Mon May 21 17:04:47 2001
@@ -1,3 +1,5 @@
+# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+#
 # Makefile for xmon
 
 O_TARGET	:= x.o
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/adb.c linux/arch/ppc/xmon/adb.c
--- v2.4.4/linux/arch/ppc/xmon/adb.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/adb.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.adb.c 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Copyright (C) 1996 Paul Mackerras.
  */
 #include "nonstdio.h"
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/ansidecl.h linux/arch/ppc/xmon/ansidecl.h
--- v2.4.4/linux/arch/ppc/xmon/ansidecl.h	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/ansidecl.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ansidecl.h 1.5 05/17/01 18:14:23 cort
+ */
 /* ANSI and traditional C compatability macros
    Copyright 1991, 1992 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/nonstdio.h linux/arch/ppc/xmon/nonstdio.h
--- v2.4.4/linux/arch/ppc/xmon/nonstdio.h	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/nonstdio.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.nonstdio.h 1.5 05/17/01 18:14:23 cort
+ */
 typedef int	FILE;
 extern FILE *xmon_stdin, *xmon_stdout;
 #define EOF	(-1)
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/ppc-dis.c linux/arch/ppc/xmon/ppc-dis.c
--- v2.4.4/linux/arch/ppc/xmon/ppc-dis.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/ppc-dis.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc-dis.c 1.5 05/17/01 18:14:23 cort
+ */
 /* ppc-dis.c -- Disassemble PowerPC instructions
    Copyright 1994 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/ppc-opc.c linux/arch/ppc/xmon/ppc-opc.c
--- v2.4.4/linux/arch/ppc/xmon/ppc-opc.c	Sat Nov 27 15:41:59 1999
+++ linux/arch/ppc/xmon/ppc-opc.c	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc-opc.c 1.5 05/17/01 18:14:23 cort
+ */
 /* ppc-opc.c -- PowerPC opcode list
    Copyright 1994 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/ppc.h linux/arch/ppc/xmon/ppc.h
--- v2.4.4/linux/arch/ppc/xmon/ppc.h	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/ppc.h	Mon May 21 17:04:47 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ppc.h 1.5 05/17/01 18:14:23 cort
+ */
 /* ppc.h -- Header file for PowerPC opcode table
    Copyright 1994 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/privinst.h linux/arch/ppc/xmon/privinst.h
--- v2.4.4/linux/arch/ppc/xmon/privinst.h	Wed May  3 01:47:57 2000
+++ linux/arch/ppc/xmon/privinst.h	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.privinst.h 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Copyright (C) 1996 Paul Mackerras.
  */
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/setjmp.c linux/arch/ppc/xmon/setjmp.c
--- v2.4.4/linux/arch/ppc/xmon/setjmp.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/setjmp.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.setjmp.c 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Copyright (C) 1996 Paul Mackerras.
  *
  * NB this file must be compiled with -O2.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
--- v2.4.4/linux/arch/ppc/xmon/start.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/xmon/start.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.start.c 1.12 05/21/01 21:39:13 paulus
+ */
+/*
  * Copyright (C) 1996 Paul Mackerras.
  */
 #include <linux/config.h>
@@ -28,7 +31,7 @@
 
 static int console;
 static int use_screen;
-static int via_modem = 1;
+static int via_modem;
 static int xmon_use_sccb;
 static struct device_node *macio_node;
 
@@ -61,27 +64,37 @@
 		struct device_node *np;
 		unsigned long addr;
 #ifdef CONFIG_BOOTX_TEXT
-		extern boot_infos_t *disp_bi;
+		if (!machine_is_compatible("iMac")) {
+			extern boot_infos_t *disp_bi;
 
-		/* see if there is a keyboard in the device tree
-		   with a parent of type "adb" */
-		for (np = find_devices("keyboard"); np; np = np->next)
-			if (np->parent && np->parent->type
-			    && strcmp(np->parent->type, "adb") == 0)
-				break;
+			/* see if there is a keyboard in the device tree
+			   with a parent of type "adb" */
+			for (np = find_devices("keyboard"); np; np = np->next)
+				if (np->parent && np->parent->type
+				    && strcmp(np->parent->type, "adb") == 0)
+					break;
 
-		/* needs to be hacked if xmon_printk is to be used
- 		   from within find_via_pmu() */
+			/* needs to be hacked if xmon_printk is to be used
+			   from within find_via_pmu() */
 #ifdef CONFIG_ADB_PMU
-		if (np != NULL && disp_bi && find_via_pmu())
-			use_screen = 1;
+			if (np != NULL && disp_bi && find_via_pmu())
+				use_screen = 1;
 #endif
 #ifdef CONFIG_ADB_CUDA
-		if (np != NULL && disp_bi && find_via_cuda())
-			use_screen = 1;
+			if (np != NULL && disp_bi && find_via_cuda())
+				use_screen = 1;
 #endif
+		}
+		prom_drawstring("xmon uses ");
 		if (use_screen)
-			prom_drawstring("xmon uses screen and keyboard\n");
+			prom_drawstring("screen and keyboard\n");
+		else {
+			if (via_modem)
+				prom_drawstring("modem on ");
+			prom_drawstring(xmon_use_sccb? "printer": "modem");
+			prom_drawstring(" port\n");
+		}
+
 #endif /* CONFIG_BOOTX_TEXT */
 
 #ifdef CHRP_ESCC
@@ -100,6 +113,15 @@
 		base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
 		sccc = base + (addr & ~PAGE_MASK);
 		sccd = sccc + 0x10;
+	}
+	else if ( _machine & _MACH_gemini )
+	{
+		/* should already be mapped by the kernel boot */
+		sccc = (volatile unsigned char *) 0xffeffb0d;
+		sccd = (volatile unsigned char *) 0xffeffb08;
+		TXRDY = 0x20;
+		RXRDY = 1;
+		console = 1;
 	}
 	else
 	{
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/start_8xx.c linux/arch/ppc/xmon/start_8xx.c
--- v2.4.4/linux/arch/ppc/xmon/start_8xx.c	Wed May  3 01:47:57 2000
+++ linux/arch/ppc/xmon/start_8xx.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.start_8xx.c 1.7 05/17/01 18:14:23 cort
+ */
+/*
  * Copyright (C) 1996 Paul Mackerras.
  * Copyright (C) 2000 Dan Malek.
  * Quick hack of Paul's code to make XMON work on 8xx processors.  Lots
@@ -15,7 +18,7 @@
 #include <asm/processor.h>
 #include <asm/8xx_immap.h>
 #include <asm/mpc8xx.h>
-#include "commproc.h"
+#include "../8xx_io/commproc.h"
 
 extern void xmon_printf(const char *fmt, ...);
 extern int xmon_8xx_write(char *str, int nb);
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/subr_prf.c linux/arch/ppc/xmon/subr_prf.c
--- v2.4.4/linux/arch/ppc/xmon/subr_prf.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/xmon/subr_prf.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.subr_prf.c 1.5 05/17/01 18:14:23 cort
+ */
+/*
  * Written by Cort Dougan to replace the version originally used
  * by Paul Mackerras, which came from NetBSD and thus had copyright
  * conflicts with Linux.
diff -u --recursive --new-file v2.4.4/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.4.4/linux/arch/ppc/xmon/xmon.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/xmon/xmon.c	Mon May 21 17:04:47 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.xmon.c 1.9 05/17/01 18:14:24 cort
+ */
+/*
  * Routines providing a simple monitor for use on the PowerMac.
  *
  * Copyright (C) 1996 Paul Mackerras.
@@ -208,10 +211,11 @@
 xmon_irq(int irq, void *d, struct pt_regs *regs)
 {
 	unsigned long flags;
-	save_flags(flags);cli();
+	__save_flags(flags);
+	__cli();
 	printf("Keyboard interrupt\n");
 	xmon(regs);
-	restore_flags(flags);
+	__restore_flags(flags);
 }
 
 int
@@ -657,7 +661,7 @@
 	unsigned stack[2];
 	struct pt_regs regs;
 	extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
-	extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
+	extern char do_bottom_half_ret, do_signal_ret;
 	extern char ret_from_except;
 
 	printf("backtrace:\n");
@@ -676,7 +680,6 @@
 		    || stack[1] == (unsigned) &ret_from_except
 		    || stack[1] == (unsigned) &ret_from_syscall_1
 		    || stack[1] == (unsigned) &ret_from_syscall_2
-		    || stack[1] == (unsigned) &lost_irq_ret
 		    || stack[1] == (unsigned) &do_bottom_half_ret
 		    || stack[1] == (unsigned) &do_signal_ret) {
 			if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/hd64465_gpio.c linux/arch/sh/kernel/hd64465_gpio.c
--- v2.4.4/linux/arch/sh/kernel/hd64465_gpio.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/hd64465_gpio.c	Sun May 20 12:11:38 2001
@@ -6,7 +6,6 @@
  * GPIO pin support for HD64465 companion chip.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/io_cat68701.c linux/arch/sh/kernel/io_cat68701.c
--- v2.4.4/linux/arch/sh/kernel/io_cat68701.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/io_cat68701.c	Sun May 20 12:11:38 2001
@@ -14,6 +14,7 @@
 
 #include <asm/io.h>
 #include <asm/machvec.h>
+#include <linux/config.h>
 #include <linux/module.h>
 
 #define SH3_PCMCIA_BUG_WORKAROUND 1
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/io_dc.c linux/arch/sh/kernel/io_dc.c
--- v2.4.4/linux/arch/sh/kernel/io_dc.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/io_dc.c	Sun May 20 12:11:38 2001
@@ -3,7 +3,6 @@
  *	I/O routines for SEGA Dreamcast
  */
 
-#include <linux/config.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
 
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/io_ec3104.c linux/arch/sh/kernel/io_ec3104.c
--- v2.4.4/linux/arch/sh/kernel/io_ec3104.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/io_ec3104.c	Sun May 20 12:11:38 2001
@@ -14,8 +14,6 @@
  * (prumpf@tux.org).
  */
 
-
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/irq_intc2.c linux/arch/sh/kernel/irq_intc2.c
--- v2.4.4/linux/arch/sh/kernel/irq_intc2.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/irq_intc2.c	Sun May 20 12:11:38 2001
@@ -12,7 +12,6 @@
  * Hitachi 7751 and the STM ST40 STB1.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/mach_dc.c linux/arch/sh/kernel/mach_dc.c
--- v2.4.4/linux/arch/sh/kernel/mach_dc.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/mach_dc.c	Sun May 20 12:11:38 2001
@@ -3,6 +3,7 @@
  *	SEGA Dreamcast machine vector
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/machvec.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/rtc.c linux/arch/sh/kernel/rtc.c
--- v2.4.4/linux/arch/sh/kernel/rtc.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/rtc.c	Thu May 24 15:14:08 2001
@@ -143,7 +143,6 @@
 
 static int set_rtc_time(unsigned long nowtime)
 {
-	extern int abs (int);
 	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/setup_dc.c linux/arch/sh/kernel/setup_dc.c
--- v2.4.4/linux/arch/sh/kernel/setup_dc.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/setup_dc.c	Sun May 20 12:11:38 2001
@@ -3,7 +3,6 @@
  *	SEGA Dreamcast support
  */
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sh/kernel/setup_ec3104.c linux/arch/sh/kernel/setup_ec3104.c
--- v2.4.4/linux/arch/sh/kernel/setup_ec3104.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/setup_ec3104.c	Sun May 20 12:11:38 2001
@@ -14,7 +14,6 @@
  * (prumpf@tux.org).
  */
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c
--- v2.4.4/linux/arch/sh/mm/cache.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/mm/cache.c	Sun May 20 12:11:38 2001
@@ -6,6 +6,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.4.4/linux/arch/sparc/config.in	Thu Apr 19 08:38:48 2001
+++ linux/arch/sparc/config.in	Mon May 21 18:12:09 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.109 2001/04/18 21:06:05 davem Exp $
+# $Id: config.in,v 1.110 2001/05/20 05:14:46 davem Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -162,9 +162,7 @@
 
    dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
 
-   if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
-      int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
-   fi
+   dep_tristate '  SCSI OnStream SC-x0 tape support' CONFIG_CHR_DEV_OSST $CONFIG_SCSI
 
    dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
 
diff -u --recursive --new-file v2.4.4/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.4.4/linux/arch/sparc/defconfig	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc/defconfig	Wed May 16 10:31:27 2001
@@ -148,7 +148,6 @@
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
-# CONFIG_IPV6_EUI64 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
 
diff -u --recursive --new-file v2.4.4/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.4.4/linux/arch/sparc/kernel/head.S	Thu Apr 26 22:17:26 2001
+++ linux/arch/sparc/kernel/head.S	Tue May  1 20:59:24 2001
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.103 2000/05/09 17:40:13 davem Exp $
+/* $Id: head.S,v 1.104 2001/04/27 07:02:41 davem Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.4.4/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.4.4/linux/arch/sparc/kernel/irq.c	Thu Apr 26 22:17:26 2001
+++ linux/arch/sparc/kernel/irq.c	Tue May  1 20:59:24 2001
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.111 2001/04/14 21:13:46 davem Exp $
+/*  $Id: irq.c,v 1.112 2001/04/27 07:02:42 davem Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
diff -u --recursive --new-file v2.4.4/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.4.4/linux/arch/sparc/kernel/sys_sunos.c	Thu Apr 26 22:17:26 2001
+++ linux/arch/sparc/kernel/sys_sunos.c	Tue May  1 20:59:24 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.133 2001/03/24 09:36:10 davem Exp $
+/* $Id: sys_sunos.c,v 1.134 2001/04/27 07:02:42 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.4.4/linux/arch/sparc/prom/console.c linux/arch/sparc/prom/console.c
--- v2.4.4/linux/arch/sparc/prom/console.c	Thu Apr 26 22:17:26 2001
+++ linux/arch/sparc/prom/console.c	Tue May  1 20:59:24 2001
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.23 2000/08/26 02:38:03 anton Exp $
+/* $Id: console.c,v 1.24 2001/04/27 07:02:42 davem Exp $
  * console.c: Routines that deal with sending and receiving IO
  *            to/from the current console device using the PROM.
  *
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.4.4/linux/arch/sparc64/config.in	Thu Apr 19 08:38:48 2001
+++ linux/arch/sparc64/config.in	Sun May 20 11:32:07 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.141 2001/04/19 01:52:04 davem Exp $
+# $Id: config.in,v 1.143 2001/05/20 05:14:46 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -146,9 +146,7 @@
 
    dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
 
-   if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
-      int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
-   fi
+   dep_tristate '  SCSI OnStream SC-x0 tape support' CONFIG_CHR_DEV_OSST $CONFIG_SCSI
 
    dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
 
@@ -337,6 +335,15 @@
 source drivers/input/Config.in
 
 source fs/Config.in
+
+mainmenu_option next_comment
+comment 'Sound'
+
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+   source drivers/sound/Config.in
+fi
+endmenu
 
 source drivers/usb/Config.in
 
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.4.4/linux/arch/sparc64/defconfig	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/defconfig	Thu May 24 15:00:58 2001
@@ -178,7 +178,6 @@
 CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
-# CONFIG_IPV6_EUI64 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
 
@@ -291,7 +290,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
-CONFIG_ST_EXTRA_DEVS=2
+CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
@@ -311,7 +310,8 @@
 CONFIG_SCSI_QLOGICPTI=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY=5000
+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
 CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8
@@ -454,6 +454,7 @@
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_MINIX_FS=m
+CONFIG_VXFS_FS=m
 # CONFIG_NTFS_FS is not set
 # CONFIG_NTFS_RW is not set
 CONFIG_HPFS_FS=m
@@ -547,6 +548,28 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+CONFIG_SOUND_ES1371=m
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+CONFIG_SOUND_TRIDENT=m
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
 # USB support
 #
 CONFIG_USB=y
@@ -561,8 +584,7 @@
 #
 # USB Controllers
 #
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_UHCI=y
 CONFIG_USB_OHCI=y
 
 #
@@ -573,6 +595,7 @@
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
 CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
 
@@ -595,6 +618,7 @@
 #
 CONFIG_USB_IBMCAM=m
 CONFIG_USB_OV511=m
+CONFIG_USB_PWC=m
 CONFIG_USB_DSBR=m
 CONFIG_USB_DABUSB=m
 
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.4.4/linux/arch/sparc64/kernel/Makefile	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/Makefile	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.66 2001/04/03 12:29:38 davem Exp $
+# $Id: Makefile,v 1.67 2001/05/11 04:31:55 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -26,7 +26,7 @@
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o
 
-obj-$(CONFIG_PCI)	 += ebus.o pci_common.o pci_iommu.o \
+obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o
 obj-$(CONFIG_SMP)	 += smp.o trampoline.o
 obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c
--- v2.4.4/linux/arch/sparc64/kernel/devices.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/devices.c	Sun May 20 12:11:38 2001
@@ -4,6 +4,7 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.4.4/linux/arch/sparc64/kernel/ioctl32.c	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.111 2001/03/27 07:28:43 davem Exp $
+/* $Id: ioctl32.c,v 1.115 2001/05/12 06:41:58 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -49,6 +49,7 @@
 #include <linux/blk.h>
 #include <linux/elevator.h>
 #include <linux/rtc.h>
+#include <linux/pci.h>
 #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
 /* Ugh. This header really is not clean */
 #define min min
@@ -514,10 +515,19 @@
 			}
 		}
 		if (!err) {
-			if (i <= ifc32.ifc_len)
+			if (ifc32.ifcbuf == 0) {
+				/* Translate from 64-bit structure multiple to
+				 * a 32-bit one.
+				 */
+				i = ifc.ifc_len;
+				i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
 				ifc32.ifc_len = i;
-			else
-				ifc32.ifc_len = i - sizeof (struct ifreq32);
+			} else {
+				if (i <= ifc32.ifc_len)
+					ifc32.ifc_len = i;
+				else
+					ifc32.ifc_len = i - sizeof (struct ifreq32);
+			}
 			if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
 				err = -EFAULT;
 		}
@@ -3369,11 +3379,6 @@
 COMPATIBLE_IOCTL(SIOCSARP)
 COMPATIBLE_IOCTL(SIOCGARP)
 COMPATIBLE_IOCTL(SIOCDARP)
-#if 0 /* XXX No longer exist in new routing code. XXX */
-COMPATIBLE_IOCTL(OLD_SIOCSARP)
-COMPATIBLE_IOCTL(OLD_SIOCGARP)
-COMPATIBLE_IOCTL(OLD_SIOCDARP)
-#endif
 COMPATIBLE_IOCTL(SIOCSRARP)
 COMPATIBLE_IOCTL(SIOCGRARP)
 COMPATIBLE_IOCTL(SIOCDRARP)
@@ -3714,6 +3719,13 @@
 COMPATIBLE_IOCTL(WIOCSTART)
 COMPATIBLE_IOCTL(WIOCSTOP)
 COMPATIBLE_IOCTL(WIOCGSTAT)
+/* Misc. */
+COMPATIBLE_IOCTL(0x41545900)		/* ATYIO_CLKR */
+COMPATIBLE_IOCTL(0x41545901)		/* ATYIO_CLKW */
+COMPATIBLE_IOCTL(PCIIOC_CONTROLLER)
+COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
+COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM)
+COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE)
 /* And these ioctls need translation */
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
@@ -3991,8 +4003,9 @@
 	} else {
 		static int count = 0;
 		if (++count <= 20)
-			printk("sys32_ioctl: Unknown cmd fd(%d) "
+			printk("sys32_ioctl(%s:%d): Unknown cmd fd(%d) "
 			       "cmd(%08x) arg(%08x)\n",
+			       current->comm, current->pid,
 			       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		error = -EINVAL;
 	}
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/isa.c linux/arch/sparc64/kernel/isa.c
--- v2.4.4/linux/arch/sparc64/kernel/isa.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/isa.c	Wed May 16 10:31:27 2001
@@ -0,0 +1,269 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <asm/oplib.h>
+#include <asm/isa.h>
+
+struct isa_bridge *isa_chain;
+
+static void __init fatal_err(const char *reason)
+{
+	prom_printf("ISA: fatal error, %s.\n", reason);
+}
+
+static void __init report_dev(struct isa_device *isa_dev, int child)
+{
+	if (child)
+		printk(" (%s)", isa_dev->prom_name);
+	else
+		printk(" [%s", isa_dev->prom_name);
+}
+
+static void __init isa_dev_get_resource(struct isa_device *isa_dev)
+{
+	struct linux_prom_registers regs[PROMREG_MAX];
+	unsigned long base, len;
+	int prop_len;
+
+	prop_len = prom_getproperty(isa_dev->prom_node, "reg",
+				    (char *) regs, sizeof(regs));
+
+	if (prop_len <= 0)
+		return;
+
+	/* Only the first one is interesting. */
+	len = regs[0].reg_size;
+	base = (((unsigned long)regs[0].which_io << 32) |
+		(unsigned long)regs[0].phys_addr);
+	base += isa_dev->bus->parent->io_space.start;
+
+	isa_dev->resource.start = base;
+	isa_dev->resource.end   = (base + len - 1UL);
+	isa_dev->resource.flags = IORESOURCE_IO;
+	isa_dev->resource.name  = isa_dev->prom_name;
+
+	request_resource(&isa_dev->bus->parent->io_space,
+			 &isa_dev->resource);
+}
+
+/* I can't believe they didn't put a real INO in the isa device
+ * interrupts property.  The whole point of the OBP properties
+ * is to shield the kernel from IRQ routing details.
+ *
+ * The P1275 standard for ISA devices seems to also have been
+ * totally ignored.
+ */
+static struct {
+	int	obp_irq;
+	int	pci_ino;
+} grover_irq_table[] = {
+	{ 1, 0x00 },	/* dma, unknown ino at this point */
+	{ 2, 0x27 },	/* floppy */
+	{ 3, 0x22 },	/* parallel */
+	{ 4, 0x2b },	/* serial */
+	{ 5, 0x25 },	/* acpi power management */
+
+	{ 0, 0x00 }	/* end of table */
+};
+
+static void __init isa_dev_get_irq(struct isa_device *isa_dev)
+{
+	int irq_prop;
+
+	irq_prop = prom_getintdefault(isa_dev->prom_node,
+				      "interrupts", -1);
+	if (irq_prop <= 0) {
+		isa_dev->irq = 0;
+	} else {
+		int i;
+
+		for (i = 0; grover_irq_table[i].obp_irq != 0; i++) {
+			if (grover_irq_table[i].obp_irq == irq_prop) {
+				struct pci_controller_info *pcic;
+				struct pci_pbm_info *pbm;
+				int ino = grover_irq_table[i].pci_ino;
+
+				if (ino == 0) {
+					isa_dev->irq = 0;
+				} else {
+					pbm = isa_dev->bus->parent;
+					pcic = pbm->parent;
+					isa_dev->irq = pcic->irq_build(pbm, NULL, ino);
+				}
+			}
+		}
+	}
+}
+
+static void __init isa_fill_children(struct isa_device *parent_isa_dev)
+{
+	int node = prom_getchild(parent_isa_dev->prom_node);
+
+	if (node == 0)
+		return;
+
+	printk(" ->");
+	while (node != 0) {
+		struct isa_device *isa_dev;
+		int prop_len;
+
+		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+		if (!isa_dev) {
+			fatal_err("cannot allocate child isa_dev");
+			prom_halt();
+		}
+
+		memset(isa_dev, 0, sizeof(*isa_dev));
+
+		/* Link it in to parent. */
+		isa_dev->next = parent_isa_dev->child;
+		parent_isa_dev->child = isa_dev;
+
+		isa_dev->bus = parent_isa_dev->bus;
+		isa_dev->prom_node = node;
+		prop_len = prom_getproperty(node, "name",
+					    (char *) isa_dev->prom_name,
+					    sizeof(isa_dev->prom_name));
+		if (prop_len <= 0) {
+			fatal_err("cannot get child isa_dev OBP node name");
+			prom_halt();
+		}
+
+		prop_len = prom_getproperty(node, "compatible",
+					    (char *) isa_dev->compatible,
+					    sizeof(isa_dev->compatible));
+
+		/* Not having this is OK. */
+		if (prop_len <= 0)
+			isa_dev->compatible[0] = '\0';
+
+		isa_dev_get_resource(isa_dev);
+		isa_dev_get_irq(isa_dev);
+
+		report_dev(isa_dev, 1);
+
+		node = prom_getsibling(node);
+	}
+}
+
+static void __init isa_fill_devices(struct isa_bridge *isa_br)
+{
+	int node = prom_getchild(isa_br->prom_node);
+
+	while (node != 0) {
+		struct isa_device *isa_dev;
+		int prop_len;
+
+		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+		if (!isa_dev) {
+			fatal_err("cannot allocate isa_dev");
+			prom_halt();
+		}
+
+		memset(isa_dev, 0, sizeof(*isa_dev));
+
+		/* Link it in. */
+		isa_dev->next = NULL;
+		if (isa_br->devices == NULL) {
+			isa_br->devices = isa_dev;
+		} else {
+			struct isa_device *tmp = isa_br->devices;
+
+			while (tmp->next)
+				tmp = tmp->next;
+
+			tmp->next = isa_dev;
+		}
+
+		isa_dev->bus = isa_br;
+		isa_dev->prom_node = node;
+		prop_len = prom_getproperty(node, "name",
+					    (char *) isa_dev->prom_name,
+					    sizeof(isa_dev->prom_name));
+		if (prop_len <= 0) {
+			fatal_err("cannot get isa_dev OBP node name");
+			prom_halt();
+		}
+
+		prop_len = prom_getproperty(node, "compatible",
+					    (char *) isa_dev->compatible,
+					    sizeof(isa_dev->compatible));
+
+		/* Not having this is OK. */
+		if (prop_len <= 0)
+			isa_dev->compatible[0] = '\0';
+
+		isa_dev_get_resource(isa_dev);
+		isa_dev_get_irq(isa_dev);
+
+		report_dev(isa_dev, 0);
+
+		isa_fill_children(isa_dev);
+
+		printk("]");
+
+		node = prom_getsibling(node);
+	}
+}
+
+void __init isa_init(void)
+{
+	struct pci_dev *pdev;
+	unsigned short vendor, device;
+	int index = 0;
+
+	vendor = PCI_VENDOR_ID_AL;
+	device = PCI_DEVICE_ID_AL_M1533;
+
+	pdev = NULL;
+	while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) {
+		struct pcidev_cookie *pdev_cookie;
+		struct pci_pbm_info *pbm;
+		struct isa_bridge *isa_br;
+		int prop_len;
+
+		pdev_cookie = pdev->sysdata;
+		if (!pdev_cookie) {
+			printk("ISA: Warning, ISA bridge ignored due to "
+			       "lack of OBP data.\n");
+			continue;
+		}
+		pbm = pdev_cookie->pbm;
+
+		isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
+		if (!isa_br) {
+			fatal_err("cannot allocate isa_bridge");
+			prom_halt();
+		}
+
+		memset(isa_br, 0, sizeof(*isa_br));
+
+		/* Link it in. */
+		isa_br->next = isa_chain;
+		isa_chain = isa_br;
+
+		isa_br->parent = pbm;
+		isa_br->self = pdev;
+		isa_br->index = index++;
+		isa_br->prom_node = pdev_cookie->prom_node;
+		strncpy(isa_br->prom_name, pdev_cookie->prom_name,
+			sizeof(isa_br->prom_name));
+
+		prop_len = prom_getproperty(isa_br->prom_node,
+					    "ranges",
+					    (char *) isa_br->isa_ranges,
+					    sizeof(isa_br->isa_ranges));
+		if (prop_len <= 0)
+			isa_br->num_isa_ranges = 0;
+		else
+			isa_br->num_isa_ranges =
+				(prop_len / sizeof(struct linux_prom_isa_ranges));
+
+		printk("isa%d:", isa_br->index);
+
+		isa_fill_devices(isa_br);
+
+		printk("\n");
+	}
+}
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.4.4/linux/arch/sparc64/kernel/pci.c	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/pci.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.24 2001/03/28 10:56:34 davem Exp $
+/* $Id: pci.c,v 1.29 2001/05/15 08:54:30 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -19,6 +19,7 @@
 #include <asm/pbm.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
+#include <asm/isa.h>
 
 unsigned long pci_memspace_mask = 0xffffffffUL;
 
@@ -77,13 +78,13 @@
 volatile int pci_poke_faulted;
 
 /* Probe for all PCI controllers in the system. */
-extern void sabre_init(int);
-extern void psycho_init(int);
-extern void schizo_init(int);
+extern void sabre_init(int, char *);
+extern void psycho_init(int, char *);
+extern void schizo_init(int, char *);
 
 static struct {
 	char *model_name;
-	void (*init)(int);
+	void (*init)(int, char *);
 } pci_controller_table[] = {
 	{ "SUNW,sabre", sabre_init },
 	{ "pci108e,a000", sabre_init },
@@ -104,7 +105,7 @@
 		if (!strncmp(model_name,
 			     pci_controller_table[i].model_name,
 			     namelen)) {
-			pci_controller_table[i].init(node);
+			pci_controller_table[i].init(node, model_name);
 			return;
 		}
 	}
@@ -187,6 +188,7 @@
 	if (pci_device_reorder)
 		pci_reorder_devs();
 
+	isa_init();
 	ebus_init();
 }
 
@@ -232,6 +234,149 @@
 		return NULL;
 	}
 	return str;
+}
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+/* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding
+ * to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+					     enum pci_mmap_state mmap_state)
+{
+	unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long user32 = user_offset & 0xffffffffUL;
+	unsigned long largest_base, this_base, addr32;
+	int i;
+
+	/* Figure out which base address this is for. */
+	largest_base = 0UL;
+	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+		struct resource *rp = &dev->resource[i];
+
+		/* Active? */
+		if (!rp->flags)
+			continue;
+
+		/* Same type? */
+		if (i == PCI_ROM_RESOURCE) {
+			if (mmap_state != pci_mmap_mem)
+				continue;
+		} else {
+			if ((mmap_state == pci_mmap_io &&
+			     (rp->flags & IORESOURCE_IO) == 0) ||
+			    (mmap_state == pci_mmap_mem &&
+			     (rp->flags & IORESOURCE_MEM) == 0))
+				continue;
+		}
+
+		this_base = rp->start;
+
+		addr32 = (this_base & PAGE_MASK) & 0xffffffffUL;
+
+		if (mmap_state == pci_mmap_io)
+			addr32 &= 0xffffff;
+
+		if (addr32 <= user32 && this_base > largest_base)
+			largest_base = this_base;
+	}
+
+	if (largest_base == 0UL)
+		return -EINVAL;
+
+	/* Now construct the final physical address. */
+	if (mmap_state == pci_mmap_io)
+		vma->vm_pgoff = (((largest_base & ~0xffffffUL) | user32) >> PAGE_SHIFT);
+	else
+		vma->vm_pgoff = (((largest_base & ~0xffffffffUL) | user32) >> PAGE_SHIFT);
+
+	return 0;
+}
+
+/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
+ * mapping.
+ */
+static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+					    enum pci_mmap_state mmap_state)
+{
+	vma->vm_flags |= (VM_SHM | VM_LOCKED);
+}
+
+/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+					     enum pci_mmap_state mmap_state)
+{
+	/* Our io_remap_page_range takes care of this, do nothing. */
+}
+
+extern int io_remap_page_range(unsigned long from, unsigned long offset,
+			       unsigned long size, pgprot_t prot, int space);
+
+/* Perform the actual remap of the pages for a PCI device mapping, as appropriate
+ * for this architecture.  The region in the process to map is described by vm_start
+ * and vm_end members of VMA, the base physical address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state,
+			int write_combine)
+{
+	int ret;
+
+	ret = __pci_mmap_make_offset(dev, vma, mmap_state);
+	if (ret < 0)
+		return ret;
+
+	__pci_mmap_set_flags(dev, vma, mmap_state);
+	__pci_mmap_set_pgprot(dev, vma, mmap_state);
+
+	ret = io_remap_page_range(vma->vm_start,
+				  (vma->vm_pgoff << PAGE_SHIFT |
+				   (write_combine ? 0x1UL : 0x0UL)),
+				  vma->vm_end - vma->vm_start, vma->vm_page_prot, 0);
+	if (ret)
+		return ret;
+
+	vma->vm_flags |= VM_IO;
+	return 0;
+}
+
+/* Return the index of the PCI controller for device PDEV. */
+
+int pci_controller_num(struct pci_dev *pdev)
+{
+	struct pcidev_cookie *cookie = pdev->sysdata;
+	int ret;
+
+	if (cookie != NULL) {
+		struct pci_pbm_info *pbm = cookie->pbm;
+		if (pbm == NULL || pbm->parent == NULL) {
+			ret = -ENXIO;
+		} else {
+			struct pci_controller_info *p = pbm->parent;
+
+			ret = p->index;
+			if (p->pbms_same_domain == 0)
+				ret = ((ret << 1) +
+				       ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
+		}
+	} else {
+		ret = -ENXIO;
+	}
+
+	return ret;
 }
 
 #endif /* !(CONFIG_PCI) */
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- v2.4.4/linux/arch/sparc64/kernel/pci_common.c	Tue Mar  6 22:44:16 2001
+++ linux/arch/sparc64/kernel/pci_common.c	Sat May 19 18:13:15 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.14 2001/02/28 03:28:55 davem Exp $
+/* $Id: pci_common.c,v 1.18 2001/05/18 23:06:35 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -10,6 +10,29 @@
 
 #include <asm/pbm.h>
 
+/* Fix self device of BUS and hook it into BUS->self.
+ * The pci_scan_bus does not do this for the host bridge.
+ */
+void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
+{
+	struct list_head *walk = &pbus->devices;
+
+	walk = walk->next;
+	while (walk != &pbus->devices) {
+		struct pci_dev *pdev = pci_dev_b(walk);
+
+		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
+			pbus->self = pdev;
+			return;
+		}
+
+		walk = walk->next;
+	}
+
+	prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
+	prom_halt();
+}
+
 /* Find the OBP PROM device tree node for a PCI device.
  * Return zero if not found.
  */
@@ -29,7 +52,10 @@
 	 */
 	if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) &&
 	    (pdev->vendor == PCI_VENDOR_ID_SUN) &&
-	    (pdev->device == PCI_DEVICE_ID_SUN_PBM)) {
+	    (pdev->device == PCI_DEVICE_ID_SUN_PBM ||
+	     pdev->device == PCI_DEVICE_ID_SUN_SCHIZO ||
+	     pdev->device == PCI_DEVICE_ID_SUN_SABRE ||
+	     pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) {
 		*nregs = 0;
 		return bus_prom_node;
 	}
@@ -474,15 +500,21 @@
 
 static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
 {
+	struct linux_prom_pci_intmap bridge_local_intmap[PROM_PCIIMAP_MAX], *intmap;
+	struct linux_prom_pci_intmask bridge_local_intmask, *intmask;
 	struct pcidev_cookie *dev_pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = dev_pcp->pbm;
 	struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs;
 	unsigned int hi, mid, lo, irq;
-	int i;
+	int i, num_intmap;
 
 	if (pbm->num_pbm_intmap == 0)
 		return 0;
 
+	intmap = &pbm->pbm_intmap[0];
+	intmask = &pbm->pbm_intmask;
+	num_intmap = pbm->num_pbm_intmap;
+
 	/* If we are underneath a PCI bridge, use PROM register
 	 * property of the parent bridge which is closest to
 	 * the PBM.
@@ -490,7 +522,7 @@
 	if (pdev->bus->number != pbm->pci_first_busno) {
 		struct pcidev_cookie *bus_pcp;
 		struct pci_dev *pwalk;
-		int offset;
+		int offset, plen;
 
 		pwalk = pdev->bus->self;
 		while (pwalk->bus &&
@@ -498,6 +530,27 @@
 			pwalk = pwalk->bus->self;
 
 		bus_pcp = pwalk->sysdata;
+
+		/* But if the PCI bridge has it's own interrupt map
+		 * and mask properties, use that and the device regs.
+		 */
+		plen = prom_getproperty(bus_pcp->prom_node, "interrupt-map",
+					(char *) &bridge_local_intmap[0],
+					sizeof(bridge_local_intmap));
+		if (plen != -1) {
+			intmap = &bridge_local_intmap[0];
+			num_intmap = plen / sizeof(struct linux_prom_pci_intmap);
+			plen = prom_getproperty(bus_pcp->prom_node, "interrupt-map-mask",
+						(char *) &bridge_local_intmask,
+						sizeof(bridge_local_intmask));
+			if (plen == -1) {
+				prom_printf("pbm_intmap_match: Bridge has intmap but "
+					    "no intmask.\n");
+				prom_halt();
+			}
+			goto check_intmap;
+		}
+
 		pregs = bus_pcp->prom_regs;
 
 		offset = prom_getint(dev_pcp->prom_node,
@@ -518,17 +571,18 @@
 		}
 	}
 
-	hi   = pregs->phys_hi & pbm->pbm_intmask.phys_hi;
-	mid  = pregs->phys_mid & pbm->pbm_intmask.phys_mid;
-	lo   = pregs->phys_lo & pbm->pbm_intmask.phys_lo;
-	irq  = *interrupt & pbm->pbm_intmask.interrupt;
-
-	for (i = 0; i < pbm->num_pbm_intmap; i++) {
-		if (pbm->pbm_intmap[i].phys_hi  == hi	&&
-		    pbm->pbm_intmap[i].phys_mid == mid	&&
-		    pbm->pbm_intmap[i].phys_lo  == lo	&&
-		    pbm->pbm_intmap[i].interrupt == irq) {
-			*interrupt = pbm->pbm_intmap[i].cinterrupt;
+check_intmap:
+	hi   = pregs->phys_hi & intmask->phys_hi;
+	mid  = pregs->phys_mid & intmask->phys_mid;
+	lo   = pregs->phys_lo & intmask->phys_lo;
+	irq  = *interrupt & intmask->interrupt;
+
+	for (i = 0; i < num_intmap; i++) {
+		if (intmap[i].phys_hi  == hi	&&
+		    intmap[i].phys_mid == mid	&&
+		    intmap[i].phys_lo  == lo	&&
+		    intmap[i].interrupt == irq) {
+			*interrupt = intmap[i].cinterrupt;
 			return 1;
 		}
 	}
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h
--- v2.4.4/linux/arch/sparc64/kernel/pci_impl.h	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/pci_impl.h	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_impl.h,v 1.7 2001/03/28 10:56:34 davem Exp $
+/* $Id: pci_impl.h,v 1.8 2001/05/15 08:54:30 davem Exp $
  * pci_impl.h: Helper definitions for PCI controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -19,6 +19,7 @@
 extern int pci_num_controllers;
 
 /* PCI bus scanning and fixup support. */
+extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
 extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
 				    int prom_node);
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c
--- v2.4.4/linux/arch/sparc64/kernel/pci_iommu.c	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc64/kernel/pci_iommu.c	Thu May 24 15:00:58 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_iommu.c,v 1.13 2001/03/14 08:42:38 davem Exp $
+/* $Id: pci_iommu.c,v 1.14 2001/05/23 03:06:51 davem Exp $
  * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -58,7 +58,7 @@
 
 static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
-	iopte_t *iopte, *limit;
+	iopte_t *iopte, *limit, *first;
 	unsigned long cnum, ent, flush_point;
 
 	cnum = 0;
@@ -77,6 +77,7 @@
 	iopte += ((ent = iommu->alloc_info[cnum].next) << cnum);
 	flush_point = iommu->alloc_info[cnum].flush;
 	
+	first = iopte;
 	for (;;) {
 		if (iopte_val(*iopte) == 0UL) {
 			if ((iopte + (1 << cnum)) >= limit)
@@ -98,10 +99,17 @@
 		}
 		if (ent == flush_point)
 			__iommu_flushall(iommu);
+		if (iopte == first)
+			goto bad;
 	}
 
 	/* I've got your streaming cluster right here buddy boy... */
 	return iopte;
+
+bad:
+	printk(KERN_EMERG "pci_iommu: alloc_streaming_cluster of npages(%ld) failed!\n",
+	       npages);
+	return NULL;
 }
 
 static void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base,
@@ -319,6 +327,8 @@
 	spin_lock_irqsave(&iommu->lock, flags);
 
 	base = alloc_streaming_cluster(iommu, npages);
+	if (base == NULL)
+		goto bad;
 	bus_addr = (iommu->page_table_map_base +
 		    ((base - iommu->page_table) << PAGE_SHIFT));
 	ret = bus_addr | (oaddr & ~PAGE_MASK);
@@ -339,6 +349,11 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return ret;
+
+bad:
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	BUG();
+	return 0;
 }
 
 /* Unmap a single streaming mode DMA translation. */
@@ -517,6 +532,8 @@
 	spin_lock_irqsave(&iommu->lock, flags);
 
 	base = alloc_streaming_cluster(iommu, npages);
+	if (base == NULL)
+		goto bad;
 	dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT);
 
 	/* Step 3: Normalize DMA addresses. */
@@ -550,6 +567,11 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return used;
+
+bad:
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	BUG();
+	return 0;
 }
 
 /* Unmap a set of streaming mode DMA translations. */
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.4.4/linux/arch/sparc64/kernel/pci_psycho.c	Thu Apr 19 08:38:49 2001
+++ linux/arch/sparc64/kernel/pci_psycho.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.22 2001/04/17 01:19:23 davem Exp $
+/* $Id: pci_psycho.c,v 1.24 2001/05/15 08:54:30 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1235,9 +1235,23 @@
 static void __init pbm_scan_bus(struct pci_controller_info *p,
 				struct pci_pbm_info *pbm)
 {
+	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+
+	if (!cookie) {
+		prom_printf("PSYCHO: Critical allocation failure.\n");
+		prom_halt();
+	}
+
+	/* All we care about is the PBM. */
+	memset(cookie, 0, sizeof(*cookie));
+	cookie->pbm = pbm;
+
 	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
 				    p->pci_ops,
 				    pbm);
+	pci_fixup_host_bridge_self(pbm->pci_bus);
+	pbm->pci_bus->self->sysdata = cookie;
+
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
@@ -1521,7 +1535,7 @@
 
 #define PSYCHO_CONFIGSPACE	0x001000000UL
 
-void __init psycho_init(int node)
+void __init psycho_init(int node, char *model_name)
 {
 	struct linux_prom64_registers pr_regs[3];
 	struct pci_controller_info *p;
@@ -1564,6 +1578,7 @@
 
 	p->portid = upa_portid;
 	p->index = pci_num_controllers++;
+	p->pbms_same_domain = 0;
 	p->scan_bus = psycho_scan_bus;
 	p->irq_build = psycho_irq_build;
 	p->base_address_update = psycho_base_address_update;
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.4.4/linux/arch/sparc64/kernel/pci_sabre.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/pci_sabre.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.27 2001/04/24 05:14:12 davem Exp $
+/* $Id: pci_sabre.c,v 1.32 2001/05/15 11:10:01 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -215,7 +215,7 @@
 	 ((unsigned long)(DEVFN) << 8)  |	\
 	 ((unsigned long)(REG)))
 
-static int apb_present;
+static int hummingbird_p;
 
 static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
 				     unsigned char bus,
@@ -231,7 +231,7 @@
 
 static int sabre_out_of_range(unsigned char devfn)
 {
-	if (!apb_present)
+	if (hummingbird_p)
 		return 0;
 
 	return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
@@ -243,7 +243,7 @@
 				unsigned char bus,
 				unsigned char devfn)
 {
-	if (!apb_present)
+	if (hummingbird_p)
 		return 0;
 
 	return ((pbm->parent == 0) ||
@@ -1112,11 +1112,28 @@
 	}
 }
 
+static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
+{
+	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+
+	if (!cookie) {
+		prom_printf("SABRE: Critical allocation failure.\n");
+		prom_halt();
+	}
+
+	/* All we care about is the PBM. */
+	memset(cookie, 0, sizeof(*cookie));
+	cookie->pbm = pbm;
+
+	return cookie;
+}
+
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
 	static int once = 0;
 	struct pci_bus *sabre_bus;
 	struct pci_pbm_info *pbm;
+	struct pcidev_cookie *cookie;
 	struct list_head *walk;
 	int sabres_scanned;
 
@@ -1142,10 +1159,15 @@
 	}
 	once++;
 
+	cookie = alloc_bridge_cookie(&p->pbm_A);
+
 	/* The pci_bus2pbm table has already been setup in sabre_init. */
 	sabre_bus = pci_scan_bus(p->pci_first_busno,
 				 p->pci_ops,
 				 &p->pbm_A);
+	pci_fixup_host_bridge_self(sabre_bus);
+	sabre_bus->self->sysdata = cookie;
+
 	apb_init(p, sabre_bus);
 
 	sabres_scanned = 0;
@@ -1161,6 +1183,9 @@
 		} else
 			continue;
 
+		cookie = alloc_bridge_cookie(pbm);
+		pbus->self->sysdata = cookie;
+
 		sabres_scanned++;
 
 		pbus->sysdata = pbm;
@@ -1444,6 +1469,11 @@
 			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 		}
 
+
+		sprintf(pbm->name, "SABRE%d PBM%c", p->index,
+			(pbm == &p->pbm_A ? 'A' : 'B'));
+		pbm->io_space.name = pbm->mem_space.name = pbm->name;
+
 		/* Hack up top-level resources. */
 		pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;
 		pbm->io_space.end   = pbm->io_space.start + (1UL << 16) - 1UL;
@@ -1461,12 +1491,10 @@
 			prom_printf("Cannot register Hummingbird's MEM space.\n");
 			prom_halt();
 		}
-	} else {
-		apb_present = 1;
 	}
 }
 
-void __init sabre_init(int pnode)
+void __init sabre_init(int pnode, char *model_name)
 {
 	struct linux_prom64_registers pr_regs[2];
 	struct pci_controller_info *p;
@@ -1478,6 +1506,18 @@
 	u32 upa_portid, dma_mask;
 	int bus;
 
+	hummingbird_p = 0;
+	if (!strcmp(model_name, "pci108e,a001"))
+		hummingbird_p = 1;
+	else if (!strcmp(model_name, "SUNW,sabre")) {
+		char compat[64];
+
+		if (prom_getproperty(pnode, "compatible",
+				     compat, sizeof(compat)) > 0 &&
+		    !strcmp(compat, "pci108e,a001"))
+			hummingbird_p = 1;
+	}
+
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
 	if (!p) {
 		prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");
@@ -1502,6 +1542,7 @@
 
 	p->portid = upa_portid;
 	p->index = pci_num_controllers++;
+	p->pbms_same_domain = 1;
 	p->scan_bus = sabre_scan_bus;
 	p->irq_build = sabre_irq_build;
 	p->base_address_update = sabre_base_address_update;
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c
--- v2.4.4/linux/arch/sparc64/kernel/pci_schizo.c	Thu Apr 19 08:38:49 2001
+++ linux/arch/sparc64/kernel/pci_schizo.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_schizo.c,v 1.14 2001/04/17 01:19:23 davem Exp $
+/* $Id: pci_schizo.c,v 1.16 2001/05/15 08:54:30 davem Exp $
  * pci_schizo.c: SCHIZO specific PCI controller support.
  *
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
@@ -1328,9 +1328,23 @@
 static void __init pbm_scan_bus(struct pci_controller_info *p,
 				struct pci_pbm_info *pbm)
 {
+	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+
+	if (!cookie) {
+		prom_printf("SCHIZO: Critical allocation failure.\n");
+		prom_halt();
+	}
+
+	/* All we care about is the PBM. */
+	memset(cookie, 0, sizeof(*cookie));
+	cookie->pbm = pbm;
+
 	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
 				    p->pci_ops,
 				    pbm);
+	pci_fixup_host_bridge_self(pbm->pci_bus);
+	pbm->pci_bus->self->sysdata = cookie;
+
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
@@ -1709,7 +1723,7 @@
 	schizo_write(pbm_b_base + 0x2000UL, tmp);
 }
 
-void __init schizo_init(int node)
+void __init schizo_init(int node, char *model_name)
 {
 	struct linux_prom64_registers pr_regs[3];
 	struct pci_controller_info *p;
@@ -1761,6 +1775,7 @@
 
 	p->portid = portid;
 	p->index = pci_num_controllers++;
+	p->pbms_same_domain = 0;
 	p->scan_bus = schizo_scan_bus;
 	p->irq_build = schizo_irq_build;
 	p->base_address_update = schizo_base_address_update;
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c
--- v2.4.4/linux/arch/sparc64/kernel/sbus.c	Sun Feb 18 19:49:54 2001
+++ linux/arch/sparc64/kernel/sbus.c	Thu May 24 15:00:58 2001
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.13 2001/02/13 01:16:44 davem Exp $
+/* $Id: sbus.c,v 1.14 2001/05/23 03:06:51 davem Exp $
  * sbus.c: UltraSparc SBUS controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -133,7 +133,7 @@
 
 static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
 {
-	iopte_t *iopte, *limit;
+	iopte_t *iopte, *limit, *first;
 	unsigned long cnum, ent, flush_point;
 
 	cnum = 0;
@@ -150,6 +150,7 @@
 	iopte += ((ent = iommu->alloc_info[cnum].next) << cnum);
 	flush_point = iommu->alloc_info[cnum].flush;
 
+	first = iopte;
 	for (;;) {
 		if (iopte_val(*iopte) == 0UL) {
 			if ((iopte + (1 << cnum)) >= limit)
@@ -169,10 +170,17 @@
 		}
 		if (ent == flush_point)
 			__iommu_flushall(iommu);
+		if (iopte == first)
+			goto bad;
 	}
 
 	/* I've got your streaming cluster right here buddy boy... */
 	return iopte;
+
+bad:
+	printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n",
+	       npages);
+	return NULL;
 }
 
 static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages)
@@ -332,6 +340,8 @@
 	spin_lock_irqsave(&iommu->lock, flags);
 	npages = size >> PAGE_SHIFT;
 	iopte = alloc_streaming_cluster(iommu, npages);
+	if (iopte == NULL)
+		goto bad;
 	dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT);
 	npages = size >> PAGE_SHIFT;
 	iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
@@ -345,6 +355,11 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return (dma_base | offset);
+
+bad:
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	BUG();
+	return 0;
 }
 
 void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction)
@@ -455,6 +470,8 @@
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	iopte = alloc_streaming_cluster(iommu, npages);
+	if (iopte == NULL)
+		goto bad;
 	dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT);
 
 	/* Normalize DVMA addresses. */
@@ -479,6 +496,11 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return used;
+
+bad:
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	BUG();
+	return 0;
 }
 
 void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction)
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/semaphore.c linux/arch/sparc64/kernel/semaphore.c
--- v2.4.4/linux/arch/sparc64/kernel/semaphore.c	Tue Apr 17 17:19:30 2001
+++ linux/arch/sparc64/kernel/semaphore.c	Sun May 20 11:32:07 2001
@@ -1,128 +1,88 @@
-/* $Id: semaphore.c,v 1.6 2001/04/14 01:12:02 davem Exp $
- *  Generic semaphore code. Buyer beware. Do your own
- * specific changes in <asm/semaphore-helper.h>
+/* $Id: semaphore.c,v 1.8 2001/05/18 08:01:35 davem Exp $
+ * semaphore.c: Sparc64 semaphore implementation.
+ *
+ * This is basically the PPC semaphore scheme ported to use
+ * the sparc64 atomic instructions, so see the PPC code for
+ * credits.
  */
 
 #include <linux/sched.h>
-#include <asm/semaphore-helper.h>
 
 /*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
- *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
  *
- * This routine adds one to the count of processes that need to
- * wake up and exit.  ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore.  The others will go back
- * to sleep.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
+ *	old_count = sem->count;
+ *	tmp = MAX(old_count, 0) + incr;
+ *	sem->count = tmp;
+ *	return old_count;
  */
+static __inline__ int __sem_update_count(struct semaphore *sem, int incr)
+{
+	int old_count, tmp;
+
+	__asm__ __volatile__("\n"
+"	! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n"
+"1:	ldsw	[%3], %0\n"
+"	mov	%0, %1\n"
+"	cmp	%0, 0\n"
+"	movl	%%icc, 0, %1\n"
+"	add	%1, %4, %1\n"
+"	cas	[%3], %0, %1\n"
+"	cmp	%0, %1\n"
+"	bne,pn	%%icc, 1b\n"
+"	 nop\n"
+	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+	: "r" (&sem->count), "r" (incr), "m" (sem->count)
+	: "cc");
+
+	return old_count;
+}
+
 void __up(struct semaphore *sem)
 {
-	wake_one_more(sem);
+	__sem_update_count(sem, 1);
 	wake_up(&sem->wait);
 }
 
-/*
- * Perform the "down" function.  Return zero for semaphore acquired,
- * return negative for signalled out of the function.
- *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible.  This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return.  If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
- *
- * Either form may be used in conjunction with "up()".
- *
- */
-
-#define DOWN_VAR				\
-	struct task_struct *tsk = current;	\
+void __down(struct semaphore * sem)
+{
+	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
 
-#define DOWN_HEAD(task_state)						\
-									\
-									\
-	tsk->state = (task_state);					\
-	add_wait_queue(&sem->wait, &wait);				\
-									\
-	/*								\
-	 * Ok, we're set up.  sem->count is known to be less than zero	\
-	 * so we must wait.						\
-	 *								\
-	 * We can let go the lock for purposes of waiting.		\
-	 * We re-acquire it after awaking so as to protect		\
-	 * all semaphore operations.					\
-	 *								\
-	 * If "up()" is called before we call waking_non_zero() then	\
-	 * we will catch it right away.  If it is called later then	\
-	 * we will have to go through a wakeup cycle to catch it.	\
-	 *								\
-	 * Multiple waiters contend for the semaphore lock to see	\
-	 * who gets to gate through and who has to wait some more.	\
-	 */								\
-	for (;;) {
-
-#define DOWN_TAIL(task_state)			\
-		tsk->state = (task_state);	\
-	}					\
-	tsk->state = TASK_RUNNING;		\
+	tsk->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	while (__sem_update_count(sem, -1) <= 0) {
+		schedule();
+		tsk->state = TASK_UNINTERRUPTIBLE;
+	}
 	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
 
-void __down(struct semaphore * sem)
-{
-	DOWN_VAR
-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
-	if (waking_non_zero(sem))
-		break;
-	schedule();
-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+	wake_up(&sem->wait);
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-	int ret = 0;
-	DOWN_VAR
-	DOWN_HEAD(TASK_INTERRUPTIBLE)
-
-	ret = waking_non_zero_interruptible(sem, tsk);
-	if (ret)
-	{
-		if (ret == 1)
-			/* ret != 0 only if we get interrupted -arca */
-			ret = 0;
-		break;
-	}
-	schedule();
-	DOWN_TAIL(TASK_INTERRUPTIBLE)
-	return ret;
-}
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
 
-int __down_trylock(struct semaphore * sem)
-{
-	return waking_non_zero_trylock(sem);
+	tsk->state = TASK_INTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	while (__sem_update_count(sem, -1) <= 0) {
+		if (signal_pending(current)) {
+			__sem_update_count(sem, 0);
+			retval = -EINTR;
+			break;
+		}
+		schedule();
+		tsk->state = TASK_INTERRUPTIBLE;
+	}
+	tsk->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+	wake_up(&sem->wait);
+	return retval;
 }
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.4.4/linux/arch/sparc64/kernel/sparc64_ksyms.c	Fri Apr 13 20:15:55 2001
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Sun May 20 11:32:07 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.105 2001/04/14 01:12:02 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.107 2001/05/18 08:01:35 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -47,6 +47,7 @@
 #endif
 #ifdef CONFIG_PCI
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #endif
 #include <asm/a.out.h>
 
@@ -156,7 +157,6 @@
 /* semaphores */
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(__up);
 
 /* Atomic counter implementation. */
@@ -199,6 +199,7 @@
 #endif
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(ebus_chain);
+EXPORT_SYMBOL(isa_chain);
 EXPORT_SYMBOL(pci_memspace_mask);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(outsb);
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.4.4/linux/arch/sparc64/kernel/sys_sunos32.c	Thu Apr 26 22:17:26 2001
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Tue May  1 20:59:24 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.59 2001/03/24 09:36:11 davem Exp $
+/* $Id: sys_sunos32.c,v 1.60 2001/04/27 07:02:42 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.4.4/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.4.4/linux/arch/sparc64/mm/init.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/mm/init.c	Wed May 16 10:20:11 2001
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.175 2001/04/24 01:09:12 davem Exp $
+/*  $Id: init.c,v 1.176 2001/05/16 15:07:11 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -1139,8 +1139,16 @@
 	unsigned long second_alias_page = 0;
 	unsigned long pt, flags, end_pfn, pages_avail;
 	unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
+	unsigned long real_end;
 
 	set_bit(0, mmu_context_bmap);
+
+	real_end = (unsigned long)&_end;
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (sparc_ramdisk_image)
+		real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
+#endif
+
 	/* We assume physical memory starts at some 4mb multiple,
 	 * if this were not true we wouldn't boot up to this point
 	 * anyways.
@@ -1161,7 +1169,7 @@
 		: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
 		  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
 		: "memory");
-		if (((unsigned long)&_end) >= KERNBASE + 0x340000) {
+		if (real_end >= KERNBASE + 0x340000) {
 			second_alias_page = alias_base + 0x400000;
 			__asm__ __volatile__(
 		"	stxa	%1, [%0] %3\n"
@@ -1189,7 +1197,7 @@
 		: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
 		  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3))
 		: "memory");
-		if (((unsigned long)&_end) >= KERNBASE + 0x340000) {
+		if (real_end >= KERNBASE + 0x340000) {
 			second_alias_page = alias_base + 0x400000;
 			__asm__ __volatile__(
 		"	stxa	%1, [%0] %3\n"
diff -u --recursive --new-file v2.4.4/linux/drivers/Makefile linux/drivers/Makefile
--- v2.4.4/linux/drivers/Makefile	Fri Dec 29 14:07:21 2000
+++ linux/drivers/Makefile	Wed May 16 10:27:02 2001
@@ -9,7 +9,7 @@
 mod-subdirs :=	dio mtd sbus video macintosh usb input telephony sgi i2o ide \
 		scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi
 
-subdir-y :=	block char net parport sound misc media cdrom
+subdir-y :=	parport char block net sound misc media cdrom
 subdir-m :=	$(subdir-y)
 
 
diff -u --recursive --new-file v2.4.4/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c
--- v2.4.4/linux/drivers/acorn/block/mfmhd.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/acorn/block/mfmhd.c	Sat Apr 28 11:27:53 2001
@@ -1485,14 +1485,7 @@
 
 	for (i = maxp - 1; i >= 0; i--) {
 		int minor = start + i;
-		kdev_t devi = MKDEV(MAJOR_NR, minor);
-		struct super_block *sb = get_super(devi);
-
-		sync_dev (devi);
-		if (sb)
-			invalidate_inodes (sb);
-		invalidate_buffers (devi);
-
+		invalidate_device (MKDEV(MAJOR_NR, minor), 1);
 		mfm_gendisk.part[minor].start_sect = 0;
 		mfm_gendisk.part[minor].nr_sects = 0;
 	}
diff -u --recursive --new-file v2.4.4/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c
--- v2.4.4/linux/drivers/acpi/driver.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/driver.c	Tue May 22 09:38:51 2001
@@ -311,8 +311,10 @@
 		size = buf.length - file->f_pos;
 		if (size > *len)
 			size = *len;
-		if (copy_to_user(buffer, data, size))
+		if (copy_to_user(buffer, data, size)) {
+			kfree(buf.pointer);
 			return -EFAULT;
+		}
 	}
 
 	kfree(buf.pointer);
diff -u --recursive --new-file v2.4.4/linux/drivers/atm/eni.c linux/drivers/atm/eni.c
--- v2.4.4/linux/drivers/atm/eni.c	Thu Jul  6 21:37:24 2000
+++ linux/drivers/atm/eni.c	Wed May 16 10:22:50 2001
@@ -1796,6 +1796,7 @@
 		return -EAGAIN;
 	}
 	/* @@@ should release IRQ on error */
+	pci_set_master(eni_dev->pci_dev);
 	if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
 	    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
 	    (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
diff -u --recursive --new-file v2.4.4/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.4.4/linux/drivers/block/DAC960.c	Tue Feb 20 21:26:22 2001
+++ linux/drivers/block/DAC960.c	Sat Apr 28 11:27:53 2001
@@ -5134,16 +5134,12 @@
 						      PartitionNumber);
 	  int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
 					       PartitionNumber);
-	  SuperBlock_T *SuperBlock = get_super(Device);
 	  if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
 	    continue;
 	  /*
 	    Flush all changes and invalidate buffered state.
 	  */
-	  sync_dev(Device);
-	  if (SuperBlock != NULL)
-	    invalidate_inodes(SuperBlock);
-	  invalidate_buffers(Device);
+	  invalidate_device(Device, 1);
 	  /*
 	    Clear existing partition sizes.
 	  */
diff -u --recursive --new-file v2.4.4/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.4.4/linux/drivers/block/acsi.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/block/acsi.c	Sat Apr 28 11:27:53 2001
@@ -1886,13 +1886,7 @@
 
 	for( i = max_p - 1; i >= 0 ; i-- ) {
 		if (gdev->part[start + i].nr_sects != 0) {
-			kdev_t devp = MKDEV(MAJOR_NR, start + i);
-			struct super_block *sb = get_super(devp);
-
-			fsync_dev(devp);
-			if (sb)
-				invalidate_inodes(sb);
-			invalidate_buffers(devp);
+			invalidate_device(MKDEV(MAJOR_NR, start + i), 1);
 			gdev->part[start + i].nr_sects = 0;
 		}
 		gdev->part[start+i].start_sect = 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c
--- v2.4.4/linux/drivers/block/acsi_slm.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/block/acsi_slm.c	Tue May 22 10:23:16 2001
@@ -378,19 +378,22 @@
 	
 	length = slm_getstats( (char *)page, MINOR(node->i_rdev) );
 	if (length < 0) {
-		free_page( page );
-		return( length );
+		count = length;
+		goto out;
 	}
 	if (file->f_pos >= length) {
-		free_page( page );
-		return( 0 );
+		count = 0;
+		goto out;
 	}
 	if (count + file->f_pos > length)
 		count = length - file->f_pos;
 	end = count + file->f_pos;
-	copy_to_user( buf, (char *)page + file->f_pos, count );
-	free_page( page );
+	if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
+		count = -EFAULT;
+		goto out;
+	}
 	file->f_pos = end;
+out:	free_page( page );
 	return( count );
 }
 
@@ -648,7 +651,8 @@
 	if (filled + n > BufferSize)
 		n = BufferSize - filled;
 
-	copy_from_user( BufferP, buf, n );
+	if (copy_from_user(BufferP, buf, n))
+		return -EFAULT;
 	BufferP += n;
 	filled += n;
 
@@ -725,8 +729,9 @@
 			if (put_user(stat,
     	    	    	    	     (long *)&((struct SLM_status *)arg)->stat))
     	    	    	    	return -EFAULT;
-			copy_to_user( ((struct SLM_status *)arg)->str, str,
-						 strlen(str) + 1 );
+			if (copy_to_user( ((struct SLM_status *)arg)->str, str,
+						 strlen(str) + 1))
+				return -EFAULT;
 		}
 		return( stat );
 	  }
@@ -734,10 +739,6 @@
 	  case SLMIOGPSIZE: {	/* get paper size */
 		int w, h;
 		
-		err = verify_area( VERIFY_WRITE, (long *)arg,
-						   sizeof(struct SLM_paper_size) );
-		if (err) return( err );
-
 		if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
 		
     	    	if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
diff -u --recursive --new-file v2.4.4/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.4.4/linux/drivers/block/amiflop.c	Sun Oct  1 20:35:15 2000
+++ linux/drivers/block/amiflop.c	Sat Apr 28 11:27:53 2001
@@ -1540,10 +1540,7 @@
 		break;
 	case FDFMTEND:
 		floppy_off(drive);
-		sb = get_super(inode->i_rdev);
-		if (sb)
-			invalidate_inodes(sb);
-		invalidate_buffers(inode->i_rdev);
+		invalidate_device(inode->i_rdev, 0);
 		break;
 	case FDGETPRM:
 		memset((void *)&getprm, 0, sizeof (getprm));
diff -u --recursive --new-file v2.4.4/linux/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- v2.4.4/linux/drivers/block/blkpg.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/block/blkpg.c	Sun May 20 11:34:05 2001
@@ -157,8 +157,7 @@
 
 	/* partition in use? Incomplete check for now. */
 	devp = MKDEV(MAJOR(dev), minor);
-	if (get_super(devp) ||		/* mounted? */
-	    is_swap_partition(devp))
+	if (is_mounted(devp) || is_swap_partition(devp))
 		return -EBUSY;
 
 	/* all seems OK */
diff -u --recursive --new-file v2.4.4/linux/drivers/block/cciss.c linux/drivers/block/cciss.c
--- v2.4.4/linux/drivers/block/cciss.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/block/cciss.c	Tue May 22 10:23:16 2001
@@ -44,8 +44,8 @@
 #include <linux/genhd.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 2.4.2)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,2)
+#define DRIVER_NAME "Compaq CISS Driver (v 2.4.5)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,5)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Charles M. White III - Compaq Computer Corporation");
@@ -55,6 +55,17 @@
 #include "cciss.h"
 #include <linux/cciss_ioctl.h>
 
+/* define the PCI info for the cards we can control */
+const struct pci_device_id cciss_pci_device_id[] = {
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS,
+			0x0E11, 0x4070, 0, 0, 0},
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
+                        0x0E11, 0x4080, 0, 0, 0},
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
+                        0x0E11, 0x4082, 0, 0, 0},
+};
+MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
+
 #define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
 
 /*  board_id = Subsystem Device ID & Vendor ID
@@ -73,7 +84,9 @@
 #define READ_AHEAD 	 128
 #define NR_CMDS		 128 /* #commands that can be outstanding */
 #define MAX_CTLR 8
-static int nr_ctlr; 
+
+#define CCISS_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
+
 static ctlr_info_t *hba[MAX_CTLR];
 
 static struct proc_dir_entry *proc_cciss;
@@ -125,10 +138,10 @@
 
         ctlr = h->ctlr;
         size = sprintf(buffer, "%s:  Compaq %s Controller\n"
-                "       Board ID: %08lx\n"
+                "       Board ID: 0x%08lx\n"
 		"       Firmware Version: %c%c%c%c\n"
-                "       Memory Address: %08lx\n"
-                "       IRQ: 0x%x\n"
+                "       Memory Address: 0x%08lx\n"
+                "       IRQ: %d\n"
                 "       Logical drives: %d\n"
                 "       Current Q depth: %d\n"
 		"       Current # commands on controller %d\n"
@@ -172,7 +185,7 @@
 static void __init cciss_procinit(int i)
 {
         if (proc_cciss == NULL) {
-                proc_cciss = proc_mkdir("driver/cciss", NULL);
+                proc_cciss = proc_mkdir("cciss", proc_root_driver);
                 if (!proc_cciss) 
 			return;
         }
@@ -186,29 +199,32 @@
  * For operations that cannot sleep, a command block is allocated at init, 
  * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
  * which ones are free or in use.  For operations that can wait for kmalloc 
- * to possible sleep, this routine can be called with a NULL pointer. 
- * cmd_free() MUST be called with a NULL pointer if cmd_alloc was. 
+ * to possible sleep, this routine can be called with get_from_pool set to 0. 
+ * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. 
  */ 
-static CommandList_struct * cmd_alloc(ctlr_info_t *h)
+static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
 {
 	CommandList_struct *c;
 	int i; 
 	u64bit temp64;
+	dma_addr_t cmd_dma_handle, err_dma_handle;
 
-	if (h == NULL)
+	if (!get_from_pool)
 	{
-		c = (CommandList_struct *)kmalloc(sizeof(CommandList_struct), 
-			GFP_KERNEL);
+		c = (CommandList_struct *) pci_alloc_consistent(
+			h->pdev, sizeof(CommandList_struct), &cmd_dma_handle); 
         	if(c==NULL)
                  	return NULL;
 		memset(c, 0, sizeof(CommandList_struct));
 
-		c->err_info = (ErrorInfo_struct *)kmalloc(
-					sizeof(ErrorInfo_struct), GFP_KERNEL);
+		c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
+					h->pdev, sizeof(ErrorInfo_struct), 
+					&err_dma_handle);
 	
 		if (c->err_info == NULL)
 		{
-			kfree(c);
+			pci_free_consistent(h->pdev, 
+				sizeof(CommandList_struct), c, cmd_dma_handle);
 			return NULL;
 		}
 		memset(c->err_info, 0, sizeof(ErrorInfo_struct));
@@ -223,18 +239,23 @@
 		printk(KERN_DEBUG "cciss: using command buffer %d\n", i);
 #endif
                 c = h->cmd_pool + i;
-		memset(c, 0, sizeof(CommandList_struct));			
+		memset(c, 0, sizeof(CommandList_struct));
+		cmd_dma_handle = h->cmd_pool_dhandle 
+					+ i*sizeof(CommandList_struct);
 		c->err_info = h->errinfo_pool + i;
 		memset(c->err_info, 0, sizeof(ErrorInfo_struct));
+		err_dma_handle = h->errinfo_pool_dhandle 
+					+ i*sizeof(ErrorInfo_struct);
                 h->nr_allocs++;
         }
 
-
-	temp64.val = (__u64) virt_to_bus(c->err_info);
+	c->busaddr = (__u32) cmd_dma_handle;
+	temp64.val = (__u64) err_dma_handle;	
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
 	c->ErrDesc.Addr.upper = temp64.val32.upper;
 	c->ErrDesc.Len = sizeof(ErrorInfo_struct);
-       	c->busaddr = virt_to_bus(c);
+	
+	c->ctlr = h->ctlr;
         return c;
 
 
@@ -243,14 +264,19 @@
 /* 
  * Frees a command block that was previously allocated with cmd_alloc(). 
  */
-static void cmd_free(ctlr_info_t *h, CommandList_struct *c)
+static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool)
 {
 	int i;
+	u64bit temp64;
 
-	if( h == NULL)
+	if( !got_from_pool)
 	{ 
-		kfree(c->err_info);
-		kfree(c);	
+		temp64.val32.lower = c->ErrDesc.Addr.lower;
+		temp64.val32.upper = c->ErrDesc.Addr.upper;
+		pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), 
+			c->err_info, (dma_addr_t) temp64.val);
+		pci_free_consistent(h->pdev, sizeof(CommandList_struct), 
+			c, (dma_addr_t) c->busaddr);
 	} else 
 	{
 		i = c - h->cmd_pool;
@@ -390,8 +416,8 @@
 		cciss_pci_info_struct pciinfo;
 
 		if (!arg) return -EINVAL;
-		pciinfo.bus = hba[ctlr]->pci_bus;
-		pciinfo.dev_fn = hba[ctlr]->pci_dev_fn;
+		pciinfo.bus = hba[ctlr]->pdev->bus->number;
+		pciinfo.dev_fn = hba[ctlr]->pdev->devfn;
 		pciinfo.board_id = hba[ctlr]->board_id;
 		if (copy_to_user((void *) arg, &pciinfo,  sizeof( cciss_pci_info_struct )))
 			return  -EFAULT;
@@ -583,13 +609,10 @@
 		if (iocommand.Request.Type.Direction == XFER_WRITE)
 		{
 			/* Copy the data into the buffer we created */ 
-			if (copy_from_user(buff, iocommand.buf,
-						iocommand.buf_size)) {
-				kfree(buff);
+			if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
 				return -EFAULT;
-			}
 		}
-		if ((c = cmd_alloc(NULL)) == NULL)
+		if ((c = cmd_alloc(h , 0)) == NULL)
 		{
 			kfree(buff);
 			return -ENOMEM;
@@ -615,8 +638,10 @@
 	
 		// Fill in the scatter gather information
 		if (iocommand.buf_size > 0 ) 
-		{	
-			temp64.val = (__u64) virt_to_bus(buff);
+		{
+			temp64.val = pci_map_single( h->pdev, buff,
+                                        iocommand.buf_size, 
+                                PCI_DMA_BIDIRECTIONAL);	
 			c->SG[0].Addr.lower = temp64.val32.lower;
 			c->SG[0].Addr.upper = temp64.val32.upper;
 			c->SG[0].Len = iocommand.buf_size;
@@ -633,12 +658,18 @@
 		while(c->cmd_type != CMD_IOCTL_DONE)
 			schedule_timeout(1);
 
+		/* unlock the buffers from DMA */
+		temp64.val32.lower = c->SG[0].Addr.lower;
+                temp64.val32.upper = c->SG[0].Addr.upper;
+                pci_unmap_single( h->pdev, (dma_addr_t) temp64.val,
+                	iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+
 		/* Copy the error information out */ 
 		iocommand.error_info = *(c->err_info);
 		if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )
 		{
-			cmd_free(NULL, c);
 			kfree(buff);
+			cmd_free(h, c, 0);
 			return( -EFAULT);	
 		} 	
 
@@ -647,13 +678,12 @@
                         /* Copy the data out of the buffer we created */
                         if (copy_to_user(iocommand.buf, buff, iocommand.buf_size))
 			{
-			             cmd_free(NULL, c);
-			             kfree(buff);
-				     return -EFAULT;	
+                        	kfree(buff);
+				cmd_free(h, c, 0);
 			}
                 }
-		cmd_free(NULL, c);
                 kfree(buff);
+		cmd_free(h, c, 0);
                 return(0);
 	} 
 
@@ -691,13 +721,9 @@
         max_p = gdev->max_p;
         start = target << gdev->minor_shift;
 
-        for(i=max_p; i>=0; i--) {
+        for(i=max_p-1; i>=0; i--) {
                 int minor = start+i;
-                kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);
-                struct super_block *sb = get_super(devi);
-                sync_dev(devi);
-                if (sb) invalidate_inodes(sb);
-                invalidate_buffers(devi);
+                invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);
                 gdev->part[minor].start_sect = 0;
                 gdev->part[minor].nr_sects = 0;
 
@@ -820,9 +846,9 @@
 	int i;
 	unsigned long complete;
 	ctlr_info_t *info_p= hba[ctlr];
-	u64bit temp64;
+	u64bit buff_dma_handle;
 
-	c = cmd_alloc(info_p);
+	c = cmd_alloc(info_p, 1);
 	if (c == NULL)
 	{
 		printk(KERN_WARNING "cciss: unable to get memory");
@@ -903,15 +929,16 @@
 			printk(KERN_WARNING
 				"cciss:  Unknown Command 0x%c sent attempted\n",
 				  cmd);
-			cmd_free(info_p, c);
+			cmd_free(info_p, c, 1);
 			return(IO_ERROR);
 	};
 	// Fill in the scatter gather information
 	if (size > 0 ) 
 	{
-		temp64.val = (__u64) virt_to_bus(buff);
-		c->SG[0].Addr.lower = temp64.val32.lower;
-		c->SG[0].Addr.upper = temp64.val32.upper;
+		buff_dma_handle.val = (__u64) pci_map_single( info_p->pdev, 
+			buff, size, PCI_DMA_BIDIRECTIONAL);
+		c->SG[0].Addr.lower = buff_dma_handle.val32.lower;
+		c->SG[0].Addr.upper = buff_dma_handle.val32.upper;
 		c->SG[0].Len = size;
 		c->SG[0].Ext = 0;  // we are not chaining
 	}
@@ -947,6 +974,9 @@
 	printk(KERN_DEBUG "cciss: command completed\n");
 #endif /* CCISS_DEBUG */
 
+	/* unlock the data buffer from DMA */
+	pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
+                                size, PCI_DMA_BIDIRECTIONAL);
 	if (complete != 1) {
 		if ( (complete & CISS_ERROR_BIT)
 		     && (complete & ~CISS_ERROR_BIT) == c->busaddr)
@@ -974,7 +1004,7 @@
 				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_size,
 				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_num,
 				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
-				cmd_free(info_p,c);
+				cmd_free(info_p,c, 1);
 				return(IO_ERROR);
 			}
 		}
@@ -982,7 +1012,7 @@
                         printk( KERN_WARNING "cciss cciss%d: SendCmd "
                       "Invalid command list address returned! (%lx)\n",
                                 ctlr, complete);
-                        cmd_free(info_p, c);
+                        cmd_free(info_p, c, 1);
                         return (IO_ERROR);
                 }
         } else {
@@ -990,10 +1020,10 @@
                         "cciss cciss%d: SendCmd Timeout out, "
                         "No command list address returned!\n",
                         ctlr);
-                cmd_free(info_p, c);
+                cmd_free(info_p, c, 1);
                 return (IO_ERROR);
         }
-	cmd_free(info_p, c);
+	cmd_free(info_p, c, 1);
         return (IO_OK);
 } 
 /*
@@ -1084,9 +1114,22 @@
 static inline void complete_command( CommandList_struct *cmd, int timeout)
 {
 	int status = 1;
-	
+	int i;
+	u64bit temp64;
+		
 	if (timeout)
 		status = 0; 
+	/* unmap the DMA mapping for all the scatter gather elements */
+	for(i=0; i<cmd->Header.SGList; i++)
+	{
+		temp64.val32.lower = cmd->SG[i].Addr.lower;
+		temp64.val32.upper = cmd->SG[i].Addr.upper;
+		pci_unmap_single(hba[cmd->ctlr]->pdev,
+			temp64.val, cmd->SG[i].Len, 
+			(cmd->Request.Type.Direction == XFER_READ) ? 
+				PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+	}
+
 	if(cmd->err_info->CommandStatus != 0) 
 	{ /* an error has occurred */ 
 		switch(cmd->err_info->CommandStatus)
@@ -1221,7 +1264,12 @@
 	struct list_head *queue_head = &q->queue_head;
 	struct request *creq;
 	u64bit temp64;
+	struct my_sg tmp_sg[MAXSGENTRIES];
+	int i;
 
+    // Loop till the queue is empty if or it is plugged
+    while (1)
+    {
 	if (q->plugged || list_empty(queue_head)) {
                 start_io(h);
                 return;
@@ -1231,7 +1279,7 @@
 	if (creq->nr_segments > MAXSGENTRIES)
                 BUG();
 
-        if ((h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR) || (h->ctlr > nr_ctlr))
+        if (h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR )
         {
                 printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
                                 h->ctlr, creq->rq_dev, creq);
@@ -1241,7 +1289,7 @@
                 return;
         }
 
-	if (( c = cmd_alloc(h)) == NULL)
+	if (( c = cmd_alloc(h, 1)) == NULL)
 	{
 		start_io(h);
 		return;
@@ -1277,22 +1325,32 @@
 		sect += bh->b_size/512;
 		if (bh->b_data == lastdataend)
 		{  // tack it on to the last segment 
-			c->SG[seg-1].Len +=bh->b_size;
+			tmp_sg[seg-1].len +=bh->b_size;
 			lastdataend += bh->b_size;
 		} else
 		{
 			if (seg == MAXSGENTRIES)
 				BUG();
-			c->SG[seg].Len = bh->b_size;
-			temp64.val = (__u64) virt_to_bus(bh->b_data);
-			c->SG[seg].Addr.lower = temp64.val32.lower;
-			c->SG[seg].Addr.upper = temp64.val32.upper;
-			c->SG[0].Ext = 0;  // we are not chaining
+			tmp_sg[seg].len = bh->b_size;
+			tmp_sg[seg].start_addr = bh->b_data;
 			lastdataend = bh->b_data + bh->b_size;
 			seg++;
 		}
 		bh = bh->b_reqnext;
 	}
+	/* get the DMA records for the setup */ 
+	for (i=0; i<seg; i++)
+	{
+		c->SG[i].Len = tmp_sg[i].len;
+		temp64.val = (__u64) pci_map_single( h->pdev,
+			tmp_sg[i].start_addr,
+			tmp_sg[i].len,
+			(c->Request.Type.Direction == XFER_READ) ? 
+                                PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+		c->SG[i].Addr.lower = temp64.val32.lower;
+                c->SG[i].Addr.upper = temp64.val32.upper;
+                c->SG[i].Ext = 0;  // we are not chaining
+	}
 	/* track how many SG entries we are using */ 
 	if( seg > h->maxSG)
 		h->maxSG = seg; 
@@ -1329,7 +1387,7 @@
 	h->Qdepth++;
 	if(h->Qdepth > h->maxQsinceinit)
 		h->maxQsinceinit = h->Qdepth; 
-	start_io(h);
+   }  // while loop
 }
 
 static void do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -1373,7 +1431,7 @@
 				removeQ(&h->cmpQ, c);
 				if (c->cmd_type == CMD_RWREQ) {
 					complete_command(c, 0);
-					cmd_free(h, c);
+					cmd_free(h, c, 1);
 				} else if (c->cmd_type == CMD_IOCTL_PEND) {
 					c->cmd_type = CMD_IOCTL_DONE;
 				}
@@ -1427,20 +1485,18 @@
 }
 #endif /* CCISS_DEBUG */ 
 
-static int cciss_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
+static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 {
 	ushort vendor_id, device_id, command;
 	unchar cache_line_size, latency_timer;
 	unchar irq, revision;
 	uint addr[6];
 	__u32 board_id;
-	struct pci_dev *pdev;
 	int cfg_offset;
 	int cfg_base_addr;
 	int cfg_base_addr_index;
 	int i;
 
-	pdev = pci_find_slot(bus, device_fn);
 	vendor_id = pdev->vendor;
 	device_id = pdev->device;
 	irq = pdev->irq;
@@ -1449,7 +1505,15 @@
 		addr[i] = pdev->resource[i].start;
 
 	if (pci_enable_device(pdev))
+	{
+		printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
 		return( -1);
+	}
+	if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0)
+	{
+		printk(KERN_ERR "cciss:  Unable to set DMA mask\n");
+		return(-1);
+	}
 	
 	(void) pci_read_config_word(pdev, PCI_COMMAND,&command);
 	(void) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
@@ -1566,59 +1630,6 @@
 	return 0;
 
 }
-/* 
- * Scans PCI space for any controllers that this driver can control. 
- */
-static int cciss_pci_detect(void)
-{
-
-	int index;
-	unchar bus=0, dev_fn=0;
-
-	#define CCISS_BOARD_TYPES 2
-	static int cciss_device_id[CCISS_BOARD_TYPES] = { 
-		PCI_DEVICE_ID_COMPAQ_CISS, PCI_DEVICE_ID_COMPAQ_CISSB};
-	int brdtype;
-
-	/* search for all PCI board types that could be for this driver */
-	for(brdtype=0; brdtype<CCISS_BOARD_TYPES; brdtype++)
-	{
-		for(index=0; ; index++) {
-			if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
-			 	cciss_device_id[brdtype], 
-					index, &bus, &dev_fn))
-				break;
-			printk(KERN_DEBUG "cciss: Device %x has been found at %x %x\n",
-				cciss_device_id[brdtype], bus, dev_fn);
-			if (index == 1000000) break;
-			if (nr_ctlr == 8) {
-				printk(KERN_WARNING "cciss: This driver"
-				" supports a maximum of 8 controllers.\n");
-				break;
-			}
-			hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
-			if(hba[nr_ctlr]==NULL)
-			{
-				printk(KERN_ERR "cciss: out of memory.\n");
-				continue;
-			}
-			memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
-			if (cciss_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
-			{
-				kfree(hba[nr_ctlr]);
-				continue;
-			}
-			sprintf(hba[nr_ctlr]->devname, "cciss%d", nr_ctlr);
-			hba[nr_ctlr]->ctlr = nr_ctlr;
-			hba[nr_ctlr]->pci_bus = bus;
-			hba[nr_ctlr]->pci_dev_fn = dev_fn;
-			nr_ctlr++;
-
-		}
-	}
-	return nr_ctlr;
-
-}
 
 /* 
  * Gets information about the local volumes attached to the controller. 
@@ -1797,166 +1808,265 @@
 	kfree(size_buff);
 }	
 
+/* Function to find the first free pointer into our hba[] array */
+/* Returns -1 if no free entries are left.  */
+static int alloc_cciss_hba(void)
+{
+	int i;
+	for(i=0; i< MAX_CTLR; i++)
+	{
+		if (hba[i] == NULL)
+		{
+			hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+			if(hba[i]==NULL)
+			{
+				printk(KERN_ERR "cciss: out of memory.\n");
+				return (-1);
+			}
+			return (i);
+		}
+	}
+	printk(KERN_WARNING "cciss: This driver supports a maximum"
+		" of 8 controllers.\n");
+	return(-1);
+}
+
+static void free_hba(int i)
+{
+	kfree(hba[i]);
+	hba[i]=NULL;
+}
+
 /*
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
  *  returns the number of block devices registered.
  */
-int __init cciss_init(void)
+static int __init cciss_init_one(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
 {
-	int num_cntlrs_reg = 0;
-	int i,j;
 	request_queue_t *q;
+	int i;
+	int j;
 
-	/* detect controllers */
-	cciss_pci_detect();
-
-	if (nr_ctlr == 0)
-		return(num_cntlrs_reg);
-
-	printk(KERN_INFO DRIVER_NAME "\n");
-	printk(KERN_INFO "Found %d controller(s)\n", nr_ctlr);
-	for(i=0;i<nr_ctlr;i++)
+	printk(KERN_DEBUG "cciss: Device 0x%x has been found at"
+			" bus %d dev %d func %d\n",
+		pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
+			PCI_FUNC(pdev->devfn));
+	i = alloc_cciss_hba();
+	if( i < 0 ) 
+		return (-1);
+	memset(hba[i], 0, sizeof(ctlr_info_t));
+	if (cciss_pci_init(hba[i], pdev) != 0)
+	{
+		free_hba(i);
+		return (-1);
+	}
+	sprintf(hba[i]->devname, "cciss%d", i);
+	hba[i]->ctlr = i;
+	hba[i]->pdev = pdev;
+			
+	if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops))
 	{
-		if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops))
-		{
-			printk(KERN_ERR "cciss:  Unable to get major number "
-				"%d for %s\n", MAJOR_NR+i, hba[i]->devname);
-			continue;
-		}
-		/* make sure the board interrupts are off */
-		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
-		if( request_irq(hba[i]->intr, do_cciss_intr, SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
-		{
-			printk(KERN_ERR "ciss: Unable to get irq %d for %s\n",
-				hba[i]->intr, hba[i]->devname);
-			unregister_blkdev( MAJOR_NR+i, hba[i]->devname);
-			continue;
-		}
-		num_cntlrs_reg++;
-		hba[i]->cmd_pool_bits = (__u32*)kmalloc(
-                                ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
-		hba[i]->cmd_pool = (CommandList_struct *)kmalloc(
-                                NR_CMDS * sizeof(CommandList_struct), 
-					GFP_KERNEL);
-		hba[i]->errinfo_pool = (ErrorInfo_struct *)kmalloc(
-                                NR_CMDS * sizeof( ErrorInfo_struct), 
-					GFP_KERNEL);
-		if((hba[i]->cmd_pool_bits == NULL) 
-			|| (hba[i]->cmd_pool == NULL)
-			|| (hba[i]->errinfo_pool == NULL))
-                {
-                        nr_ctlr = i;
-			kfree(hba[i]->cmd_pool_bits);
-			kfree(hba[i]->cmd_pool);
-			kfree(hba[i]->errinfo_pool);
-                        free_irq(hba[i]->intr, hba[i]);
-                        unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
-                        num_cntlrs_reg--;
-                        printk( KERN_ERR "cciss: out of memory");
-			return(num_cntlrs_reg);
-		}
-
-		/* command and error info recs zeroed out before 
+		printk(KERN_ERR "cciss:  Unable to get major number "
+			"%d for %s\n", MAJOR_NR+i, hba[i]->devname);
+		free_hba(i);
+		return(-1);
+	}
+	/* make sure the board interrupts are off */
+	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
+	if( request_irq(hba[i]->intr, do_cciss_intr, 
+		SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
+	{
+		printk(KERN_ERR "ciss: Unable to get irq %d for %s\n",
+			hba[i]->intr, hba[i]->devname);
+		unregister_blkdev( MAJOR_NR+i, hba[i]->devname);
+		free_hba(i);
+		return(-1);
+	}
+	hba[i]->cmd_pool_bits = (__u32*)kmalloc(
+        	((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
+	hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent(
+		hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), 
+		&(hba[i]->cmd_pool_dhandle));
+	hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent(
+		hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), 
+		&(hba[i]->errinfo_pool_dhandle));
+	if((hba[i]->cmd_pool_bits == NULL) 
+		|| (hba[i]->cmd_pool == NULL)
+		|| (hba[i]->errinfo_pool == NULL))
+        {
+		if(hba[i]->cmd_pool_bits)
+                	kfree(hba[i]->cmd_pool_bits);
+                if(hba[i]->cmd_pool)
+                	pci_free_consistent(hba[i]->pdev,  
+				NR_CMDS * sizeof(CommandList_struct), 
+				hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);	
+		if(hba[i]->errinfo_pool)
+			pci_free_consistent(hba[i]->pdev,
+				NR_CMDS * sizeof( ErrorInfo_struct),
+				hba[i]->errinfo_pool, 
+				hba[i]->errinfo_pool_dhandle);
+                free_irq(hba[i]->intr, hba[i]);
+                unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+		free_hba(i);
+                printk( KERN_ERR "cciss: out of memory");
+		return(-1);
+	}
+
+	/* Initialize the pdev driver private data. 
+		have it point to hba[i].  */
+	pdev->driver_data = hba[i];
+	/* command and error info recs zeroed out before 
 			they are used */
-                memset(hba[i]->cmd_pool_bits, 0, 
-			((NR_CMDS+31)/32)*sizeof(__u32));
+        memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));
 
 #ifdef CCISS_DEBUG	
-		printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);
+	printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);
 #endif /* CCISS_DEBUG */
 
-		cciss_getgeometry(i);
+	cciss_getgeometry(i);
 
-		/* Turn the interrupts on so we can service requests */
-		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
+	/* Turn the interrupts on so we can service requests */
+	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
-		cciss_procinit(i);
+	cciss_procinit(i);
 
-		q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
-                q->queuedata = hba[i];
-                blk_init_queue(q, do_cciss_request);
-                blk_queue_headactive(q, 0);		
-
-		/* fill in the other Kernel structs */
-		blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
-                hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
-                read_ahead[MAJOR_NR+i] = READ_AHEAD;
-
-		/* Set the pointers to queue functions */ 
-		q->back_merge_fn = cpq_back_merge_fn;
-                q->front_merge_fn = cpq_front_merge_fn;
-                q->merge_requests_fn = cpq_merge_requests_fn;
-
-
-		/* Fill in the gendisk data */ 	
-		hba[i]->gendisk.major = MAJOR_NR + i;
-		hba[i]->gendisk.major_name = "cciss";
-		hba[i]->gendisk.minor_shift = NWD_SHIFT;
-		hba[i]->gendisk.max_p = MAX_PART;
-		hba[i]->gendisk.part = hba[i]->hd;
-		hba[i]->gendisk.sizes = hba[i]->sizes;
-		hba[i]->gendisk.nr_real = hba[i]->num_luns;
-
-		/* Get on the disk list */ 
-		hba[i]->gendisk.next = gendisk_head;
-		gendisk_head = &(hba[i]->gendisk); 
-
-		cciss_geninit(i);
-		for(j=0; j<NWD; j++)
-			register_disk(&(hba[i]->gendisk),
-				MKDEV(MAJOR_NR+i, j <<4), 
-				MAX_PART, &cciss_fops, 
-				hba[i]->drv[j].nr_blocks);
-	}
-	return(nr_ctlr);
-}
+	q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+        q->queuedata = hba[i];
+        blk_init_queue(q, do_cciss_request);
+        blk_queue_headactive(q, 0);		
 
-EXPORT_NO_SYMBOLS;
+	/* fill in the other Kernel structs */
+	blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
+        hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
+        read_ahead[MAJOR_NR+i] = READ_AHEAD;
 
-/* This is a bit of a hack... */
-static int __init init_cciss_module(void)
-{
+	/* Set the pointers to queue functions */ 
+	q->back_merge_fn = cpq_back_merge_fn;
+        q->front_merge_fn = cpq_front_merge_fn;
+        q->merge_requests_fn = cpq_merge_requests_fn;
 
-	if (cciss_init() == 0) /* all the block dev numbers already used */
-		return -EIO;	  /* or no controllers were found */
-	return 0;
+
+	/* Fill in the gendisk data */ 	
+	hba[i]->gendisk.major = MAJOR_NR + i;
+	hba[i]->gendisk.major_name = "cciss";
+	hba[i]->gendisk.minor_shift = NWD_SHIFT;
+	hba[i]->gendisk.max_p = MAX_PART;
+	hba[i]->gendisk.part = hba[i]->hd;
+	hba[i]->gendisk.sizes = hba[i]->sizes;
+	hba[i]->gendisk.nr_real = hba[i]->num_luns;
+
+	/* Get on the disk list */ 
+	hba[i]->gendisk.next = gendisk_head;
+	gendisk_head = &(hba[i]->gendisk); 
+
+	cciss_geninit(i);
+	for(j=0; j<NWD; j++)
+		register_disk(&(hba[i]->gendisk),
+			MKDEV(MAJOR_NR+i, j <<4), 
+			MAX_PART, &cciss_fops, 
+			hba[i]->drv[j].nr_blocks);
+
+	return(1);
 }
 
-static void __exit cleanup_cciss_module(void)
+static void __devexit cciss_remove_one (struct pci_dev *pdev)
 {
+	ctlr_info_t *tmp_ptr;
 	int i;
 	struct gendisk *g;
 
-	for(i=0; i<nr_ctlr; i++)
+	if (pdev->driver_data == NULL)
+	{
+		printk( KERN_ERR "cciss: Unable to remove device \n");
+		return;
+	}
+	tmp_ptr = (ctlr_info_t *) pdev->driver_data;
+	i = tmp_ptr->ctlr;
+	if (hba[i] == NULL) 
 	{
-		/* Turn board interrupts off */ 
-		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
-		free_irq(hba[i]->intr, hba[i]);
-		iounmap((void*)hba[i]->vaddr);
-		unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
-		remove_proc_entry(hba[i]->devname, proc_cciss);	
+		printk(KERN_ERR "cciss: device appears to "
+			"already be removed \n");
+		return;
+	}
+	/* Turn board interrupts off */
+	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
+	free_irq(hba[i]->intr, hba[i]);
+	pdev->driver_data = NULL;
+	iounmap((void*)hba[i]->vaddr);
+	unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+	remove_proc_entry(hba[i]->devname, proc_cciss);	
+	
 
-		/* remove it from the disk list */ 
-		if (gendisk_head == &(hba[i]->gendisk))
-		{
-			gendisk_head = hba[i]->gendisk.next;
-		} else 
+	/* remove it from the disk list */
+	if (gendisk_head == &(hba[i]->gendisk))
+	{
+		gendisk_head = hba[i]->gendisk.next;
+	} else
+	{
+		for(g=gendisk_head; g ; g=g->next)
 		{
-			for(g=gendisk_head; g ; g=g->next)
+			if(g->next == &(hba[i]->gendisk))
 			{
-				if(g->next == &(hba[i]->gendisk))
-				{
-					g->next = hba[i]->gendisk.next;
-				}
+				g->next = hba[i]->gendisk.next;
 			}
 		}
-		remove_proc_entry("driver/cciss", &proc_root);
-		kfree(hba[i]->cmd_pool);
-		kfree(hba[i]->errinfo_pool);
-                kfree(hba[i]->cmd_pool_bits);
-		kfree(hba[i]);
 	}
+	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), 
+		hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
+	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
+		hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
+	kfree(hba[i]->cmd_pool_bits);
+	free_hba(i);
+}	
+
+static struct pci_driver cciss_pci_driver = {
+	 name:   "cciss",
+	probe:  cciss_init_one,
+	remove:  cciss_remove_one,
+	id_table:  cciss_pci_device_id, /* id_table */
+};
+
+/*
+*  This is it.  Register the PCI driver information for the cards we control
+*  the OS will call our registered routines when it finds one of our cards. 
+*/
+int __init cciss_init(void)
+{
+
+	printk(KERN_INFO DRIVER_NAME "\n");
+	/* Register for out PCI devices */
+	if (pci_register_driver(&cciss_pci_driver) > 0 )
+		return 0;
+	else 
+		return -ENODEV;
+
+ }
+
+EXPORT_NO_SYMBOLS;
+static int __init init_cciss_module(void)
+{
+
+	return ( cciss_init());
+}
+
+static void __exit cleanup_cciss_module(void)
+{
+	int i;
+
+	pci_unregister_driver(&cciss_pci_driver);
+	/* double check that all controller entrys have been removed */
+	for (i=0; i< MAX_CTLR; i++) 
+	{
+		if (hba[i] != NULL)
+		{
+			printk(KERN_WARNING "cciss: had to remove"
+					" controller %d\n", i);
+			cciss_remove_one(hba[i]->pdev);
+		}
+	}
+	remove_proc_entry("cciss", proc_root_driver);
 }
 
 module_init(init_cciss_module);
diff -u --recursive --new-file v2.4.4/linux/drivers/block/cciss.h linux/drivers/block/cciss.h
--- v2.4.4/linux/drivers/block/cciss.h	Fri Apr 13 20:26:07 2001
+++ linux/drivers/block/cciss.h	Tue May 22 10:23:16 2001
@@ -15,6 +15,11 @@
 
 #define MAJOR_NR COMPAQ_CISS_MAJOR 
 
+struct my_sg {
+	int len;
+	char *start_addr;
+};
+
 struct ctlr_info;
 typedef struct ctlr_info ctlr_info_t;
 
@@ -42,8 +47,7 @@
 	char	devname[8];
 	char    *product_name;
 	char	firm_ver[4]; // Firmware version 
-	unchar  pci_bus;
-        unchar  pci_dev_fn;
+	struct pci_dev *pdev;
 	__u32	board_id;
 	ulong   vaddr;
 	__u32	paddr;	
@@ -70,7 +74,9 @@
 
 	//* pointers to command and error info pool */ 
 	CommandList_struct 	*cmd_pool;
+	dma_addr_t		cmd_pool_dhandle; 
 	ErrorInfo_struct 	*errinfo_pool;
+	dma_addr_t		errinfo_pool_dhandle; 
         __u32   		*cmd_pool_bits;
 	int			nr_allocs;
 	int			nr_frees; 
diff -u --recursive --new-file v2.4.4/linux/drivers/block/cciss_cmd.h linux/drivers/block/cciss_cmd.h
--- v2.4.4/linux/drivers/block/cciss_cmd.h	Fri Apr 13 20:26:07 2001
+++ linux/drivers/block/cciss_cmd.h	Tue May 22 10:23:16 2001
@@ -125,20 +125,20 @@
 //Command List Structure
 typedef union _SCSI3Addr_struct {
    struct {
+    BYTE Dev;
     BYTE Bus:6;
     BYTE Mode:2;        // b00
-    BYTE Dev;
   } PeripDev;
    struct {
+    BYTE DevLSB;
     BYTE DevMSB:6;
     BYTE Mode:2;        // b01
-    BYTE DevLSB;
   } LogDev;
    struct {
-    BYTE Targ:6;
-    BYTE Mode:2;        // b10
     BYTE Dev:5;
     BYTE Bus:3;
+    BYTE Targ:6;
+    BYTE Mode:2;        // b10
   } LogUnit;
 } SCSI3Addr_struct;
 
@@ -224,6 +224,7 @@
 	/* information associated with the command */ 
   __u32			   busaddr; /* physical address of this record */
   ErrorInfo_struct * 	   err_info; /* pointer to the allocated mem */ 
+  int			   ctlr;
   int			   cmd_type; 
   struct _CommandList_struct *prev;
   struct _CommandList_struct *next;
diff -u --recursive --new-file v2.4.4/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.4.4/linux/drivers/block/cpqarray.c	Tue Feb 13 14:13:43 2001
+++ linux/drivers/block/cpqarray.c	Tue May 22 10:23:16 2001
@@ -44,8 +44,8 @@
 
 #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 
-#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.2)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,2)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.4)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,4)
 
 /* Embedded module documentation macros - see modules.h */
 /* Original author Chris Frantz - Compaq Computer Corporation */
@@ -68,6 +68,8 @@
 #define MAX_CTLR	8
 #define CTLR_SHIFT	8
 
+#define CPQARRAY_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
+
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
 
@@ -123,8 +125,8 @@
 static void getgeometry(int ctlr);
 static void start_fwbk(int ctlr);
 
-static cmdlist_t * cmd_alloc(ctlr_info_t *h);
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool);
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool);
 
 static int sendcmd(
 	__u8	cmd,
@@ -204,7 +206,7 @@
 static void __init ida_procinit(int i)
 {
 	if (proc_array == NULL) {
-		proc_array = proc_mkdir("driver/array", NULL);
+		proc_array = proc_mkdir("array", proc_root_driver);
 		if (!proc_array) return;
 	}
 
@@ -228,12 +230,12 @@
 
 	ctlr = h->ctlr;
 	size = sprintf(buffer, "%s:  Compaq %s Controller\n"
-		"       Board ID: %08lx\n"
+		"       Board ID: 0x%08lx\n"
 		"       Firmware Revision: %c%c%c%c\n"
-		"       Controller Sig: %08lx\n"
-		"       Memory Address: %08lx\n"
-		"       I/O Port: %04x\n"
-		"       IRQ: %x\n"
+		"       Controller Sig: 0x%08lx\n"
+		"       Memory Address: 0x%08lx\n"
+		"       I/O Port: 0x%04x\n"
+		"       IRQ: %d\n"
 		"       Logical drives: %d\n"
 		"       Physical drives: %d\n\n"
 		"       Current Q depth: %d\n"
@@ -314,7 +316,7 @@
 	int i;
 	struct gendisk *g;
 
-	remove_proc_entry("driver/array", NULL);
+	remove_proc_entry("array", proc_root_driver);
 
 	for(i=0; i<nr_ctlr; i++) {
 		hba[i]->access.set_intr_mask(hba[i], 0);
@@ -324,7 +326,9 @@
 		del_timer(&hba[i]->timer);
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
 		remove_proc_entry(hba[i]->devname, proc_array);
-		kfree(hba[i]->cmd_pool);
+		pci_free_consistent(hba[i]->pci_dev, 
+			NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool), 
+			hba[i]->cmd_pool_dhandle);
 		kfree(hba[i]->cmd_pool_bits);
 
 		if (gendisk_head == &ida_gendisk[i]) {
@@ -474,8 +478,9 @@
 			continue;
 		}
 		num_cntlrs_reg++;
-		hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
-				NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
+		hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
+				hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t), 
+				&(hba[i]->cmd_pool_dhandle));
 		hba[i]->cmd_pool_bits = (__u32*)kmalloc(
 				((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
 		
@@ -485,7 +490,10 @@
 			if(hba[i]->cmd_pool_bits)
 				kfree(hba[i]->cmd_pool_bits);
 			if(hba[i]->cmd_pool)
-				kfree(hba[i]->cmd_pool);
+				pci_free_consistent(hba[i]->pci_dev, 
+					NR_CMDS * sizeof(cmdlist_t), 
+					hba[i]->cmd_pool, 
+					hba[i]->cmd_pool_dhandle);
 			free_irq(hba[i]->intr, hba[i]);
 			unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
 			num_cntlrs_reg--;
@@ -580,9 +588,11 @@
 		pdev = pci_find_device(ida_vendor_id[brdtype],
 				       ida_device_id[brdtype], NULL);
 		while (pdev) {
-			printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",
+			printk(KERN_DEBUG "cpqarray: Device 0x%x has"
+				" been found at bus %d dev %d func %d\n",
 				ida_vendor_id[brdtype],
-				pdev->bus->number, pdev->devfn);
+				pdev->bus->number, PCI_SLOT(pdev->devfn),
+				PCI_FUNC(pdev->devfn));
 			if (nr_ctlr == 8) {
 				printk(KERN_WARNING "cpqarray: This driver"
 				" supports a maximum of 8 controllers.\n");
@@ -647,7 +657,15 @@
 		addr[i] = pci_resource_start(pdev, i);
 
 	if (pci_enable_device(pdev))
+	{
+		printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n");
+		return -1;
+	}
+	if (pci_set_dma_mask(pdev, CPQARRAY_DMA_MASK) != 0)
+	{
+		printk(KERN_ERR "cpqarray: Unable to set DMA mask\n");
 		return -1;
+	}
 
 	pci_read_config_word(pdev, PCI_COMMAND, &command);
 	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
@@ -905,7 +923,12 @@
 	struct list_head * queue_head = &q->queue_head;
 	struct buffer_head *bh;
 	struct request *creq;
+	struct my_sg tmp_sg[SG_MAX];
+	int i;
 
+// Loop till the queue is empty if or it is plugged 
+   while (1)
+{
 	if (q->plugged || list_empty(queue_head)) {
 		start_io(h);
 		return;
@@ -925,7 +948,7 @@
                 return;
 	}
 
-	if ((c = cmd_alloc(h)) == NULL)
+	if ((c = cmd_alloc(h,1)) == NULL)
 	{
                 start_io(h);
                 return;
@@ -951,18 +974,28 @@
 	while(bh) {
 		sect += bh->b_size/512;
 		if (bh->b_data == lastdataend) {
-			c->req.sg[seg-1].size += bh->b_size;
+			tmp_sg[seg-1].size += bh->b_size;
 			lastdataend += bh->b_size;
 		} else {
 			if (seg == SG_MAX)
 				BUG();
-			c->req.sg[seg].size = bh->b_size;
-			c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
+			tmp_sg[seg].size = bh->b_size;
+			tmp_sg[seg].start_addr = bh->b_data;
 			lastdataend = bh->b_data + bh->b_size;
 			seg++;
 		}
 		bh = bh->b_reqnext;
 	}
+	/* Now do all the DMA Mappings */
+	for( i=0; i < seg; i++)
+	{
+		c->req.sg[i].size = tmp_sg[i].size;
+		c->req.sg[i].addr = (__u32) pci_map_single(
+                		h->pci_dev, tmp_sg[i].start_addr, 
+				tmp_sg[i].size,
+                                (creq->cmd == READ) ? 
+					PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+	}
 DBGPX(	printk("Submitting %d sectors in %d segments\n", sect, seg); );
 	c->req.hdr.sg_cnt = seg;
 	c->req.hdr.blk_cnt = sect;
@@ -993,8 +1026,7 @@
 	h->Qdepth++;
 	if (h->Qdepth > h->maxQsinceinit) 
 		h->maxQsinceinit = h->Qdepth;
-
-	start_io(h);
+   } // while loop
 }
 
 /* 
@@ -1043,6 +1075,7 @@
 static inline void complete_command(cmdlist_t *cmd, int timeout)
 {
 	int ok=1;
+	int i;
 
 	if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
 	   (hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
@@ -1063,6 +1096,13 @@
 		ok = 0;	
 	}
 	if (timeout) ok = 0;
+	/* unmap the DMA mapping for all the scatter gather elements */
+        for(i=0; i<cmd->req.hdr.sg_cnt; i++)
+        {
+                pci_unmap_single(hba[cmd->ctlr]->pci_dev,
+                        cmd->req.sg[i].addr, cmd->req.sg[i].size,
+                        (cmd->req.hdr.cmd == IDA_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+        }
 	complete_buffers(cmd->bh, ok);
 }
 
@@ -1110,7 +1150,7 @@
 				removeQ(&h->cmpQ, c);
 				if (c->type == CMD_RWREQ) {
 					complete_command(c, 0);
-					cmd_free(h, c);
+					cmd_free(h, c, 1);
 				} else if (c->type == CMD_IOCTL_PEND) {
 					c->type = CMD_IOCTL_DONE;
 				}
@@ -1243,7 +1283,7 @@
 	unsigned long flags;
 	int error;
 
-	if ((c = cmd_alloc(NULL)) == NULL)
+	if ((c = cmd_alloc(h, 0)) == NULL)
 		return -ENOMEM;
 	c->ctlr = ctlr;
 	c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
@@ -1262,13 +1302,16 @@
 		if (!p) 
 		{ 
 			error = -ENOMEM; 
-			cmd_free(NULL, c); 
+			cmd_free(h, c, 0); 
 			return(error);
 		}
 		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
-		c->req.hdr.blk = virt_to_bus(&(io->c));
+		c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c), 
+				sizeof(ida_ioctl_t), 
+				PCI_DMA_BIDIRECTIONAL);
 		c->req.sg[0].size = io->sg[0].size;
-		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev, p, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 		c->req.hdr.sg_cnt = 1;
 		break;
 	case IDA_READ:
@@ -1276,12 +1319,13 @@
 		if (!p) 
 		{ 
                         error = -ENOMEM; 
-                        cmd_free(NULL, c);
+                        cmd_free(h, c, 0);
                         return(error);
                 }
 
 		c->req.sg[0].size = io->sg[0].size;
-		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev, p, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL); 
 		c->req.hdr.sg_cnt = 1;
 		break;
 	case IDA_WRITE:
@@ -1291,20 +1335,22 @@
 		if (!p) 
  		{ 
                         error = -ENOMEM; 
-                        cmd_free(NULL, c);
+                        cmd_free(h, c, 0);
                         return(error);
                 }
 		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
 		c->req.sg[0].size = io->sg[0].size;
-		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev, p, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL); 
 		c->req.hdr.sg_cnt = 1;
 		break;
 	default:
 		c->req.sg[0].size = sizeof(io->c);
-		c->req.sg[0].addr = virt_to_bus(&io->c);
+		c->req.sg[0].addr = pci_map_single(h->pci_dev,&io->c, 
+			c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 		c->req.hdr.sg_cnt = 1;
 	}
-
+	
 	/* Put the request on the tail of the request queue */
 	spin_lock_irqsave(&io_request_lock, flags);
 	addQ(&h->reqQ, c);
@@ -1316,9 +1362,15 @@
 	while(c->type != CMD_IOCTL_DONE)
 		schedule();
 
+	/* Unmap the DMA  */
+	pci_unmap_single(h->pci_dev, c->req.sg[0].addr, c->req.sg[0].size, 
+		PCI_DMA_BIDIRECTIONAL);
 	/* Post submit processing */
 	switch(io->cmd) {
 	case PASSTHRU_A:
+		pci_unmap_single(h->pci_dev, c->req.hdr.blk,
+                                sizeof(ida_ioctl_t),
+                                PCI_DMA_BIDIRECTIONAL);
 	case IDA_READ:
 	case DIAG_PASS_THRU:
 		copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size);
@@ -1332,7 +1384,7 @@
 	}
 
 	io->rcode = c->req.hdr.rcode;
-	cmd_free(NULL, c);
+	cmd_free(h, c, 0);
 	return(0);
 }
 
@@ -1342,13 +1394,15 @@
  * critical (and can wait for kmalloc and possibly sleep) can pass in NULL
  * as the first argument to get a new command.
  */
-static cmdlist_t * cmd_alloc(ctlr_info_t *h)
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool)
 {
 	cmdlist_t * c;
 	int i;
+	dma_addr_t cmd_dhandle;
 
-	if (h == NULL) {
-		c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
+	if (!get_from_pool) {
+		c = (cmdlist_t*)pci_alloc_consistent(h->pci_dev, 
+			sizeof(cmdlist_t), &cmd_dhandle);
 		if(c==NULL)
 			return NULL;
 	} else {
@@ -1358,20 +1412,22 @@
 				return NULL;
 		} while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
 		c = h->cmd_pool + i;
+		cmd_dhandle = h->cmd_pool_dhandle + i*sizeof(cmdlist_t);
 		h->nr_allocs++;
 	}
 
 	memset(c, 0, sizeof(cmdlist_t));
-	c->busaddr = virt_to_bus(c);
+	c->busaddr = cmd_dhandle; 
 	return c;
 }
 
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c)
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool)
 {
 	int i;
 
-	if (h == NULL) {
-		kfree(c);
+	if (!got_from_pool) {
+		pci_free_consistent(h->pci_dev, sizeof(cmdlist_t), c,
+			c->busaddr);
 	} else {
 		i = c - h->cmd_pool;
 		clear_bit(i%32, h->cmd_pool_bits+(i/32));
@@ -1400,7 +1456,7 @@
 	unsigned long i;
 	ctlr_info_t *info_p = hba[ctlr];
 
-	c = cmd_alloc(info_p);
+	c = cmd_alloc(info_p, 1);
 	if(!c)
 		return IO_ERROR;
 	c->ctlr = ctlr;
@@ -1424,7 +1480,8 @@
 	c->req.hdr.blk = blk;
 	c->req.hdr.blk_cnt = blkcnt;
 	c->req.hdr.cmd = (unsigned char) cmd;
-	c->req.sg[0].addr = (__u32) virt_to_bus(buff);
+	c->req.sg[0].addr = (__u32) pci_map_single(info_p->pci_dev, 
+		buff, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 	/*
 	 * Disable interrupt
 	 */
@@ -1447,13 +1504,16 @@
 	 */
 	info_p->access.submit_command(info_p, c);
 	complete = pollcomplete(ctlr);
+	
+	pci_unmap_single(info_p->pci_dev, (dma_addr_t) c->req.sg[0].addr, 
+		c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
 	if (complete != 1) {
 		if (complete != c->busaddr) {
 			printk( KERN_WARNING
 			"cpqarray ida%d: idaSendPciCmd "
 		      "Invalid command list address returned! (%08lx)\n",
 				ctlr, (unsigned long)complete);
-			cmd_free(info_p, c);
+			cmd_free(info_p, c, 1);
 			return (IO_ERROR);
 		}
 	} else {
@@ -1461,7 +1521,7 @@
 			"cpqarray ida%d: idaSendPciCmd Timeout out, "
 			"No command list address returned!\n",
 			ctlr);
-		cmd_free(info_p, c);
+		cmd_free(info_p, c, 1);
 		return (IO_ERROR);
 	}
 
@@ -1473,11 +1533,11 @@
 				"cmd: 0x%x, return code = 0x%x\n",
 				ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
 
-			cmd_free(info_p, c);
+			cmd_free(info_p, c, 1);
 			return (IO_ERROR);
 		}
 	}
-	cmd_free(info_p, c);
+	cmd_free(info_p, c, 1);
 	return (IO_OK);
 }
 
@@ -1574,13 +1634,9 @@
 	max_p = gdev->max_p;
 	start = target << gdev->minor_shift;
 
-	for(i=max_p; i>=0; i--) {
+	for(i=max_p-1; i>=0; i--) {
 		int minor = start+i;
-		kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);
-		struct super_block *sb = get_super(devi);
-		sync_dev(devi);
-		if (sb) invalidate_inodes(sb);
-		invalidate_buffers(devi);
+		invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);
 		gdev->part[minor].start_sect = 0;	
 		gdev->part[minor].nr_sects = 0;	
 
diff -u --recursive --new-file v2.4.4/linux/drivers/block/cpqarray.h linux/drivers/block/cpqarray.h
--- v2.4.4/linux/drivers/block/cpqarray.h	Fri Feb  9 11:30:22 2001
+++ linux/drivers/block/cpqarray.h	Tue May 22 10:23:16 2001
@@ -56,6 +56,11 @@
 
 #ifdef __KERNEL__
 
+struct my_sg {
+	int size;
+	char *start_addr;
+};
+
 struct ctlr_info;
 typedef struct ctlr_info ctlr_info_t;
 
@@ -104,6 +109,7 @@
 	cmdlist_t *reqQ;
 	cmdlist_t *cmpQ;
 	cmdlist_t *cmd_pool;
+	dma_addr_t cmd_pool_dhandle;
 	__u32	*cmd_pool_bits;
 
 	unsigned int Qdepth;
diff -u --recursive --new-file v2.4.4/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.4.4/linux/drivers/block/genhd.c	Sun Sep 17 23:16:35 2000
+++ linux/drivers/block/genhd.c	Wed May 16 14:01:32 2001
@@ -17,8 +17,6 @@
 #include <linux/blk.h>
 #include <linux/init.h>
 
-extern int parport_init(void);
-extern int chr_dev_init(void);
 extern int blk_dev_init(void);
 #ifdef CONFIG_BLK_DEV_DAC960
 extern void DAC960_Initialize(void);
@@ -31,12 +29,8 @@
 extern int cpqarray_init(void);
 extern void ieee1394_init(void);
 
-void __init device_init(void)
+int __init device_init(void)
 {
-#ifdef CONFIG_PARPORT
-	parport_init();
-#endif
-	chr_dev_init();
 	blk_dev_init();
 	sti();
 #ifdef CONFIG_I2O
@@ -64,4 +58,7 @@
 #ifdef CONFIG_VT
 	console_map_init();
 #endif
+	return 0;
 }
+
+__initcall(device_init);
diff -u --recursive --new-file v2.4.4/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.4.4/linux/drivers/block/nbd.c	Wed Apr 11 19:02:30 2001
+++ linux/drivers/block/nbd.c	Tue May  1 14:20:25 2001
@@ -5,7 +5,8 @@
  * deadlocks sometimes - you can not swap over TCP in general.
  * 
  * Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
- * 
+ * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
+ *
  * (part of code stolen from loop.c)
  *
  * 97-3-25 compiled 0-th version, not yet tested it 
@@ -20,6 +21,9 @@
  * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
  * 01-2-27 Fix to store proper blockcount for kernel (calculated using
  *   BLOCK_SIZE_BITS, not device blocksize) <aga@permonline.ru>
+ * 01-3-11 Make nbd work with new Linux block layer code. It now supports
+ *   plugging like all the other block devices. Also added in MSG_MORE to
+ *   reduce number of partial TCP segments sent. <steve@chygwyn.com>
  *
  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  * why not: would need verify_area and friends, would share yet another 
diff -u --recursive --new-file v2.4.4/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.4.4/linux/drivers/block/paride/pd.c	Sun Feb  4 10:05:29 2001
+++ linux/drivers/block/paride/pd.c	Sat Apr 28 11:27:53 2001
@@ -589,9 +589,6 @@
 
 {       int p, unit, minor;
         long flags;
-        kdev_t devp;
-
-	struct super_block *sb;
 
         unit = DEVICE_NR(dev);
         if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV;
@@ -607,13 +604,7 @@
 
         for (p=(PD_PARTNS-1);p>=0;p--) {
 		minor = p + unit*PD_PARTNS;
-                devp = MKDEV(MAJOR_NR, minor);
-                fsync_dev(devp);
-
-                sb = get_super(devp);
-                if (sb) invalidate_inodes(sb);
-
-                invalidate_buffers(devp);
+                invalidate_device(MKDEV(MAJOR_NR, minor), 1);
                 pd_hd[minor].start_sect = 0;
                 pd_hd[minor].nr_sects = 0;
         }
diff -u --recursive --new-file v2.4.4/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.4.4/linux/drivers/block/ps2esdi.c	Wed Apr 18 11:49:13 2001
+++ linux/drivers/block/ps2esdi.c	Thu May 24 15:14:08 2001
@@ -56,7 +56,7 @@
 #include <asm/uaccess.h>
 
 #define PS2ESDI_IRQ 14
-#define MAX_HD 1
+#define MAX_HD 2
 #define MAX_RETRIES 5
 #define MAX_16BIT 65536
 #define ESDI_TIMEOUT   0xf000
@@ -105,14 +105,14 @@
 
 static void ps2esdi_get_device_cfg(void);
 
-void ps2esdi_reset_timer(unsigned long unused);
+static void ps2esdi_reset_timer(unsigned long unused);
 
-u_int dma_arb_level;		/* DMA arbitration level */
+static u_int dma_arb_level;		/* DMA arbitration level */
 
 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
 
-int no_int_yet;
+static int no_int_yet;
 static int access_count[MAX_HD];
 static char ps2esdi_valid[MAX_HD];
 static int ps2esdi_sizes[MAX_HD << 6];
@@ -123,26 +123,26 @@
 static struct timer_list esdi_timer = { function: ps2esdi_reset_timer };
 static int reset_status;
 static int ps2esdi_slot = -1;
-int tp720esdi = 0;		/* Is it Integrated ESDI of ThinkPad-720? */
-int intg_esdi = 0;              /* If integrated adapter */
+static int tp720esdi = 0;	/* Is it Integrated ESDI of ThinkPad-720? */
+static int intg_esdi = 0;       /* If integrated adapter */
 struct ps2esdi_i_struct {
 	unsigned int head, sect, cyl, wpcom, lzone, ctl;
 };
 
 #if 0
 #if 0				/* try both - I don't know which one is better... UB */
-struct ps2esdi_i_struct ps2esdi_info[] =
+static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
 {
 	{4, 48, 1553, 0, 0, 0},
 	{0, 0, 0, 0, 0, 0}};
 #else
-struct ps2esdi_i_struct ps2esdi_info[] =
+static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
 {
 	{64, 32, 161, 0, 0, 0},
 	{0, 0, 0, 0, 0, 0}};
 #endif
 #endif
-struct ps2esdi_i_struct ps2esdi_info[] =
+static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
 {
 	{0, 0, 0, 0, 0, 0},
 	{0, 0, 0, 0, 0, 0}};
@@ -191,9 +191,9 @@
 
 #ifdef MODULE
 
-int cyl[2] = {-1,-1};
-int head[2] = {-1, -1};
-int sect[2] = {-1, -1};
+static int cyl[MAX_HD] = {-1,-1};
+static int head[MAX_HD] = {-1, -1};
+static int sect[MAX_HD] = {-1, -1};
 
 MODULE_PARM(tp720esdi, "i");
 MODULE_PARM(cyl, "i");
@@ -203,7 +203,7 @@
 int init_module(void) {
 	int drive;
 
-	for(drive = 0; drive <= 1; drive++) {
+	for(drive = 0; drive < MAX_HD; drive++) {
 	        struct ps2_esdi_i_struct *info = &ps2esdi_info[drive];
 
         	if (cyl[drive] != -1) {
@@ -953,10 +953,10 @@
 		break;
 	}
 	if(ending != -1) {
-		spin_lock_irqsave(io_request_lock, flags);
+		spin_lock_irqsave(&io_request_lock, flags);
 		end_request(ending);
 		do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
-		spin_unlock_irqrestore(io_request_lock, flags);
+		spin_unlock_irqrestore(&io_request_lock, flags);
 	}
 }				/* handle interrupts */
 
@@ -1145,15 +1145,9 @@
 	for (partition = ps2esdi_gendisk.max_p - 1;
 	     partition >= 0; partition--) {
 		int minor = (start | partition);
-		kdev_t devp = MKDEV(MAJOR_NR, minor);
-		struct super_block * sb = get_super(devp);
-		
-		sync_dev(devp);
-		if (sb)
-			invalidate_inodes(sb);
-		invalidate_buffers(devp);
-		ps2esdi_gendisk.part[start + partition].start_sect = 0;
-		ps2esdi_gendisk.part[start + partition].nr_sects = 0;
+		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
+		ps2esdi_gendisk.part[minor].start_sect = 0;
+		ps2esdi_gendisk.part[minor].nr_sects = 0;
 	}
 
 	grok_partitions(&ps2esdi_gendisk, target, 1<<6, 
@@ -1165,7 +1159,7 @@
 	return (0);
 }
 
-void ps2esdi_reset_timer(unsigned long unused)
+static void ps2esdi_reset_timer(unsigned long unused)
 {
 
 	int status;
diff -u --recursive --new-file v2.4.4/linux/drivers/block/smart1,2.h linux/drivers/block/smart1,2.h
--- v2.4.4/linux/drivers/block/smart1,2.h	Fri Jun 23 21:04:36 2000
+++ linux/drivers/block/smart1,2.h	Tue May  1 16:05:00 2001
@@ -45,7 +45,7 @@
 }
 
 /*  
- *  This card is the oposite of the other cards.  
+ *  This card is the opposite of the other cards.  
  *   0 turns interrupts on... 
  *   0x08 turns them off... 
  */
diff -u --recursive --new-file v2.4.4/linux/drivers/block/swim3.c linux/drivers/block/swim3.c
--- v2.4.4/linux/drivers/block/swim3.c	Tue Sep 19 08:31:53 2000
+++ linux/drivers/block/swim3.c	Tue May 22 10:23:16 2001
@@ -851,7 +851,7 @@
 				   sizeof(struct floppy_struct));
 		return err;
 	}
-	return -ENOIOCTLCMD;
+	return -ENOTTY;
 }
 
 static int floppy_open(struct inode *inode, struct file *filp)
diff -u --recursive --new-file v2.4.4/linux/drivers/block/swim_iop.c linux/drivers/block/swim_iop.c
--- v2.4.4/linux/drivers/block/swim_iop.c	Wed Feb 16 10:56:45 2000
+++ linux/drivers/block/swim_iop.c	Sat May 19 17:43:05 2001
@@ -363,7 +363,7 @@
 				   sizeof(struct floppy_struct));
 		return err;
 	}
-	return -ENOIOCTLCMD;
+	return -ENOTTY;
 }
 
 static int floppy_open(struct inode *inode, struct file *filp)
diff -u --recursive --new-file v2.4.4/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.4.4/linux/drivers/block/xd.c	Fri Feb 16 16:02:35 2001
+++ linux/drivers/block/xd.c	Thu May 24 15:14:08 2001
@@ -401,13 +401,7 @@
 
 	for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
 		int minor = (start | partition);
-		kdev_t devp = MKDEV(MAJOR_NR, minor);
-		struct super_block * sb = get_super(devp);
-		
-		sync_dev(devp);
-		if (sb)
-			invalidate_inodes(sb);
-		invalidate_buffers(devp);
+		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
 		xd_gendisk.part[minor].start_sect = 0;
 		xd_gendisk.part[minor].nr_sects = 0;
 	};
@@ -1160,19 +1154,7 @@
 
 void cleanup_module(void)
 {
-	int partition,dev,start;
-
 	devfs_unregister_blkdev(MAJOR_NR, "xd");
-	for (dev = 0; dev < xd_drives; dev++) {
-		start = dev << xd_gendisk.minor_shift; 
-		for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
-			int minor = (start | partition);
-			kdev_t devp = MKDEV(MAJOR_NR, minor);
-			start = dev << xd_gendisk.minor_shift; 
-			sync_dev(devp);
-			invalidate_buffers(devp);
-		}
-	}
 	xd_done();
 	devfs_unregister (devfs_handle);
 	if (xd_drives) {
diff -u --recursive --new-file v2.4.4/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.4.4/linux/drivers/cdrom/cdrom.c	Thu Mar 29 11:56:07 2001
+++ linux/drivers/cdrom/cdrom.c	Fri May  4 15:09:23 2001
@@ -2626,7 +2626,8 @@
 
 static void cdrom_sysctl_unregister(void)
 {
-	unregister_sysctl_table(cdrom_sysctl_header);
+	if (cdrom_sysctl_header)
+		unregister_sysctl_table(cdrom_sysctl_header);
 }
 
 #endif /* CONFIG_SYSCTL */
diff -u --recursive --new-file v2.4.4/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.4.4/linux/drivers/cdrom/sbpcd.c	Fri Apr  6 10:42:55 2001
+++ linux/drivers/cdrom/sbpcd.c	Thu May 24 15:14:08 2001
@@ -1118,7 +1118,7 @@
 	return (0);
 }
 /*==========================================================================*/
-#endif 00000
+#endif
 /*==========================================================================*/
 static int ResponseInfo(void)
 {
diff -u --recursive --new-file v2.4.4/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.4.4/linux/drivers/char/Makefile	Thu Apr 26 14:11:29 2001
+++ linux/drivers/char/Makefile	Wed May 16 10:27:02 2001
@@ -16,7 +16,7 @@
 
 O_TARGET := char.o
 
-obj-y	 += tty_io.o n_tty.o tty_ioctl.o mem.o raw.o pty.o misc.o random.o
+obj-y	 += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o
 
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
diff -u --recursive --new-file v2.4.4/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.4.4/linux/drivers/char/acquirewdt.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/char/acquirewdt.c	Sat May 19 17:43:05 2001
@@ -110,7 +110,7 @@
 	  break;
 
 	default:
-	  return -ENOIOCTLCMD;
+	  return -ENOTTY;
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c
--- v2.4.4/linux/drivers/char/advantechwdt.c	Tue Mar  6 19:44:34 2001
+++ linux/drivers/char/advantechwdt.c	Sat May 19 17:43:05 2001
@@ -120,7 +120,7 @@
 	  break;
 
 	default:
-	  return -ENOIOCTLCMD;
+	  return -ENOTTY;
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c
--- v2.4.4/linux/drivers/char/agp/agpgart_fe.c	Wed Apr 11 19:02:30 2001
+++ linux/drivers/char/agp/agpgart_fe.c	Tue May 15 01:29:34 2001
@@ -852,6 +852,9 @@
 	if (copy_from_user(&reserve, (void *) arg, sizeof(agp_region))) {
 		return -EFAULT;
 	}
+	if ((unsigned) reserve.seg_count >= ~0U/sizeof(agp_segment))
+		return -EFAULT;
+
 	client = agp_find_client_by_pid(reserve.pid);
 
 	if (reserve.seg_count == 0) {
diff -u --recursive --new-file v2.4.4/linux/drivers/char/drm/ffb_drv.c linux/drivers/char/drm/ffb_drv.c
--- v2.4.4/linux/drivers/char/drm/ffb_drv.c	Fri Apr 13 20:15:55 2001
+++ linux/drivers/char/drm/ffb_drv.c	Sun May 20 12:11:38 2001
@@ -6,7 +6,6 @@
 
 #include "drmP.h"
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <asm/shmparam.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/char/drm/fops.c linux/drivers/char/drm/fops.c
--- v2.4.4/linux/drivers/char/drm/fops.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/fops.c	Tue May 22 10:23:16 2001
@@ -47,7 +47,10 @@
 	DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
 
 	priv		    = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+	if(priv == NULL)
+		return -ENOMEM;
 	memset(priv, 0, sizeof(*priv));
+
 	filp->private_data  = priv;
 	priv->uid	    = current->euid;
 	priv->pid	    = current->pid;
diff -u --recursive --new-file v2.4.4/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.4.4/linux/drivers/char/epca.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/char/epca.c	Tue May 22 10:23:16 2001
@@ -876,6 +876,9 @@
 
 		/* First we read the data in from the file system into a temp buffer */
 
+		memoff(ch);
+		restore_flags(flags);
+
 		if (bytesAvailable) 
 		{ /* Begin bytesAvailable */
 
@@ -916,8 +919,6 @@
 			post_fep_init.
 		--------------------------------------------------------------------- */
 		buf = ch->tmp_buf;
-		memoff(ch);
-		restore_flags(flags);
 
 	} /* End from_user */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- v2.4.4/linux/drivers/char/i810-tco.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/char/i810-tco.c	Thu May 24 15:14:08 2001
@@ -181,8 +181,10 @@
 	/*
 	 *      Shut off the timer.
 	 */
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
 	tco_timer_stop ();
 	timer_alive = 0;
+#endif	
 	return 0;
 }
 
@@ -213,7 +215,7 @@
 	};
 	switch (cmd) {
 	default:
-		return -ENOIOCTLCMD;
+		return -ENOTTY;
 	case WDIOC_GETSUPPORT:
 		if (copy_to_user
 		    ((struct watchdog_info *) arg, &ident, sizeof (ident)))
diff -u --recursive --new-file v2.4.4/linux/drivers/char/machzwd.c linux/drivers/char/machzwd.c
--- v2.4.4/linux/drivers/char/machzwd.c	Thu Apr 12 12:16:35 2001
+++ linux/drivers/char/machzwd.c	Tue May 22 10:23:16 2001
@@ -357,7 +357,7 @@
 			break;
 
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 	}
 
 	return 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.4.4/linux/drivers/char/mem.c	Fri Apr 27 14:23:25 2001
+++ linux/drivers/char/mem.c	Sat May 19 18:11:36 2001
@@ -29,9 +29,6 @@
 #ifdef CONFIG_I2C
 extern int i2c_init_all(void);
 #endif
-#ifdef CONFIG_VIDEO_DEV
-extern int videodev_init(void);
-#endif
 #ifdef CONFIG_FB
 extern void fbmem_init(void);
 #endif
@@ -648,8 +645,7 @@
 #if defined(CONFIG_ADB)
 	adbdev_init();
 #endif
-#ifdef CONFIG_VIDEO_DEV
-	videodev_init();
-#endif
 	return 0;
 }
+
+__initcall(chr_dev_init);
diff -u --recursive --new-file v2.4.4/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.4.4/linux/drivers/char/misc.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/char/misc.c	Thu May 24 15:14:08 2001
@@ -73,7 +73,6 @@
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int ds1286_init(void);
-extern int radio_init(void);
 extern int pmu_device_init(void);
 extern int tosh_init(void);
 
@@ -261,9 +260,6 @@
 #endif
 #ifdef CONFIG_SGI_DS1286
 	ds1286_init();
-#endif
-#ifdef CONFIG_MISC_RADIO
-	radio_init();
 #endif
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_device_init();
diff -u --recursive --new-file v2.4.4/linux/drivers/char/mixcomwd.c linux/drivers/char/mixcomwd.c
--- v2.4.4/linux/drivers/char/mixcomwd.c	Sun Dec  3 17:45:21 2000
+++ linux/drivers/char/mixcomwd.c	Tue May 22 10:23:16 2001
@@ -165,7 +165,7 @@
 			mixcomwd_ping();
 			break;
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/char/moxa.c linux/drivers/char/moxa.c
--- v2.4.4/linux/drivers/char/moxa.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/moxa.c	Tue May 22 10:23:16 2001
@@ -698,21 +698,32 @@
 	struct moxa_str *ch;
 	int len, port;
 	unsigned long flags;
-	unsigned char *temp;
 
 	ch = (struct moxa_str *) tty->driver_data;
 	if (ch == NULL)
 		return (0);
 	port = ch->port;
 	save_flags(flags);
-	cli();
 	if (from_user) {
-		copy_from_user(moxaXmitBuff, buf, count);
-		temp = moxaXmitBuff;
-	} else
-		temp = (unsigned char *) buf;
-	len = MoxaPortWriteData(port, temp, count);
-	restore_flags(flags);
+		if (count > PAGE_SIZE)
+			count = PAGE_SIZE;
+		down(&moxaBuffSem);
+		if (copy_from_user(moxaXmitBuff, buf, count)) {
+			len = -EFAULT;
+		} else {
+			cli();
+			len = MoxaPortWriteData(port, moxaXmitBuff, count);
+			restore_flags(flags);
+		}
+		up(&moxaBuffSem);
+		if (len < 0)
+			return len;
+	} else {
+		cli();
+		len = MoxaPortWriteData(port, (unsigned char *) buf, count);
+		restore_flags(flags);
+	}
+
 	/*********************************************
 	if ( !(ch->statusflags & LOWWAIT) &&
 	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )
diff -u --recursive --new-file v2.4.4/linux/drivers/char/mxser.c linux/drivers/char/mxser.c
--- v2.4.4/linux/drivers/char/mxser.c	Fri Mar  2 11:12:07 2001
+++ linux/drivers/char/mxser.c	Wed May 16 10:31:27 2001
@@ -27,10 +27,11 @@
  *
  *      Copyright (C) 1999,2000  Moxa Technologies Co., LTD.
  *
- *      for             : LINUX 2.0.X, 2.2.X
- *      date            : 1999/07/22
- *      version         : 1.1 
+ *      for             : LINUX 2.0.X, 2.2.X, 2.4.X
+ *      date            : 2001/05/01
+ *      version         : 1.2 
  *      
+ *    Fixes for C104H/PCI by Tim Hockin <thockin@sun.com>
  */
 
 #include <linux/config.h>
@@ -61,7 +62,7 @@
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
-#define		MXSER_VERSION			"1.1kern"
+#define		MXSER_VERSION			"1.2"
 
 #define		MXSERMAJOR	 	174
 #define		MXSERCUMAJOR		175
@@ -120,7 +121,7 @@
 #define CI104J_ASIC_ID  5
 
 enum {
-	MXSER_BOARD_C168_ISA = 1,
+	MXSER_BOARD_C168_ISA = 0,
 	MXSER_BOARD_C104_ISA,
 	MXSER_BOARD_CI104J,
 	MXSER_BOARD_C168_PCI,
@@ -434,7 +435,7 @@
 			     "mxser", info);
 	if (retval) {
 		restore_flags(flags);
-		printk("Board %d: %s", board, mxser_brdname[hwconf->board_type - 1]);
+		printk("Board %d: %s", board, mxser_brdname[hwconf->board_type]);
 		printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq);
 		return (retval);
 	}
@@ -455,7 +456,7 @@
 	unsigned int ioaddress;
 
 	hwconf->board_type = board_type;
-	hwconf->ports = mxser_numports[board_type - 1];
+	hwconf->ports = mxser_numports[board_type];
 	ioaddress = pci_resource_start (pdev, 2);
 	for (i = 0; i < hwconf->ports; i++)
 		hwconf->ioaddr[i] = ioaddress + 8 * i;
@@ -544,7 +545,7 @@
 
 		if (retval != 0)
 			printk("Found MOXA %s board (CAP=0x%x)\n",
-			       mxser_brdname[hwconf.board_type - 1],
+			       mxser_brdname[hwconf.board_type],
 			       ioaddr[b]);
 
 		if (retval <= 0) {
@@ -579,7 +580,7 @@
 
 		if (retval != 0)
 			printk("Found MOXA %s board (CAP=0x%x)\n",
-			       mxser_brdname[hwconf.board_type - 1],
+			       mxser_brdname[hwconf.board_type],
 			       ioaddr[b]);
 
 		if (retval <= 0) {
@@ -612,21 +613,15 @@
 
 		n = sizeof(mxser_pcibrds) / sizeof(mxser_pciinfo);
 		index = 0;
-		b = 0;
-		while (b < n) {
+		for (b = 0; b < n; b++) {
 			pdev = pci_find_device(mxser_pcibrds[b].vendor_id,
 					       mxser_pcibrds[b].device_id, pdev);
-			if (!pdev)
-			{
-				b++;
-				continue;
-			}
-			if (pci_enable_device(pdev))
+			if (!pdev || pci_enable_device(pdev))
 				continue;
 			hwconf.pdev = pdev;
 			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
-				mxser_brdname[mxser_pcibrds[b].board_type - 1],
-				pdev->bus->number, PCI_SLOT(pdev->devfn >> 3));
+				mxser_brdname[mxser_pcibrds[b].board_type],
+				pdev->bus->number, PCI_SLOT(pdev->devfn));
 			if (m >= MXSER_BOARDS) {
 				printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
 			} else {
@@ -892,29 +887,56 @@
 	if (from_user)
 		down(&mxvar_tmp_buf_sem);
 	save_flags(flags);
-	while (1) {
-		cli();
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
+	if (from_user) {
+		down(&mxvar_tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
 
-		if (from_user) {
-			copy_from_user(mxvar_tmp_buf, buf, c);
+			c -= copy_from_user(mxvar_tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
+
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				    SERIAL_XMIT_SIZE - info->xmit_head));
+				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
-		} else
+			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+			info->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&mxvar_tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
+
 			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+			info->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&mxvar_tmp_buf_sem);
+
+	cli();
 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
@@ -1352,7 +1374,7 @@
 		return;
 	if (port == 0)
 		return;
-	max = mxser_numports[mxsercfg[i].board_type - 1];
+	max = mxser_numports[mxsercfg[i].board_type];
 
 	while (1) {
 		irqbits = inb(port->vector) & port->vectormask;
diff -u --recursive --new-file v2.4.4/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.4.4/linux/drivers/char/pc110pad.c	Sun Feb  4 10:05:29 2001
+++ linux/drivers/char/pc110pad.c	Tue May 22 10:23:16 2001
@@ -766,7 +766,7 @@
 		current_params.tap_interval	= new.tap_interval;
 		return 0;
 	}
-	return -ENOIOCTLCMD;
+	return -ENOTTY;
 }
 
 
diff -u --recursive --new-file v2.4.4/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.4.4/linux/drivers/char/pcwd.c	Fri Apr  6 10:42:55 2001
+++ linux/drivers/char/pcwd.c	Thu May 24 15:14:08 2001
@@ -247,7 +247,7 @@
 
 	switch(cmd) {
 	default:
-		return -ENOIOCTLCMD;
+		return -ENOTTY;
 
 	case WDIOC_GETSUPPORT:
 		i = copy_to_user((void*)arg, &ident, sizeof(ident));
@@ -506,6 +506,8 @@
 	char *ret;
 
 	ret = kmalloc(6, GFP_KERNEL);
+	if(ret == NULL)
+		return NULL;
 
 	while((count < 3) && (!found)) {
 		outb_p(0x80, current_readport + 2);
@@ -527,10 +529,8 @@
 		ten = send_command(0x82);
 		hund = send_command(0x83);
 		minor = send_command(0x84);
-	}
-
-	if (found)
 		sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+	}
 	else
 		sprintf(ret, "ERROR");
 
@@ -642,12 +642,12 @@
 
 static void __exit pcwatchdog_exit(void)
 {
+	misc_deregister(&pcwd_miscdev);
 	/*  Disable the board  */
 	if (revision == PCWD_REVISION_C) {
 		outb_p(0xA5, current_readport + 3);
 		outb_p(0xA5, current_readport + 3);
 	}
-	misc_deregister(&pcwd_miscdev);
 	if (supports_temp)
 		misc_deregister(&temp_miscdev);
 
diff -u --recursive --new-file v2.4.4/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.4.4/linux/drivers/char/pcxx.c	Fri Feb 16 16:02:35 2001
+++ linux/drivers/char/pcxx.c	Tue May 22 10:23:16 2001
@@ -685,7 +685,6 @@
 	int total, remain, size, stlen;
 	unsigned int head, tail;
 	unsigned long flags;
-
 	/* printk("Entering pcxe_write()\n"); */
 
 	if ((ch=chan(tty))==NULL)
@@ -696,6 +695,7 @@
 
 	if (from_user) {
 
+		down(&ch->tmp_buf_sem);
 		save_flags(flags);
 		cli();
 		globalwinon(ch);
@@ -703,19 +703,21 @@
 		/* It seems to be necessary to make sure that the value is stable here somehow
 		   This is a rather odd pice of code here. */
 		do
-		{ tail = bc->tout;
+		{
+			tail = bc->tout;
 		} while (tail != bc->tout);
 		
 		tail &= (size - 1);
 		stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
 		count = MIN(stlen, count);
+		memoff(ch);
+		restore_flags(flags);
+
 		if (count)
 			if (copy_from_user(ch->tmp_buf, buf, count))
 				count = 0;
 
 		buf = ch->tmp_buf;
-		memoff(ch);
-		restore_flags(flags);
 	}
 
 	/*
@@ -763,6 +765,9 @@
 	}
 	memoff(ch);
 	restore_flags(flags);
+	
+	if(from_user)
+		up(&ch->tmp_buf_sem);
 
 	return(total);
 }
@@ -1587,6 +1592,7 @@
 			ch->txbufsize = bc->tmax + 1;
 			ch->rxbufsize = bc->rmax + 1;
 			ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
+			init_MUTEX(&ch->tmp_buf_sem);
 
 			if (!ch->tmp_buf) {
 				printk(KERN_ERR "Unable to allocate memory for temp buffers\n");
diff -u --recursive --new-file v2.4.4/linux/drivers/char/pcxx.h linux/drivers/char/pcxx.h
--- v2.4.4/linux/drivers/char/pcxx.h	Tue Aug 22 15:21:54 2000
+++ linux/drivers/char/pcxx.h	Tue May 22 10:23:16 2001
@@ -120,6 +120,7 @@
 	unchar						*txptr;
 	unchar						*rxptr;
 	unchar						*tmp_buf;		/* Temp buffer */
+	struct semaphore				tmp_buf_sem;
 							/* ---- Termios data ---- */
 	ulong						c_iflag;
 	ulong						c_cflag;
diff -u --recursive --new-file v2.4.4/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.4.4/linux/drivers/char/ppdev.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/ppdev.c	Sat May 19 18:07:04 2001
@@ -35,17 +35,25 @@
  *   WCTLONIRQ	on interrupt, set control lines
  *   CLRIRQ	clear (and return) interrupt count
  *   SETTIME	sets device timeout (struct timeval)
- *   GETTIME    gets device timeout (struct timeval)
+ *   GETTIME	gets device timeout (struct timeval)
+ *   GETMODES	gets hardware supported modes (unsigned int)
+ *   GETMODE	gets the current IEEE1284 mode
+ *   GETPHASE   gets the current IEEE1284 phase
+ *   GETFLAGS   gets current (user-visible) flags
+ *   SETFLAGS   sets current (user-visible) flags
  * read/write	read or write in current IEEE 1284 protocol
  * select	wait for interrupt (in readfds)
  *
  * Changes:
- * Added SETTIME/GETTIME ioctl, Fred Barnes 1999.
+ * Added SETTIME/GETTIME ioctl, Fred Barnes, 1999.
  *
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 2000/08/25
  * - On error, copy_from_user and copy_to_user do not return -EFAULT,
  *   They return the positive number of bytes *not* copied due to address
  *   space errors.
+ *
+ * Added GETMODES/GETMODE/GETPHASE ioctls, Fred Barnes <frmb2@ukc.ac.uk>, 03/01/2001.
+ * Added GETFLAGS/SETFLAGS ioctls, Fred Barnes, 04/2001
  */
 
 #include <linux/module.h>
@@ -84,7 +92,7 @@
 
 /* Other constants */
 #define PP_INTERRUPT_TIMEOUT (10 * HZ) /* 10s */
-#define PP_BUFFER_SIZE 256
+#define PP_BUFFER_SIZE 1024
 #define PARDEVICE_MAX 8
 
 /* ROUND_UP macro from fs/select.c */
@@ -109,6 +117,8 @@
 	char * kbuffer;
 	ssize_t bytes_read = 0;
 	ssize_t got = 0;
+	struct parport *pport;
+	int mode;
 
 	if (!(pp->flags & PP_CLAIMED)) {
 		/* Don't have the port claimed */
@@ -118,18 +128,40 @@
 	}
 
 	kbuffer = kmalloc (min (count, PP_BUFFER_SIZE), GFP_KERNEL);
-	if (!kbuffer)
+	if (!kbuffer) {
 		return -ENOMEM;
+	}
+	pport = pp->pdev->port;
+	mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
 
 	while (bytes_read < count) {
 		ssize_t need = min(count - bytes_read, PP_BUFFER_SIZE);
 
-		got = parport_read (pp->pdev->port, kbuffer, need);
+		if (mode == IEEE1284_MODE_EPP) {
+			/* various specials for EPP mode */
+			int flags = 0;
+			size_t (*fn)(struct parport *, void *, size_t, int);
+
+			if (pp->flags & PP_W91284PIC) {
+				flags |= PARPORT_W91284PIC;
+			}
+			if (pp->flags & PP_FASTREAD) {
+				flags |= PARPORT_EPP_FAST;
+			}
+			if (pport->ieee1284.mode & IEEE1284_ADDR) {
+				fn = pport->ops->epp_read_addr;
+			} else {
+				fn = pport->ops->epp_read_data;
+			}
+			got = (*fn)(pport, kbuffer, need, flags);
+		} else {
+			got = parport_read (pport, kbuffer, need);
+		}
 
 		if (got <= 0) {
-			if (!bytes_read)
+			if (!bytes_read) {
 				bytes_read = got;
-
+			}
 			break;
 		}
 
@@ -141,13 +173,15 @@
 		bytes_read += got;
 
 		if (signal_pending (current)) {
-			if (!bytes_read)
+			if (!bytes_read) {
 				bytes_read = -EINTR;
+			}
 			break;
 		}
 
-		if (current->need_resched)
+		if (current->need_resched) {
 			schedule ();
+		}
 	}
 
 	kfree (kbuffer);
@@ -163,6 +197,8 @@
 	char * kbuffer;
 	ssize_t bytes_written = 0;
 	ssize_t wrote;
+	int mode;
+	struct parport *pport;
 
 	if (!(pp->flags & PP_CLAIMED)) {
 		/* Don't have the port claimed */
@@ -172,8 +208,11 @@
 	}
 
 	kbuffer = kmalloc (min (count, PP_BUFFER_SIZE), GFP_KERNEL);
-	if (!kbuffer)
+	if (!kbuffer) {
 		return -ENOMEM;
+	}
+	pport = pp->pdev->port;
+	mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
 
 	while (bytes_written < count) {
 		ssize_t n = min(count - bytes_written, PP_BUFFER_SIZE);
@@ -183,24 +222,38 @@
 			break;
 		}
 
-		wrote = parport_write (pp->pdev->port, kbuffer, n);
+		if ((pp->flags & PP_FASTWRITE) && (mode == IEEE1284_MODE_EPP)) {
+			/* do a fast EPP write */
+			if (pport->ieee1284.mode & IEEE1284_ADDR) {
+				wrote = pport->ops->epp_write_addr (pport,
+					kbuffer, n, PARPORT_EPP_FAST);
+			} else {
+				wrote = pport->ops->epp_write_data (pport,
+					kbuffer, n, PARPORT_EPP_FAST);
+			}
+		} else {
+			wrote = parport_write (pp->pdev->port, kbuffer, n);
+		}
 
 		if (wrote <= 0) {
-			if (!bytes_written)
+			if (!bytes_written) {
 				bytes_written = wrote;
+			}
 			break;
 		}
 
 		bytes_written += wrote;
 
 		if (signal_pending (current)) {
-			if (!bytes_written)
+			if (!bytes_written) {
 				bytes_written = -EINTR;
+			}
 			break;
 		}
 
-		if (current->need_resched)
+		if (current->need_resched) {
 			schedule ();
+		}
 	}
 
 	kfree (kbuffer);
@@ -276,7 +329,9 @@
 	struct parport * port;
 
 	/* First handle the cases that don't take arguments. */
-	if (cmd == PPCLAIM) {
+	switch (cmd) {
+	case PPCLAIM:
+	    {
 		struct ieee1284_info *info;
 
 		if (pp->flags & PP_CLAIMED) {
@@ -288,8 +343,9 @@
 		/* Deferred device registration. */
 		if (!pp->pdev) {
 			int err = register_device (minor, pp);
-			if (err)
+			if (err) {
 				return err;
+			}
 		}
 
 		parport_claim_or_block (pp->pdev);
@@ -307,9 +363,8 @@
 		info->phase = pp->state.phase;
 
 		return 0;
-	}
-
-	if (cmd == PPEXCL) {
+	    }
+	case PPEXCL:
 		if (pp->pdev) {
 			printk (KERN_DEBUG CHRDEV "%x: too late for PPEXCL; "
 				"already registered\n", minor);
@@ -324,9 +379,8 @@
 		 * when we finally do the registration. */
 		pp->flags |= PP_EXCL;
 		return 0;
-	}
-
-	if (cmd == PPSETMODE) {
+	case PPSETMODE:
+	    {
 		int mode;
 		if (copy_from_user (&mode, (int *) arg, sizeof (mode)))
 			return -EFAULT;
@@ -340,20 +394,82 @@
 		}
 
 		return 0;
-	}
+	    }
+	case PPGETMODE:
+	    {
+		int mode;
 
-	if (cmd == PPSETPHASE) {
+		if (pp->flags & PP_CLAIMED) {
+			mode = pp->pdev->port->ieee1284.mode;
+		} else {
+			mode = pp->state.mode;
+		}
+		if (copy_to_user ((int *)arg, &mode, sizeof (mode))) {
+			return -EFAULT;
+		}
+		return 0;
+	    }
+	case PPSETPHASE:
+	    {
 		int phase;
-		if (copy_from_user (&phase, (int *) arg, sizeof (phase)))
+		if (copy_from_user (&phase, (int *) arg, sizeof (phase))) {
 			return -EFAULT;
+		}
 		/* FIXME: validate phase */
 		pp->state.phase = phase;
 
-		if (pp->flags & PP_CLAIMED)
+		if (pp->flags & PP_CLAIMED) {
 			pp->pdev->port->ieee1284.phase = phase;
+		}
 
 		return 0;
-	}
+	    }
+	case PPGETPHASE:
+	    {
+		int phase;
+
+		if (pp->flags & PP_CLAIMED) {
+			phase = pp->pdev->port->ieee1284.phase;
+		} else {
+			phase = pp->state.phase;
+		}
+		if (copy_to_user ((int *)arg, &phase, sizeof (phase))) {
+			return -EFAULT;
+		}
+		return 0;
+	    }
+	case PPGETMODES:
+	    {
+		unsigned int modes;
+
+		modes = pp->pdev->port->modes;
+		if (copy_to_user ((unsigned int *)arg, &modes, sizeof (port->modes))) {
+			return -EFAULT;
+		}
+		return 0;
+	    }
+	case PPSETFLAGS:
+	    {
+		int uflags;
+
+		if (copy_from_user (&uflags, (int *)arg, sizeof (uflags))) {
+			return -EFAULT;
+		}
+		pp->flags &= ~PP_FLAGMASK;
+		pp->flags |= (uflags & PP_FLAGMASK);
+		return 0;
+	    }
+	case PPGETFLAGS:
+	    {
+		int uflags;
+
+		uflags = pp->flags & PP_FLAGMASK;
+		if (copy_to_user ((int *)arg, &uflags, sizeof (uflags))) {
+			return -EFAULT;
+		}
+		return 0;
+	    }
+	}	/* end switch() */
 
 	/* Everything else requires the port to be claimed, so check
 	 * that now. */
@@ -537,13 +653,28 @@
 {
 	unsigned int minor = MINOR (inode->i_rdev);
 	struct pp_struct *pp = file->private_data;
+	int compat_negot;
 
 	lock_kernel();
-	if (pp->pdev && pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT) {
-		if (!(pp->flags & PP_CLAIMED)) {
-			parport_claim_or_block (pp->pdev);
-			pp->flags |= PP_CLAIMED;
-		}
+	compat_negot = 0;
+	if (!(pp->flags & PP_CLAIMED) && pp->pdev &&
+	    (pp->state.mode != IEEE1284_MODE_COMPAT)) {
+	    	struct ieee1284_info *info;
+
+		/* parport released, but not in compatability mode */
+		parport_claim_or_block (pp->pdev);
+		pp->flags |= PP_CLAIMED;
+		info = &pp->pdev->port->ieee1284;
+		pp->saved_state.mode = info->mode;
+		pp->saved_state.phase = info->phase;
+		info->mode = pp->state.mode;
+		info->phase = pp->state.phase;
+		compat_negot = 1;
+	} else if ((pp->flags & PP_CLAIMED) && pp->pdev &&
+	    (pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT)) {
+		compat_negot = 2;
+	}
+	if (compat_negot) {
 		parport_negotiate (pp->pdev->port, IEEE1284_MODE_COMPAT);
 		printk (KERN_DEBUG CHRDEV
 			"%x: negotiated back to compatibility mode because "
@@ -551,9 +682,18 @@
 	}
 
 	if (pp->flags & PP_CLAIMED) {
+		struct ieee1284_info *info;
+
+		info = &pp->pdev->port->ieee1284;
+		pp->state.mode = info->mode;
+		pp->state.phase = info->phase;
+		info->mode = pp->saved_state.mode;
+		info->phase = pp->saved_state.phase;
 		parport_release (pp->pdev);
-		printk (KERN_DEBUG CHRDEV "%x: released pardevice because "
-			"user-space forgot\n", minor);
+		if (compat_negot != 1) {
+			printk (KERN_DEBUG CHRDEV "%x: released pardevice "
+				"because user-space forgot\n", minor);
+		}
 	}
 
 	if (pp->pdev) {
diff -u --recursive --new-file v2.4.4/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.4.4/linux/drivers/char/random.c	Fri Feb 16 16:02:36 2001
+++ linux/drivers/char/random.c	Tue May  1 16:05:00 2001
@@ -610,7 +610,7 @@
 static void batch_entropy_process(void *private_);
 
 /* note: the size must be a power of 2 */
-static int batch_entropy_init(int size, struct entropy_store *r)
+static int __init batch_entropy_init(int size, struct entropy_store *r)
 {
 	batch_entropy_pool = kmalloc(2*size*sizeof(__u32), GFP_KERNEL);
 	if (!batch_entropy_pool)
diff -u --recursive --new-file v2.4.4/linux/drivers/char/raw.c linux/drivers/char/raw.c
--- v2.4.4/linux/drivers/char/raw.c	Fri Apr 27 14:23:25 2001
+++ linux/drivers/char/raw.c	Sun May 20 11:34:05 2001
@@ -131,7 +131,7 @@
 	 */
 	
 	sector_size = 512;
-	if (get_super(rdev) != NULL) {
+	if (is_mounted(rdev)) {
 		if (blksize_size[MAJOR(rdev)])
 			sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
 	} else {
diff -u --recursive --new-file v2.4.4/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.4.4/linux/drivers/char/riscom8.c	Thu Jan  4 12:50:12 2001
+++ linux/drivers/char/riscom8.c	Wed May 16 10:31:27 2001
@@ -1217,33 +1217,58 @@
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 
-	if (from_user)
+	save_flags(flags);
+	if (from_user) {
 		down(&tmp_buf_sem);
+		while (1) {
+			cli();		
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0)
+				break;
 
-	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
 
-		if (from_user) {
-			copy_from_user(tmp_buf, buf, c);
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-		} else
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
+
 			memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&tmp_buf_sem);
+
+	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
@@ -1251,6 +1276,7 @@
 		rc_out(bp, CD180_IER, port->IER);
 	}
 	restore_flags(flags);
+
 	return total;
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c
--- v2.4.4/linux/drivers/char/sbc60xxwdt.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/char/sbc60xxwdt.c	Tue May 22 10:23:16 2001
@@ -16,6 +16,7 @@
  *
  *           12/4 - 2000      [Initial revision]
  *           25/4 - 2000      Added /dev/watchdog support
+ *           09/5 - 2001      [smj@oro.net] fixed fop_write to "return 1" on success
  *
  *
  *  Theory of operation:
@@ -178,6 +179,7 @@
 
 		/* Well, anyhow someone wrote to us, we should return that favour */
 		next_heartbeat = jiffies + WDT_HEARTBEAT;
+		return 1;
 	}
 	return 0;
 }
@@ -241,7 +243,7 @@
 	switch(cmd)
 	{
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 		case WDIOC_GETSUPPORT:
 			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
 		case WDIOC_KEEPALIVE:
diff -u --recursive --new-file v2.4.4/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.4.4/linux/drivers/char/serial.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/char/serial.c	Sun May 20 12:11:38 2001
@@ -565,9 +565,12 @@
 
 	icount = &info->state->icount;
 	do {
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			tty->flip.tqueue.routine((void *) tty);
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				return;		// if TTY_DONT_FLIP is set
+		}
 		ch = serial_inp(info, UART_RX);
-		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-			goto ignore_char;
 		*tty->flip.char_buf_ptr = ch;
 		icount->rx++;
 		
@@ -657,7 +660,9 @@
 			tty->flip.flag_buf_ptr++;
 			tty->flip.char_buf_ptr++;
 		}
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 	ignore_char:
+#endif
 		*status = serial_inp(info, UART_LSR);
 	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
 #if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
diff -u --recursive --new-file v2.4.4/linux/drivers/char/serial167.c linux/drivers/char/serial167.c
--- v2.4.4/linux/drivers/char/serial167.c	Mon Nov 27 17:11:26 2000
+++ linux/drivers/char/serial167.c	Wed May 16 10:31:27 2001
@@ -1247,36 +1247,54 @@
         return 0;
     }
 
-    while (1) {
-        save_flags(flags); cli();		
-	c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-			   SERIAL_XMIT_SIZE - info->xmit_head));
-	if (c <= 0){
-	    restore_flags(flags);
-	    break;
-	}
-
-	if (from_user) {
+    if (from_user) {
 	    down(&tmp_buf_sem);
-	    if (copy_from_user(tmp_buf, buf, c)) {
-	    	up(&tmp_buf_sem);
-	        restore_flags(flags);
-		return 0;
+	    while (1) {
+		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    if (c <= 0)
+			    break;
+
+		    c -= copy_from_user(tmp_buf, buf, c);
+		    if (!c) {
+			    if (!total)
+				    total = -EFAULT;
+			    break;
+		    }
+
+		    cli();
+		    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				   SERIAL_XMIT_SIZE - info->xmit_head));
+		    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		    info->xmit_cnt += c;
+		    restore_flags(flags);
+
+		    buf += c;
+		    count -= c;
+		    total += c;
 	    }
-	    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-		       SERIAL_XMIT_SIZE - info->xmit_head));
-	    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 	    up(&tmp_buf_sem);
-	} else
-	    memcpy(info->xmit_buf + info->xmit_head, buf, c);
-	info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-	info->xmit_cnt += c;
-	restore_flags(flags);
-	buf += c;
-	count -= c;
-	total += c;
-    }
+    } else {
+	    while (1) {
+		    cli();
+		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    if (c <= 0) {
+			    restore_flags(flags);
+			    break;
+		    }
+
+		    memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		    info->xmit_cnt += c;
+		    restore_flags(flags);
 
+		    buf += c;
+		    count -= c;
+		    total += c;
+	    }
+    }
 
     if (info->xmit_cnt
     && !tty->stopped
diff -u --recursive --new-file v2.4.4/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.4.4/linux/drivers/char/softdog.c	Tue Feb 13 14:13:43 2001
+++ linux/drivers/char/softdog.c	Sat May 19 17:43:05 2001
@@ -132,7 +132,7 @@
 	};
 	switch (cmd) {
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 		case WDIOC_GETSUPPORT:
 			if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
 				return -EFAULT;
diff -u --recursive --new-file v2.4.4/linux/drivers/char/specialix.c linux/drivers/char/specialix.c
--- v2.4.4/linux/drivers/char/specialix.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/specialix.c	Wed May 16 10:31:27 2001
@@ -1611,33 +1611,56 @@
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 
-	if (from_user)
+	save_flags(flags);
+	if (from_user) {
 		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0)
+				break;
 
-	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-		                   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
 
-		if (from_user) {
-			copy_from_user(tmp_buf, buf, c);
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			               SERIAL_XMIT_SIZE - port->xmit_head));
+				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-		} else
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&tmp_buf_sem);
+
+	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
diff -u --recursive --new-file v2.4.4/linux/drivers/char/synclink.c linux/drivers/char/synclink.c
--- v2.4.4/linux/drivers/char/synclink.c	Wed Apr 18 14:40:06 2001
+++ linux/drivers/char/synclink.c	Tue May  1 16:05:00 2001
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 3.2 2000/11/06 22:34:38 paul Exp $
+ * $Id: synclink.c,v 3.8 2001/03/30 17:30:38 ez Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -107,8 +107,12 @@
 #endif
 
 #ifdef CONFIG_SYNCLINK_SYNCPPP
+#if LINUX_VERSION_CODE < VERSION(2,4,3) 
+#include "../net/wan/syncppp.h"
+#else
 #include <net/syncppp.h>
 #endif
+#endif
 
 #include <asm/segment.h>
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -176,6 +180,14 @@
 	int	cts_down;
 };
 
+/* transmit holding buffer definitions*/
+#define MAX_TX_HOLDING_BUFFERS 5
+struct tx_holding_buffer {
+	int	buffer_size;
+	unsigned char *	buffer;
+};
+
+
 /*
  * Device instance data structure
  */
@@ -241,11 +253,21 @@
 	DMABUFFERENTRY *rx_buffer_list;	/* list of receive buffer entries */
 	unsigned int current_rx_buffer;
 
+	int num_tx_dma_buffers;		/* number of tx dma frames required */
+ 	int tx_dma_buffers_used;
 	unsigned int tx_buffer_count;	/* count of total allocated Tx buffers */
 	DMABUFFERENTRY *tx_buffer_list;	/* list of transmit buffer entries */
+	int start_tx_dma_buffer;	/* tx dma buffer to start tx dma operation */
+	int current_tx_buffer;          /* next tx dma buffer to be loaded */
 	
 	unsigned char *intermediate_rxbuffer;
 
+	int num_tx_holding_buffers;	/* number of tx holding buffer allocated */
+	int get_tx_holding_index;  	/* next tx holding buffer for adapter to load */
+	int put_tx_holding_index;  	/* next tx holding buffer to store user request */
+	int tx_holding_count;		/* number of tx holding buffers waiting */
+	struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS];
+
 	int rx_enabled;
 	int rx_overflow;
 
@@ -685,6 +707,8 @@
 #define usc_TCmd(a,b) usc_OutReg((a), TCSR, (u16)((a)->tcsr_value + (b)))
 #define usc_RCmd(a,b) usc_OutReg((a), RCSR, (b))
 
+#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1))
+
 void usc_process_rxoverrun_sync( struct mgsl_struct *info );
 void usc_start_receiver( struct mgsl_struct *info );
 void usc_stop_receiver( struct mgsl_struct *info );
@@ -775,7 +799,10 @@
  */
 void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
 int  mgsl_get_rx_frame( struct mgsl_struct *info );
+int  mgsl_get_raw_rx_frame( struct mgsl_struct *info );
 void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
+void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
+int num_free_tx_dma_buffers(struct mgsl_struct *info);
 void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
 void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
 
@@ -790,6 +817,10 @@
 void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
 int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
 void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
+void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
+int load_next_tx_holding_buffer(struct mgsl_struct *info);
+int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
 
 /*
  * Bottom half interrupt handlers
@@ -810,6 +841,7 @@
 void mgsl_isr_io_pin( struct mgsl_struct *info );
 void mgsl_isr_misc( struct mgsl_struct *info );
 void mgsl_isr_receive_dma( struct mgsl_struct *info );
+void mgsl_isr_transmit_dma( struct mgsl_struct *info );
 
 typedef void (*isr_dispatch_func)(struct mgsl_struct *);
 
@@ -874,6 +906,8 @@
 static int debug_level = 0;
 static int maxframe[MAX_TOTAL_DEVICES] = {0,};
 static int dosyncppp[MAX_TOTAL_DEVICES] = {0,};
+static int txdmabufs[MAX_TOTAL_DEVICES] = {0,};
+static int txholdbufs[MAX_TOTAL_DEVICES] = {0,};
 	
 MODULE_PARM(break_on_load,"i");
 MODULE_PARM(ttymajor,"i");
@@ -884,9 +918,11 @@
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
+MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
+MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "3.2";
+static char *driver_version = "3.8";
 
 static int __init synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
@@ -1096,11 +1132,14 @@
 
 void mgsl_bh_receive(struct mgsl_struct *info)
 {
+	int (*get_rx_frame)(struct mgsl_struct *info) =
+		(info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
+
 	if ( debug_level >= DEBUG_LEVEL_BH )
 		printk( "%s(%d):mgsl_bh_receive(%s)\n",
 			__FILE__,__LINE__,info->device_name);
 	
-	while( mgsl_get_rx_frame(info) );
+	while( (get_rx_frame)(info) );
 }
 
 void mgsl_bh_transmit(struct mgsl_struct *info)
@@ -1318,11 +1357,6 @@
 #endif
 			} else
 				info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    (status & MISCSTATUS_DCD_LATCHED))
-				hardpps();
-#endif
 		}
 		if (status & MISCSTATUS_CTS_LATCHED)
 		{
@@ -1609,6 +1643,58 @@
 
 }	/* end of mgsl_isr_receive_dma() */
 
+/* mgsl_isr_transmit_dma()
+ *
+ *	This function services a transmit DMA channel interrupt.
+ *
+ *	For this driver there is one source of transmit DMA interrupts
+ *	as identified in the Transmit DMA Mode Register (TDMR):
+ *
+ *     	BIT2  EOB       End of Buffer. This interrupt occurs when a
+ *     			transmit DMA buffer has been emptied.
+ *
+ *     	The driver maintains enough transmit DMA buffers to hold at least
+ *     	one max frame size transmit frame. When operating in a buffered
+ *     	transmit mode, there may be enough transmit DMA buffers to hold at
+ *     	least two or more max frame size frames. On an EOB condition,
+ *     	determine if there are any queued transmit buffers and copy into
+ *     	transmit DMA buffers if we have room.
+ *
+ * Arguments:		info		pointer to device instance data
+ * Return Value:	None
+ */
+void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+{
+	u16 status;
+
+	/* clear interrupt pending and IUS bit for Tx DMA IRQ */
+	usc_OutDmaReg(info, CDIR, BIT8+BIT0 );
+
+	/* Read the transmit DMA status to identify interrupt type. */
+	/* This also clears the status bits. */
+
+	status = usc_InDmaReg( info, TDMR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n",
+			__FILE__,__LINE__,info->device_name,status);
+
+	if ( status & BIT2 ) {
+		--info->tx_dma_buffers_used;
+
+		/* if there are transmit frames queued,
+		 *  try to load the next one
+		 */
+		if ( load_next_tx_holding_buffer(info) ) {
+			/* if call returns non-zero value, we have
+			 * at least one free tx holding buffer
+			 */
+			info->pending_bh |= BH_TRANSMIT;
+		}
+	}
+
+}	/* end of mgsl_isr_transmit_dma() */
+
 /* mgsl_interrupt()
  * 
  * 	Interrupt service routine entry point.
@@ -1652,6 +1738,8 @@
 		/* Dispatch interrupt vector */
 		if ( UscVector )
 			(*UscIsrTable[UscVector])(info);
+		else if ( (DmaVector&(BIT10|BIT9)) == BIT10)
+			mgsl_isr_transmit_dma(info);
 		else
 			mgsl_isr_receive_dma(info);
 
@@ -1818,7 +1906,9 @@
 	usc_stop_transmitter(info);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	
-	if (info->params.mode == MGSL_MODE_HDLC || info->netcount)
+	if (info->params.mode == MGSL_MODE_HDLC ||
+	    info->params.mode == MGSL_MODE_RAW ||
+	    info->netcount)
 		usc_set_sync_mode(info);
 	else
 		usc_set_async_mode(info);
@@ -1970,8 +2060,7 @@
 
 	spin_lock_irqsave(&info->irq_spinlock,flags);
 	
-	if ( (info->params.mode != MGSL_MODE_HDLC) || 
-	     !info->tx_active ) {
+	if ( (info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active ) {
 	
 		if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
 			info->xmit_buf[info->xmit_head++] = ch;
@@ -2015,8 +2104,8 @@
 	spin_lock_irqsave(&info->irq_spinlock,flags);
 	
 	if (!info->tx_active) {
-		if ( (info->params.mode == MGSL_MODE_HDLC) &&
-			info->xmit_cnt ) {
+		if ( (info->params.mode == MGSL_MODE_HDLC ||
+			info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) {
 			/* operating in synchronous (frame oriented) mode */
 			/* copy data from circular xmit_buf to */
 			/* transmit DMA buffer. */
@@ -2060,11 +2149,51 @@
 	if (!tty || !info->xmit_buf || !tmp_buf)
 		goto cleanup;
 
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+			info->params.mode == MGSL_MODE_RAW ) {
+		/* operating in synchronous (frame oriented) mode */
 		/* operating in synchronous (frame oriented) mode */
-
 		if (info->tx_active) {
-			ret = 0; goto cleanup; 
+
+			if ( info->params.mode == MGSL_MODE_HDLC ) {
+				ret = 0;
+				goto cleanup;
+			}
+			/* transmitter is actively sending data -
+			 * if we have multiple transmit dma and
+			 * holding buffers, attempt to queue this
+			 * frame for transmission at a later time.
+			 */
+			if (info->tx_holding_count >= info->num_tx_holding_buffers ) {
+				/* no tx holding buffers available */
+				ret = 0;
+				goto cleanup;
+			}
+
+			/* queue transmit frame request */
+			ret = count;
+			if (from_user) {
+				down(&tmp_buf_sem);
+				COPY_FROM_USER(err,tmp_buf, buf, count);
+				if (err) {
+					if ( debug_level >= DEBUG_LEVEL_INFO )
+						printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n",
+							__FILE__,__LINE__,info->device_name);
+					ret = -EFAULT;
+				} else
+					save_tx_buffer_request(info,tmp_buf,count);
+				up(&tmp_buf_sem);
+			}
+			else
+				save_tx_buffer_request(info,buf,count);
+
+			/* if we have sufficient tx dma buffers,
+			 * load the next buffered tx request
+			 */
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			load_next_tx_holding_buffer(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			goto cleanup;
 		}
 	
 		/* if operating in HDLC LoopMode and the adapter  */
@@ -2200,7 +2329,8 @@
 		printk("%s(%d):mgsl_write_room(%s)=%d\n",
 			 __FILE__,__LINE__, info->device_name,ret );
 			 
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
 		/* operating in synchronous (frame oriented) mode */
 		if ( info->tx_active )
 			return 0;
@@ -2234,10 +2364,11 @@
 		printk("%s(%d):mgsl_chars_in_buffer(%s)=%d\n",
 			 __FILE__,__LINE__, info->device_name,info->xmit_cnt );
 			 
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
 		/* operating in synchronous (frame oriented) mode */
 		if ( info->tx_active )
-			return info->tx_buffer_list[0].rcc;
+			return info->max_frame_size;
 		else
 			return 0;
 	}
@@ -2627,11 +2758,11 @@
  	unsigned long flags;
 	int s;
 	int rc=0;
-	u16 regval;
 	struct mgsl_icount cprev, cnow;
-	int events = 0;
+	int events;
 	int mask;
-	struct	_input_signal_events signal_events_prev, signal_events_now;
+	struct	_input_signal_events oldsigs, newsigs;
+	DECLARE_WAITQUEUE(wait, current);
 
 	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
 	if (rc) {
@@ -2644,114 +2775,99 @@
 
 	spin_lock_irqsave(&info->irq_spinlock,flags);
 
+	/* return immediately if state matches requested events */
 	usc_get_serial_signals(info);
 	s = info->serial_signals;
+	events = mask &
+		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
+ 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
+		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
+		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
+	if (events) {
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		goto exit;
+	}
 
-	/* note the counters on entry */
+	/* save current irq counts */
 	cprev = info->icount;
-	signal_events_prev = info->input_signal_events;
+	oldsigs = info->input_signal_events;
 	
-	if (mask & MgslEvent_ExitHuntMode) {
-		/* enable exit hunt mode IRQ */
-		regval = usc_InReg(info,RICR);
-		if (!(regval & RXSTATUS_EXITED_HUNT))
-			usc_OutReg(info, RICR, regval | RXSTATUS_EXITED_HUNT);
+	/* enable hunt and idle irqs if needed */
+	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+		u16 oldreg = usc_InReg(info,RICR);
+		u16 newreg = oldreg +
+			 (mask & MgslEvent_ExitHuntMode ? RXSTATUS_EXITED_HUNT:0) +
+			 (mask & MgslEvent_IdleReceived ? RXSTATUS_IDLE_RECEIVED:0);
+		if (oldreg != newreg)
+			usc_OutReg(info, RICR, newreg);
 	}
 	
-	if (mask & MgslEvent_IdleReceived) {
-		/* enable idle mode received IRQ */
-		regval = usc_InReg(info,RICR);
-		if (!(regval & RXSTATUS_IDLE_RECEIVED))
-			usc_OutReg(info, RICR, regval | RXSTATUS_IDLE_RECEIVED);
-	}
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&info->event_wait_q, &wait);
 	
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
-	/* Determine if any user requested events for input signals is currently TRUE */
-	
-	events |= (mask & ((s & SerialSignal_DSR) ?
-			MgslEvent_DsrActive:MgslEvent_DsrInactive));
-
-	events |= (mask & ((s & SerialSignal_DCD) ?
-			MgslEvent_DcdActive:MgslEvent_DcdInactive));
-		
-	events |= (mask & ((s & SerialSignal_CTS) ?
-			MgslEvent_CtsActive:MgslEvent_CtsInactive));
-		
-	events |= (mask & ((s & SerialSignal_RI) ?
-			MgslEvent_RiActive:MgslEvent_RiInactive));
-	
 
-	while(!events) {
-		/* sleep until event occurs */
-		interruptible_sleep_on(&info->event_wait_q);
-		
-		/* see if a signal woke us */
+	for(;;) {
+		schedule();
 		if (signal_pending(current)) {
 			rc = -ERESTARTSYS;
 			break;
 		}
 			
+		/* get current irq counts */
 		spin_lock_irqsave(&info->irq_spinlock,flags);
-
-		/* get icount and serial signal states */
 		cnow = info->icount;
-		signal_events_now = info->input_signal_events;
+		newsigs = info->input_signal_events;
+		set_current_state(TASK_INTERRUPTIBLE);
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-		if (signal_events_now.dsr_up != signal_events_prev.dsr_up && 
-				mask & MgslEvent_DsrActive )
-			events |= MgslEvent_DsrActive;
-		
-		if (signal_events_now.dsr_down != signal_events_prev.dsr_down && 
-				mask & MgslEvent_DsrInactive )
-			events |= MgslEvent_DsrInactive;
-
-		if (signal_events_now.dcd_up != signal_events_prev.dcd_up &&
-				mask & MgslEvent_DcdActive )
-			events |= MgslEvent_DcdActive;
-		
-		if (signal_events_now.dcd_down != signal_events_prev.dcd_down &&
-				mask & MgslEvent_DcdInactive )
-			events |= MgslEvent_DcdInactive;
-		
-		if (signal_events_now.cts_up != signal_events_prev.cts_up &&
-				mask & MgslEvent_CtsActive )
-			events |= MgslEvent_CtsActive;
-		
-		if (signal_events_now.cts_down != signal_events_prev.cts_down &&
-				mask & MgslEvent_CtsInactive )
-			events |= MgslEvent_CtsInactive;
-		
-		if (signal_events_now.ri_up != signal_events_prev.ri_up &&
-				mask & MgslEvent_RiActive )
-			events |= MgslEvent_RiActive;
-		
-		if (signal_events_now.ri_down != signal_events_prev.ri_down &&
-				mask & MgslEvent_RiInactive )
-			events |= MgslEvent_RiInactive;
-		
-		if (cnow.exithunt != cprev.exithunt)
-			events |= (mask & MgslEvent_ExitHuntMode);
+		/* if no change, wait aborted for some reason */
+		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
+		    newsigs.dsr_down == oldsigs.dsr_down &&
+		    newsigs.dcd_up   == oldsigs.dcd_up   &&
+		    newsigs.dcd_down == oldsigs.dcd_down &&
+		    newsigs.cts_up   == oldsigs.cts_up   &&
+		    newsigs.cts_down == oldsigs.cts_down &&
+		    newsigs.ri_up    == oldsigs.ri_up    &&
+		    newsigs.ri_down  == oldsigs.ri_down  &&
+		    cnow.exithunt    == cprev.exithunt   &&
+		    cnow.rxidle      == cprev.rxidle) {
+			rc = -EIO;
+			break;
+		}
 
-		if (cnow.rxidle != cprev.rxidle)
-			events |= (mask & MgslEvent_IdleReceived);
+		events = mask &
+			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
+			(newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
+			(newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
+			(newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
+			(newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
+			(newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
+			(newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
+			(newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
+			(cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
+			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
+		if (events)
+			break;
 		
 		cprev = cnow;
-		signal_events_prev = signal_events_now;
+		oldsigs = newsigs;
 	}
 	
+	remove_wait_queue(&info->event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+
 	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
 		spin_lock_irqsave(&info->irq_spinlock,flags);
 		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
-			regval = usc_InReg(info,RICR);
-			usc_OutReg(info, RICR, regval & 
+			usc_OutReg(info, RICR, usc_InReg(info,RICR) &
 				~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED));
 		}
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	}
-
+exit:
 	if ( rc == 0 )
 		PUT_USER(rc, events, mask_ptr);
 		
@@ -2759,6 +2875,56 @@
 	
 }	/* end of mgsl_wait_event() */
 
+static int modem_input_wait(struct mgsl_struct *info,int arg)
+{
+ 	unsigned long flags;
+	int rc;
+	struct mgsl_icount cprev, cnow;
+	DECLARE_WAITQUEUE(wait, current);
+
+	/* save current irq counts */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	cprev = info->icount;
+	add_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+
+		/* get new irq counts */
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		cnow = info->icount;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+			rc = -EIO;
+			break;
+		}
+
+		/* check for change in caller specified modem input */
+		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)) {
+			rc = 0;
+			break;
+		}
+
+		cprev = cnow;
+	}
+	remove_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+	return rc;
+}
+
 /* get_modem_info()
  * 
  * 	Read the state of the serial control and
@@ -2926,7 +3092,7 @@
 int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
 {
 	int error;
-	struct mgsl_icount cprev, cnow;	/* kernel counter temps */
+	struct mgsl_icount cnow;	/* kernel counter temps */
 	struct serial_icounter_struct *p_cuser;	/* user space */
 	unsigned long flags;
 	
@@ -2961,37 +3127,12 @@
 			while(MOD_IN_USE)
 				MOD_DEC_USE_COUNT;
 			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
+
+		/* Wait for modem input (DCD,RI,DSR,CTS) change
+		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
 		 */
 		case TIOCMIWAIT:
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			/* note the counters on entry */
-			cprev = info->icount;
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			while (1) {
-				interruptible_sleep_on(&info->status_event_wait_q);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				save_flags(flags); cli();
-				cnow = info->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 */
+			return modem_input_wait(info,(int)arg);
 
 		/* 
 		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
@@ -3243,7 +3384,8 @@
 	if (timeout)
 		char_time = MIN(char_time, timeout);
 		
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
 		while (info->tx_active) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(char_time);
@@ -3601,7 +3743,8 @@
 	if (info->serial_signals & SerialSignal_RI)
 		strcat(stat_buf, "|RI");
 
-	if (info->params.mode == MGSL_MODE_HDLC) {
+	if (info->params.mode == MGSL_MODE_HDLC ||
+	    info->params.mode == MGSL_MODE_RAW ) {
 		ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d",
 			      info->icount.txok, info->icount.rxok);
 		if (info->icount.txunder)
@@ -3742,15 +3885,15 @@
 		 *
 		 * This leaves 62 4K pages.
 		 *
-		 * The next N pages are used for a transmit frame. We
-		 * reserve enough 4K page blocks to hold the configured
-		 * MaxFrameSize
+		 * The next N pages are used for transmit frame(s). We
+		 * reserve enough 4K page blocks to hold the required
+		 * number of transmit dma buffers (num_tx_dma_buffers),
+		 * each of MaxFrameSize size.
 		 *
 		 * Of the remaining pages (62-N), determine how many can
 		 * be used to receive full MaxFrameSize inbound frames
 		 */
-		
-		info->tx_buffer_count = BuffersPerFrame;
+		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
 		info->rx_buffer_count = 62 - info->tx_buffer_count;
 	} else {
 		/* Calculate the number of PAGE_SIZE buffers needed for */
@@ -3763,7 +3906,7 @@
 		/* End of List condition if all receive buffers are used when */
 		/* using linked list DMA buffers. */
 
-		info->tx_buffer_count = BuffersPerFrame;
+		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
 		info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
 		
 		/* 
@@ -3783,12 +3926,14 @@
 	if ( mgsl_alloc_buffer_list_memory( info ) < 0 ||
 		  mgsl_alloc_frame_memory(info, info->rx_buffer_list, info->rx_buffer_count) < 0 || 
 		  mgsl_alloc_frame_memory(info, info->tx_buffer_list, info->tx_buffer_count) < 0 || 
-		  mgsl_alloc_intermediate_rxbuffer_memory(info) < 0 ) {
+		  mgsl_alloc_intermediate_rxbuffer_memory(info) < 0  ||
+		  mgsl_alloc_intermediate_txbuffer_memory(info) < 0 ) {
 		printk("%s(%d):Can't allocate DMA buffer memory\n",__FILE__,__LINE__);
 		return -ENOMEM;
 	}
 	
 	mgsl_reset_rx_dma_buffers( info );
+  	mgsl_reset_tx_dma_buffers( info );
 
 	return 0;
 
@@ -4044,6 +4189,149 @@
 
 }	/* end of mgsl_free_intermediate_rxbuffer_memory() */
 
+/*
+ * mgsl_alloc_intermediate_txbuffer_memory()
+ *
+ * 	Allocate intermdiate transmit buffer(s) large enough to hold max_frame_size.
+ * 	This buffer is used to load transmit frames into the adapter's dma transfer
+ * 	buffers when there is sufficient space.
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ *
+ * Return Value:	0 if success, otherwise -ENOMEM
+ */
+int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
+{
+	int i;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s %s(%d)  allocating %d tx holding buffers\n",
+				info->device_name, __FILE__,__LINE__,info->num_tx_holding_buffers);
+
+	memset(info->tx_holding_buffers,0,sizeof(info->tx_holding_buffers));
+
+	for ( i=0; i<info->num_tx_holding_buffers; ++i) {
+		info->tx_holding_buffers[i].buffer =
+			kmalloc(info->max_frame_size, GFP_KERNEL);
+		if ( info->tx_holding_buffers[i].buffer == NULL )
+			return -ENOMEM;
+	}
+
+	return 0;
+
+}	/* end of mgsl_alloc_intermediate_txbuffer_memory() */
+
+/*
+ * mgsl_free_intermediate_txbuffer_memory()
+ *
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ *
+ * Return Value:	None
+ */
+void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
+{
+	int i;
+
+	for ( i=0; i<info->num_tx_holding_buffers; ++i ) {
+		if ( info->tx_holding_buffers[i].buffer ) {
+				kfree(info->tx_holding_buffers[i].buffer);
+				info->tx_holding_buffers[i].buffer=NULL;
+		}
+	}
+
+	info->get_tx_holding_index = 0;
+	info->put_tx_holding_index = 0;
+	info->tx_holding_count = 0;
+
+}	/* end of mgsl_free_intermediate_txbuffer_memory() */
+
+
+/*
+ * load_next_tx_holding_buffer()
+ *
+ * attempts to load the next buffered tx request into the
+ * tx dma buffers
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ *
+ * Return Value:	1 if next buffered tx request loaded
+ * 			into adapter's tx dma buffer,
+ * 			0 otherwise
+ */
+int load_next_tx_holding_buffer(struct mgsl_struct *info)
+{
+	int ret = 0;
+
+	if ( info->tx_holding_count ) {
+		/* determine if we have enough tx dma buffers
+		 * to accomodate the next tx frame
+		 */
+		struct tx_holding_buffer *ptx =
+			&info->tx_holding_buffers[info->get_tx_holding_index];
+		int num_free = num_free_tx_dma_buffers(info);
+		int num_needed = ptx->buffer_size / DMABUFFERSIZE;
+		if ( ptx->buffer_size % DMABUFFERSIZE )
+			++num_needed;
+
+		if (num_needed <= num_free) {
+			info->xmit_cnt = ptx->buffer_size;
+			mgsl_load_tx_dma_buffer(info,ptx->buffer,ptx->buffer_size);
+
+			--info->tx_holding_count;
+			if ( ++info->get_tx_holding_index >= info->num_tx_holding_buffers)
+				info->get_tx_holding_index=0;
+
+			/* restart transmit timer */
+			del_timer(&info->tx_timer);
+			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			add_timer(&info->tx_timer);
+
+			ret = 1;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * save_tx_buffer_request()
+ *
+ * attempt to store transmit frame request for later transmission
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ * 	Buffer		pointer to buffer containing frame to load
+ * 	BufferSize	size in bytes of frame in Buffer
+ *
+ * Return Value:	1 if able to store, 0 otherwise
+ */
+int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
+{
+	struct tx_holding_buffer *ptx;
+
+	if ( info->tx_holding_count >= info->num_tx_holding_buffers ) {
+		return 0;	        /* all buffers in use */
+	}
+
+	ptx = &info->tx_holding_buffers[info->put_tx_holding_index];
+	ptx->buffer_size = BufferSize;
+	memcpy( ptx->buffer, Buffer, BufferSize);
+
+	++info->tx_holding_count;
+	if ( ++info->put_tx_holding_index >= info->num_tx_holding_buffers)
+		info->put_tx_holding_index=0;
+
+	return 1;
+}
+
 int mgsl_claim_resources(struct mgsl_struct *info)
 {
 	if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) {
@@ -4120,7 +4408,7 @@
 	return 0;
 errout:
 	mgsl_release_resources(info);
-	return ENODEV;
+	return -ENODEV;
 
 }	/* end of mgsl_claim_resources() */
 
@@ -4141,6 +4429,7 @@
 	}
 	mgsl_free_dma_buffers(info);
 	mgsl_free_intermediate_rxbuffer_memory(info);
+     	mgsl_free_intermediate_txbuffer_memory(info);
 	
 	if ( info->io_addr_requested ) {
 		release_region(info->io_base,info->io_addr_size);
@@ -4187,6 +4476,20 @@
 		if (maxframe[info->line])
 			info->max_frame_size = maxframe[info->line];
 		info->dosyncppp = dosyncppp[info->line];
+
+		if (txdmabufs[info->line]) {
+			info->num_tx_dma_buffers = txdmabufs[info->line];
+			if (info->num_tx_dma_buffers < 1)
+				info->num_tx_dma_buffers = 1;
+		}
+
+		if (txholdbufs[info->line]) {
+			info->num_tx_holding_buffers = txholdbufs[info->line];
+			if (info->num_tx_holding_buffers < 1)
+				info->num_tx_holding_buffers = 1;
+			else if (info->num_tx_holding_buffers > MAX_TX_HOLDING_BUFFERS)
+				info->num_tx_holding_buffers = MAX_TX_HOLDING_BUFFERS;
+		}
 	}
 
 	mgsl_device_count++;
@@ -4255,6 +4558,8 @@
 		spin_lock_init(&info->netlock);
 		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
 		info->idle_mode = HDLC_TXIDLE_FLAGS;		
+		info->num_tx_dma_buffers = 1;
+		info->num_tx_holding_buffers = 0;
 	}
 	
 	return info;
@@ -4432,6 +4737,7 @@
 	unsigned long flags;
 	int rc;
 	struct mgsl_struct *info;
+	struct mgsl_struct *tmp;
 
 	printk("Unloading %s: version %s\n", driver_name, driver_version);
 	save_flags(flags);
@@ -4451,7 +4757,9 @@
 			mgsl_sppp_delete(info);
 #endif
 		mgsl_release_resources(info);
+		tmp = info;
 		info = info->next_device;
+		kfree(tmp);
 	}
 	
 	if (tmp_buf) {
@@ -4691,6 +4999,27 @@
 		 *
 		 * 0000 0110 0000 0110 = 0x0606
 		 */
+		if (info->params.mode == MGSL_MODE_RAW) {
+			RegValue = 0x0001;		/* Set Receive mode = external sync */
+
+			usc_OutReg( info, IOCR,		/* Set IOCR DCD is RxSync Detect Input */
+				(unsigned short)((usc_InReg(info, IOCR) & ~(BIT13|BIT12)) | BIT12));
+
+			/*
+			 * TxSubMode:
+			 * 	CMR <15>		0	Don't send CRC on Tx Underrun
+			 * 	CMR <14>		x	undefined
+			 * 	CMR <13>		0	Send preamble before openning sync
+			 * 	CMR <12>		0	Send 8-bit syncs, 1=send Syncs per TxLength
+			 *
+			 * TxMode:
+			 * 	CMR <11-8)	0100	MonoSync
+			 *
+			 * 	0x00 0100 xxxx xxxx  04xx
+			 */
+			RegValue |= 0x0400;
+		}
+		else {
 
 		RegValue = 0x0606;
 
@@ -4700,12 +5029,14 @@
 			RegValue |= BIT15;
 		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
 			RegValue |= BIT15 + BIT14;
+		}
 
 		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
 			RegValue |= BIT13;
 	}
 
-	if ( info->params.flags & HDLC_FLAG_SHARE_ZERO )
+	if ( info->params.mode == MGSL_MODE_HDLC &&
+		(info->params.flags & HDLC_FLAG_SHARE_ZERO) )
 		RegValue |= BIT12;
 
 	if ( info->params.addr_filter != 0xff )
@@ -4745,15 +5076,13 @@
 	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
 	}
 
-	if ( info->params.crc_type == HDLC_CRC_16_CCITT )
+	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
 		RegValue |= BIT9;
-	else if ( info->params.crc_type == HDLC_CRC_32_CCITT )
+	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
 		RegValue |= ( BIT12 | BIT10 | BIT9 );
 
 	usc_OutReg( info, RMR, RegValue );
 
-
- 
 	/* Set the Receive count Limit Register (RCLR) to 0xffff. */
 	/* When an opening flag of an SDLC frame is recognized the */
 	/* Receive Character count (RCC) is loaded with the value in */
@@ -4822,9 +5151,9 @@
 	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
 	}
 
-	if ( info->params.crc_type == HDLC_CRC_16_CCITT )
+	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
 		RegValue |= BIT9 + BIT8;
-	else if ( info->params.crc_type == HDLC_CRC_32_CCITT )
+	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
 		RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8);
 
 	usc_OutReg( info, TMR, RegValue );
@@ -5495,7 +5824,8 @@
 	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
 	usc_RTCmd( info, RTCmd_PurgeRxFifo );
 
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
 		/* DMA mode Transfers */
 		/* Program the DMA controller. */
 		/* Enable the DMA controller end of buffer interrupt. */
@@ -5585,8 +5915,14 @@
 			/* Transmit DMA buffer is loaded, so program USC */
 			/* to send the frame contained in the buffers.	 */
 
+			FrameSize = info->tx_buffer_list[info->start_tx_dma_buffer].rcc;
 
-			FrameSize = info->tx_buffer_list[0].rcc;
+			/* if operating in Raw sync mode, reset the rcc component
+			 * of the tx dma buffer entry, otherwise, the serial controller
+			 * will send a closing sync char after this count.
+			 */
+	    		if ( info->params.mode == MGSL_MODE_RAW )
+				info->tx_buffer_list[info->start_tx_dma_buffer].rcc = 0;
 
 			/* Program the Transmit Character Length Register (TCLR) */
 			/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
@@ -5595,7 +5931,7 @@
 			usc_RTCmd( info, RTCmd_PurgeTxFifo );
 
 			/* Program the address of the 1st DMA Buffer Entry in linked list */
-			phys_addr = info->tx_buffer_list[0].phys_entry;
+			phys_addr = info->tx_buffer_list[info->start_tx_dma_buffer].phys_entry;
 			usc_OutDmaReg( info, NTARL, (u16)phys_addr );
 			usc_OutDmaReg( info, NTARU, (u16)(phys_addr >> 16) );
 
@@ -5603,6 +5939,19 @@
 			usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
 			usc_EnableInterrupts( info, TRANSMIT_STATUS );
 
+			if ( info->params.mode == MGSL_MODE_RAW &&
+					info->num_tx_dma_buffers > 1 ) {
+			   /* When running external sync mode, attempt to 'stream' transmit  */
+			   /* by filling tx dma buffers as they become available. To do this */
+			   /* we need to enable Tx DMA EOB Status interrupts :               */
+			   /*                                                                */
+			   /* 1. Arm End of Buffer (EOB) Transmit DMA Interrupt (BIT2 of TDIAR) */
+			   /* 2. Enable Transmit DMA Interrupts (BIT0 of DICR) */
+
+			   usc_OutDmaReg( info, TDIAR, BIT2|BIT3 );
+			   usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT0) );
+			}
+
 			/* Initialize Transmit DMA Channel */
 			usc_DmaCmd( info, DmaCmd_InitTxChannel );
 			
@@ -6026,6 +6375,9 @@
 void usc_loopback_frame( struct mgsl_struct *info )
 {
 	int i;
+	unsigned long oldmode = info->params.mode;
+
+	info->params.mode = MGSL_MODE_HDLC;
 	
 	usc_DisableMasterIrqBit( info );
 
@@ -6079,6 +6431,8 @@
 
 	usc_EnableMasterIrqBit(info);
 
+	info->params.mode = oldmode;
+
 }	/* end of usc_loopback_frame() */
 
 /* usc_set_sync_mode()	Programs the USC for SDLC communications.
@@ -6130,6 +6484,38 @@
 	info->tcsr_value += usc_idle_mode;
 	usc_OutReg(info, TCSR, info->tcsr_value);
 
+	/*
+	 * if SyncLink WAN adapter is running in external sync mode, the
+	 * transmitter has been set to Monosync in order to try to mimic
+	 * a true raw outbound bit stream. Monosync still sends an open/close
+	 * sync char at the start/end of a frame. Try to match those sync
+	 * patterns to the idle mode set here
+	 */
+	if ( info->params.mode == MGSL_MODE_RAW ) {
+		unsigned char syncpat = 0;
+		switch( info->idle_mode ) {
+		case HDLC_TXIDLE_FLAGS:
+			syncpat = 0x7e;
+			break;
+		case HDLC_TXIDLE_ALT_ZEROS_ONES:
+			syncpat = 0x55;
+			break;
+		case HDLC_TXIDLE_ZEROS:
+		case HDLC_TXIDLE_SPACE:
+			syncpat = 0x00;
+			break;
+		case HDLC_TXIDLE_ONES:
+		case HDLC_TXIDLE_MARK:
+			syncpat = 0xff;
+			break;
+		case HDLC_TXIDLE_ALT_MARK_SPACE:
+			syncpat = 0xaa;
+			break;
+		}
+
+		usc_SetTransmitSyncChars(info,syncpat,syncpat);
+	}
+
 }	/* end of usc_set_txidle() */
 
 /* usc_get_serial_signals()
@@ -6307,6 +6693,48 @@
  */
 
 /*
+ * mgsl_reset_tx_dma_buffers()
+ *
+ * 	Set the count for all transmit buffers to 0 to indicate the
+ * 	buffer is available for use and set the current buffer to the
+ * 	first buffer. This effectively makes all buffers free and
+ * 	discards any data in buffers.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
+{
+	unsigned int i;
+
+	for ( i = 0; i < info->tx_buffer_count; i++ ) {
+		*((unsigned long *)&(info->tx_buffer_list[i].count)) = 0;
+	}
+
+	info->current_tx_buffer = 0;
+	info->start_tx_dma_buffer = 0;
+	info->tx_dma_buffers_used = 0;
+
+	info->get_tx_holding_index = 0;
+	info->put_tx_holding_index = 0;
+	info->tx_holding_count = 0;
+
+}	/* end of mgsl_reset_tx_dma_buffers() */
+
+/*
+ * num_free_tx_dma_buffers()
+ *
+ * 	returns the number of free tx dma buffers available
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	number of free tx dma buffers
+ */
+int num_free_tx_dma_buffers(struct mgsl_struct *info)
+{
+	return info->tx_buffer_count - info->tx_dma_buffers_used;
+}
+
+/*
  * mgsl_reset_rx_dma_buffers()
  * 
  * 	Set the count for all receive buffers to DMABUFFERSIZE
@@ -6392,10 +6820,11 @@
 	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
 	unsigned short status;
 	DMABUFFERENTRY *pBufEntry;
-	unsigned int framesize;
+	unsigned int framesize = 0;
 	int ReturnCode = 0;
 	unsigned long flags;
 	struct tty_struct *tty = info->tty;
+	int return_frame = 0;
 	
 	/*
 	 * current_rx_buffer points to the 1st buffer of the next available
@@ -6451,14 +6880,20 @@
 			info->icount.rxabort++;
 		else if ( status & RXSTATUS_OVERRUN )
 			info->icount.rxover++;
-		else 
+		else {
 			info->icount.rxcrc++;
+			if ( info->params.crc_type & HDLC_CRC_RETURN_EX )
+				return_frame = 1;
+		}
 		framesize = 0;
 #ifdef CONFIG_SYNCLINK_SYNCPPP
 		info->netstats.rx_errors++;
 		info->netstats.rx_frame_errors++;
 #endif
-	} else {
+	} else
+		return_frame = 1;
+
+	if ( return_frame ) {
 		/* receive frame has no errors, get frame size.
 		 * The frame size is the starting value of the RCC (which was
 		 * set to 0xffff) minus the ending value of the RCC (decremented
@@ -6483,7 +6918,9 @@
 			MIN(framesize,DMABUFFERSIZE),0);	
 		
 	if (framesize) {
-		if (framesize > info->max_frame_size)
+		if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
+				((framesize+1) > info->max_frame_size) ) ||
+			(framesize > info->max_frame_size) )
 			info->icount.rxlong++;
 		else {
 			/* copy dma buffer(s) to contiguous intermediate buffer */
@@ -6491,6 +6928,7 @@
 			int index = StartIndex;
 			unsigned char *ptmp = info->intermediate_rxbuffer;
 
+			if ( !(status & RXSTATUS_CRC_ERROR))
 			info->icount.rxok++;
 			
 			while(copy_count) {
@@ -6509,6 +6947,18 @@
 					index = 0;
 			}
 
+			if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) {
+				++framesize;
+				*ptmp = (status & RXSTATUS_CRC_ERROR ?
+						RX_CRC_ERROR :
+						RX_OK);
+
+				if ( debug_level >= DEBUG_LEVEL_DATA )
+					printk("%s(%d):mgsl_get_rx_frame(%s) rx frame status=%d\n",
+						__FILE__,__LINE__,info->device_name,
+						*ptmp);
+			}
+
 #ifdef CONFIG_SYNCLINK_SYNCPPP
 			if (info->netcount) {
 				/* pass frame to syncppp device */
@@ -6518,6 +6968,7 @@
 #endif
 			{
 				/* Call the line discipline receive callback directly. */
+				if ( tty && tty->ldisc.receive_buf )
 				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
 			}
 		}
@@ -6547,6 +6998,180 @@
 
 }	/* end of mgsl_get_rx_frame() */
 
+/* mgsl_get_raw_rx_frame()
+ *
+ *     	This function attempts to return a received frame from the
+ *	receive DMA buffers when running in external loop mode. In this mode,
+ *	we will return at most one DMABUFFERSIZE frame to the application.
+ *	The USC receiver is triggering off of DCD going active to start a new
+ *	frame, and DCD going inactive to terminate the frame (similar to
+ *	processing a closing flag character).
+ *
+ *	In this routine, we will return DMABUFFERSIZE "chunks" at a time.
+ *	If DCD goes inactive, the last Rx DMA Buffer will have a non-zero
+ * 	status field and the RCC field will indicate the length of the
+ *	entire received frame. We take this RCC field and get the modulus
+ *	of RCC and DMABUFFERSIZE to determine if number of bytes in the
+ *	last Rx DMA buffer and return that last portion of the frame.
+ *
+ * Arguments:	 	info	pointer to device extension
+ * Return Value:	1 if frame returned, otherwise 0
+ */
+int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+{
+	unsigned int CurrentIndex, NextIndex;
+	unsigned short status;
+	DMABUFFERENTRY *pBufEntry;
+	unsigned int framesize = 0;
+	int ReturnCode = 0;
+	unsigned long flags;
+	struct tty_struct *tty = info->tty;
+
+	/*
+ 	 * current_rx_buffer points to the 1st buffer of the next available
+	 * receive frame. The status field is set by the 16C32 after
+	 * completing a receive frame. If the status field of this buffer
+	 * is zero, either the USC is still filling this buffer or this
+	 * is one of a series of buffers making up a received frame.
+	 *
+	 * If the count field of this buffer is zero, the USC is either
+	 * using this buffer or has used this buffer. Look at the count
+	 * field of the next buffer. If that next buffer's count is
+	 * non-zero, the USC is still actively using the current buffer.
+	 * Otherwise, if the next buffer's count field is zero, the
+	 * current buffer is complete and the USC is using the next
+	 * buffer.
+	 */
+	CurrentIndex = NextIndex = info->current_rx_buffer;
+	++NextIndex;
+	if ( NextIndex == info->rx_buffer_count )
+		NextIndex = 0;
+
+	if ( info->rx_buffer_list[CurrentIndex].status != 0 ||
+		(info->rx_buffer_list[CurrentIndex].count == 0 &&
+			info->rx_buffer_list[NextIndex].count == 0)) {
+		/*
+	 	 * Either the status field of this dma buffer is non-zero
+		 * (indicating the last buffer of a receive frame) or the next
+	 	 * buffer is marked as in use -- implying this buffer is complete
+		 * and an intermediate buffer for this received frame.
+	 	 */
+
+		status = info->rx_buffer_list[CurrentIndex].status;
+
+		if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
+				RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
+			if ( status & RXSTATUS_SHORT_FRAME )
+				info->icount.rxshort++;
+			else if ( status & RXSTATUS_ABORT )
+				info->icount.rxabort++;
+			else if ( status & RXSTATUS_OVERRUN )
+				info->icount.rxover++;
+			else
+				info->icount.rxcrc++;
+			framesize = 0;
+		} else {
+			/*
+			 * A receive frame is available, get frame size and status.
+			 *
+			 * The frame size is the starting value of the RCC (which was
+			 * set to 0xffff) minus the ending value of the RCC (decremented
+			 * once for each receive character) minus 2 or 4 for the 16-bit
+			 * or 32-bit CRC.
+			 *
+			 * If the status field is zero, this is an intermediate buffer.
+			 * It's size is 4K.
+			 *
+			 * If the DMA Buffer Entry's Status field is non-zero, the
+			 * receive operation completed normally (ie: DCD dropped). The
+			 * RCC field is valid and holds the received frame size.
+			 * It is possible that the RCC field will be zero on a DMA buffer
+			 * entry with a non-zero status. This can occur if the total
+			 * frame size (number of bytes between the time DCD goes active
+			 * to the time DCD goes inactive) exceeds 65535 bytes. In this
+			 * case the 16C32 has underrun on the RCC count and appears to
+			 * stop updating this counter to let us know the actual received
+			 * frame size. If this happens (non-zero status and zero RCC),
+			 * simply return the entire RxDMA Buffer
+			 */
+			if ( status ) {
+				/*
+				 * In the event that the final RxDMA Buffer is
+				 * terminated with a non-zero status and the RCC
+				 * field is zero, we interpret this as the RCC
+				 * having underflowed (received frame > 65535 bytes).
+				 *
+				 * Signal the event to the user by passing back
+				 * a status of RxStatus_CrcError returning the full
+				 * buffer and let the app figure out what data is
+				 * actually valid
+				 */
+				if ( info->rx_buffer_list[CurrentIndex].rcc )
+					framesize = RCLRVALUE - info->rx_buffer_list[CurrentIndex].rcc;
+				else
+					framesize = DMABUFFERSIZE;
+			}
+			else
+				framesize = DMABUFFERSIZE;
+		}
+
+		if ( framesize > DMABUFFERSIZE ) {
+			/*
+			 * if running in raw sync mode, ISR handler for
+			 * End Of Buffer events terminates all buffers at 4K.
+			 * If this frame size is said to be >4K, get the
+			 * actual number of bytes of the frame in this buffer.
+			 */
+			framesize = framesize % DMABUFFERSIZE;
+		}
+
+
+		if ( debug_level >= DEBUG_LEVEL_BH )
+			printk("%s(%d):mgsl_get_raw_rx_frame(%s) status=%04X size=%d\n",
+				__FILE__,__LINE__,info->device_name,status,framesize);
+
+		if ( debug_level >= DEBUG_LEVEL_DATA )
+			mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
+				MIN(framesize,DMABUFFERSIZE),0);
+
+		if (framesize) {
+			/* copy dma buffer(s) to contiguous intermediate buffer */
+			/* NOTE: we never copy more than DMABUFFERSIZE bytes	*/
+
+			pBufEntry = &(info->rx_buffer_list[CurrentIndex]);
+			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
+			info->icount.rxok++;
+
+			/* Call the line discipline receive callback directly. */
+			if ( tty && tty->ldisc.receive_buf )
+				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+		}
+
+		/* Free the buffers used by this frame. */
+		mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex );
+
+		ReturnCode = 1;
+	}
+
+
+	if ( info->rx_enabled && info->rx_overflow ) {
+		/* The receiver needs to restarted because of
+		 * a receive overflow (buffer or FIFO). If the
+		 * receive buffers are now empty, then restart receiver.
+		 */
+
+		if ( !info->rx_buffer_list[CurrentIndex].status &&
+			info->rx_buffer_list[CurrentIndex].count ) {
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			usc_start_receiver(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		}
+	}
+
+	return ReturnCode;
+
+}	/* end of mgsl_get_raw_rx_frame() */
+
 /* mgsl_load_tx_dma_buffer()
  * 
  * 	Load the transmit DMA buffer with the specified data.
@@ -6576,12 +7201,19 @@
 	 	info->cmr_value |= BIT13;			  
 	}
 		
+	/* begin loading the frame in the next available tx dma
+	 * buffer, remember it's starting location for setting
+	 * up tx dma operation
+	 */
+	i = info->current_tx_buffer;
+	info->start_tx_dma_buffer = i;
+
 	/* Setup the status and RCC (Frame Size) fields of the 1st */
 	/* buffer entry in the transmit DMA buffer list. */
 
-	info->tx_buffer_list[0].status = info->cmr_value & 0xf000;
-	info->tx_buffer_list[0].rcc    = BufferSize;
-	info->tx_buffer_list[0].count  = BufferSize;
+	info->tx_buffer_list[i].status = info->cmr_value & 0xf000;
+	info->tx_buffer_list[i].rcc    = BufferSize;
+	info->tx_buffer_list[i].count  = BufferSize;
 
 	/* Copy frame data from 1st source buffer to the DMA buffers. */
 	/* The frame data may span multiple DMA buffers. */
@@ -6590,6 +7222,9 @@
 		/* Get a pointer to next DMA buffer entry. */
 		pBufEntry = &info->tx_buffer_list[i++];
 			
+		if ( i == info->tx_buffer_count )
+			i=0;
+
 		/* Calculate the number of bytes that can be copied from */
 		/* the source buffer to this DMA buffer. */
 		if ( BufferSize > DMABUFFERSIZE )
@@ -6609,8 +7244,13 @@
 		/* Advance source pointer and reduce remaining data count. */
 		Buffer += Copycount;
 		BufferSize -= Copycount;
+
+		++info->tx_dma_buffers_used;
 	}
 
+	/* remember next available tx dma buffer */
+	info->current_tx_buffer = i;
+
 }	/* end of mgsl_load_tx_dma_buffer() */
 
 /*
@@ -6741,7 +7381,7 @@
 	unsigned int i;
 	char *TmpPtr;
 	BOOLEAN rc = TRUE;
-	unsigned short status;
+	unsigned short status=0;
 	unsigned long EndTime;
 	unsigned long flags;
 	MGSL_PARAMS tmp_params;
@@ -6998,7 +7638,7 @@
 		status = info->rx_buffer_list[0].status;
 
 		if ( status & (BIT8 + BIT3 + BIT1) ) {
-			/* receive error has occurred */
+			/* receive error has occured */
 			rc = FALSE;
 		} else {
 			if ( memcmp( info->tx_buffer_list[0].virt_addr ,
@@ -7219,7 +7859,9 @@
 	if ( debug_level >= DEBUG_LEVEL_INFO )
 		printk( "%s(%d):mgsl_tx_timeout(%s)\n",
 			__FILE__,__LINE__,info->device_name);
-	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
+	if(info->tx_active &&
+	   (info->params.mode == MGSL_MODE_HDLC ||
+	    info->params.mode == MGSL_MODE_RAW) ) {
 		info->icount.txtimeout++;
 	}
 	spin_lock_irqsave(&info->irq_spinlock,flags);
diff -u --recursive --new-file v2.4.4/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.4.4/linux/drivers/char/wdt.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/char/wdt.c	Sat May 19 17:43:05 2001
@@ -311,7 +311,7 @@
 	switch(cmd)
 	{
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 		case WDIOC_GETSUPPORT:
 			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/char/wdt285.c linux/drivers/char/wdt285.c
--- v2.4.4/linux/drivers/char/wdt285.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/wdt285.c	Sat May 19 17:43:05 2001
@@ -136,7 +136,7 @@
 	switch(cmd)
 	{
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 		case WDIOC_GETSUPPORT:
 			i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info));
 			if (i)
diff -u --recursive --new-file v2.4.4/linux/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- v2.4.4/linux/drivers/char/wdt_pci.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/char/wdt_pci.c	Sat May 19 17:43:05 2001
@@ -327,7 +327,7 @@
 	switch(cmd)
 	{
 		default:
-			return -ENOIOCTLCMD;
+			return -ENOTTY;
 		case WDIOC_GETSUPPORT:
 			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.4.4/linux/drivers/i2o/i2o_block.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/i2o/i2o_block.c	Tue May  1 16:12:51 2001
@@ -28,14 +28,16 @@
  *    		Support for larger I/Os through merge* functions 
  *       	(taken from DAC960 driver)
  *	Boji T Kannanthanam:
- *		Reduced the timeout during RAID 5 creation. 
- *		This is to prevent race condition when a RAID volume
- *		is created and immediately deleted.
+ *		Set the I2O Block devices to be detected in increasing 
+ *		order of TIDs during boot.
+ *		Search and set the I2O block device that we boot off from  as
+ *		the first device to be claimed (as /dev/i2o/hda)
+ *		Properly attach/detach I2O gendisk structure from the system
+ *		gendisk list. The I2O block devices now appear in 
+ * 		/proc/partitions.
  *
  *	To do:
  *		Serial number scanning to find duplicates for FC multipathing
- *		Remove the random timeout in the code needed for RAID 5
- *			volume creation.
  */
 
 #include <linux/major.h>
@@ -86,7 +88,8 @@
 #define I2OB_EVENT_MASK		(I2O_EVT_IND_BSA_VOLUME_LOAD |	\
 				 I2O_EVT_IND_BSA_VOLUME_UNLOAD | \
 				 I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ | \
-				 I2O_EVT_IND_BSA_CAPACITY_CHANGE)
+				 I2O_EVT_IND_BSA_CAPACITY_CHANGE | \
+				 I2O_EVT_IND_BSA_SCSI_SMART )
 
 
 /*
@@ -135,6 +138,8 @@
 	request_queue_t *req_queue;
 	int max_segments;
 	int done_flag;
+	int constipated;
+	int depth;
 };
 
 /*
@@ -164,7 +169,9 @@
 	struct i2ob_request *i2ob_qhead;
 	request_queue_t req_queue;
 };
-static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS] = {NULL};
+static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS];
+static struct i2ob_request *i2ob_backlog[MAX_I2O_CONTROLLERS];
+static struct i2ob_request *i2ob_backlog_tail[MAX_I2O_CONTROLLERS];
 
 /*
  *	Each I2O disk is one of these.
@@ -179,10 +186,10 @@
  * Mutex and spin lock for event handling synchronization
  * evt_msg contains the last event.
  */
-DECLARE_MUTEX(i2ob_evt_sem);
+static DECLARE_MUTEX_LOCKED(i2ob_evt_sem);
+static DECLARE_MUTEX_LOCKED(i2ob_thread_dead);
 static spinlock_t i2ob_evt_lock = SPIN_LOCK_UNLOCKED;
-static unsigned int evt_msg[MSG_FRAME_SIZE>>2];
-DECLARE_WAIT_QUEUE_HEAD(i2ob_evt_wait);
+static u32 evt_msg[MSG_FRAME_SIZE>>2];
 
 static struct timer_list i2ob_timer;
 static int i2ob_timer_started = 0;
@@ -195,6 +202,7 @@
 static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int);
 static void i2ob_end_request(struct request *);
 static void i2ob_request(request_queue_t *);
+static int i2ob_backlog_request(struct i2o_controller *, struct i2ob_device *);
 static int i2ob_init_iop(unsigned int);
 static request_queue_t* i2ob_get_queue(kdev_t);
 static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
@@ -203,6 +211,7 @@
 
 static int evt_pid = 0;
 static int evt_running = 0;
+static int scan_unit = 0;
 
 /*
  * I2O OSM registration structure...keeps getting bigger and bigger :)
@@ -255,7 +264,12 @@
 	__raw_writel(i2ob_context|(unit<<8), msg+8);
 	__raw_writel(ireq->num, msg+12);
 	__raw_writel(req->nr_sectors << 9, msg+20);
-	
+
+	/* 
+	 * Mask out partitions from now on
+	 */
+	unit &= 0xF0;
+		
 	/* This can be optimised later - just want to be sure its right for
 	   starters */
 	offset = ((u64)(req->sector+base)) << 9;
@@ -266,8 +280,6 @@
 	if(req->cmd == READ)
 	{
 		__raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4);
-		/* We don't yet do cache/readahead and other magic */
-		__raw_writel(1<<16, msg+16);
 		while(bh!=NULL)
 		{
 			if(bh->b_data == last) {
@@ -293,16 +305,20 @@
 			count -= bh->b_size;
 			bh = bh->b_reqnext;
 		}
+		/*
+		 *	Heuristic for now since the block layer doesnt give
+		 *	us enough info. If its a big write assume sequential
+		 *	readahead on controller. If its small then don't read
+		 *	ahead but do use the controller cache.
+		 */
+		if(size >= 8192)
+			__raw_writel((8<<24)|(1<<16)|8, msg+16);
+		else
+			__raw_writel((8<<24)|(1<<16)|4, msg+16);
 	}
 	else if(req->cmd == WRITE)
 	{
 		__raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4);
-		/* 
-		 * Allow replies to come back once data is cached in the controller
-		 * This allows us to handle writes quickly thus giving more of the
-		 * queue to reads.
-		 */
-		__raw_writel(0x00000010, msg+16);
 		while(bh!=NULL)
 		{
 			if(bh->b_data == last) {
@@ -328,13 +344,32 @@
 			count -= bh->b_size;
 			bh = bh->b_reqnext;
 		}
+
+		if(c->battery)
+		{
+			
+			if(size>16384)
+				__raw_writel(4, msg+16);
+			else
+				/* 
+				 * Allow replies to come back once data is cached in the controller
+				 * This allows us to handle writes quickly thus giving more of the
+				 * queue to reads.
+				 */
+				__raw_writel(16, msg+16);
+		}
+		else
+		{
+			/* Large write, don't cache */
+			if(size>8192)
+				__raw_writel(4, msg+16);
+			else
+			/* write through */
+				__raw_writel(8, msg+16);
+		}
 	}
 	__raw_writel(I2O_MESSAGE_SIZE(mptr-msg)>>2 | SGL_OFFSET_8, msg);
 	
-	if(req->current_nr_sectors > i2ob_max_sectors[unit])
-		printk("Gathered sectors %ld.\n", 
-			req->current_nr_sectors);
-			
 	if(count != 0)
 	{
 		printk(KERN_ERR "Request count botched by %d.\n", count);
@@ -434,7 +469,32 @@
 	return 1;
 }
 
+static int i2ob_flush(struct i2o_controller *c, struct i2ob_device *d, int unit)
+{
+	unsigned long msg;
+	u32 m = i2ob_get(d);
+	
+	if(m == 0xFFFFFFFF)
+		return -1;
+		
+	msg = c->mem_offset + m;
 
+	/*
+	 *	Ask the controller to write the cache back. This sorts out
+	 *	the supertrak firmware flaw and also does roughly the right
+	 *	thing for other cases too.
+	 */
+	 	
+	__raw_writel(FIVE_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
+	__raw_writel(I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|d->tid, msg+4);
+	__raw_writel(i2ob_context|(unit<<8), msg+8);
+	__raw_writel(0, msg+12);
+	__raw_writel(60<<16, msg+16);
+	
+	i2o_post_message(c,m);
+	return 0;
+}
+			
 /*
  *	OSM reply handler. This gets all the message replies
  */
@@ -447,7 +507,7 @@
 	u32 *m = (u32 *)msg;
 	u8 unit = (m[2]>>8)&0xF0;	/* low 4 bits are partition */
 	struct i2ob_device *dev = &i2ob_dev[(unit&0xF0)];
-
+	
 	/*
 	 * FAILed message
 	 */
@@ -482,9 +542,20 @@
 	if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
 	{
 		spin_lock(&i2ob_evt_lock);
-		memcpy(&evt_msg, m, msg->size);
+		memcpy(evt_msg, msg, (m[0]>>16)<<2);
 		spin_unlock(&i2ob_evt_lock);
-		wake_up_interruptible(&i2ob_evt_wait);
+		up(&i2ob_evt_sem);
+		return;
+	}
+
+	if(msg->function == I2O_CMD_BLOCK_CFLUSH)
+	{
+		spin_lock_irqsave(&io_request_lock, flags);
+		dev->constipated=0;
+		DEBUG(("unconstipated\n"));
+		if(i2ob_backlog_request(c, dev)==0)
+			i2ob_request(dev->req_queue);
+		spin_unlock_irqrestore(&io_request_lock, flags);
 		return;
 	}
 
@@ -517,6 +588,7 @@
 
 	if(st!=0)
 	{
+		int err;
 		char *bsa_errors[] = 
 		{ 
 			"Success", 
@@ -535,12 +607,78 @@
 			"Volume has changed, waiting for acknowledgement"
 		};
 				
+		err = m[4]&0xFFFF;
+		
+		/*
+		 *	Device not ready means two things. One is that the
+		 *	the thing went offline (but not a removal media)
+		 *
+		 *	The second is that you have a SuperTrak 100 and the
+		 *	firmware got constipated. Unlike standard i2o card
+		 *	setups the supertrak returns an error rather than
+		 *	blocking for the timeout in these cases.
+		 */
+		 
+		
+		spin_lock_irqsave(&io_request_lock, flags);
+		if(err==4)
+		{
+			/*
+			 *	Time to uncork stuff
+			 */
+			
+			if(!dev->constipated)
+			{
+				dev->constipated = 1;
+				DEBUG(("constipated\n"));
+				/* Now pull the chain */
+				if(i2ob_flush(c, dev, unit)<0)
+				{
+					DEBUG(("i2ob: Unable to queue flush. Retrying I/O immediately.\n"));
+					dev->constipated=0;
+				}
+				DEBUG(("flushing\n"));
+			}
+			
+			/*
+			 *	Recycle the request
+			 */
+			 
+//			i2ob_unhook_request(ireq, c->unit);
+			
+			/*
+			 *	Place it on the recycle queue
+			 */
+			 
+			ireq->next = NULL;
+			if(i2ob_backlog_tail[c->unit]!=NULL)
+				i2ob_backlog_tail[c->unit]->next = ireq;
+			else
+				i2ob_backlog[c->unit] = ireq;			
+			i2ob_backlog_tail[c->unit] = ireq;
+			
+			atomic_dec(&i2ob_queues[c->unit]->queue_depth);
+
+			/*
+			 *	If the constipator flush failed we want to
+			 *	poke the queue again. 
+			 */
+			 
+			i2ob_request(dev->req_queue);
+			spin_unlock_irqrestore(&io_request_lock, flags);
+			
+			/*
+			 *	and out
+			 */
+			 
+			return;	
+		}
+		spin_unlock_irqrestore(&io_request_lock, flags);
 		printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, 
 			bsa_errors[m[4]&0XFFFF]);
 		if(m[4]&0x00FF0000)
 			printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF );
-		printk("\n");
-
+		printk(".\n");
 		ireq->req->errors++;	
 	}
 	else
@@ -559,7 +697,9 @@
 	/*
 	 *	We may be able to do more I/O
 	 */
-	i2ob_request(dev->req_queue);
+
+	if(i2ob_backlog_request(c, dev)==0)
+		i2ob_request(dev->req_queue);
 
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
@@ -575,6 +715,14 @@
 	unsigned int flags;
 	int unit;
 	int i;
+	//The only event that has data is the SCSI_SMART event.
+	struct i2o_reply {
+		u32 header[4];
+		u32 evt_indicator;
+		u8 ASC;
+		u8 ASCQ;
+		u8 data[16];
+		} *evt_local;
 
 	lock_kernel();
 	daemonize();
@@ -585,15 +733,13 @@
 
 	while(1)
 	{
-#warning "RACE"
-		interruptible_sleep_on(&i2ob_evt_wait);
- 		if(signal_pending(current)) {
+		if(down_interruptible(&i2ob_evt_sem))
+		{
 			evt_running = 0;
-			return 0;
+			printk("exiting...");
+			break;
 		}
 
-		printk(KERN_INFO "Doing something in i2o_block event thread\n");
-		
 		/*
 		 * Keep another CPU/interrupt from overwriting the 
 		 * message while we're reading it
@@ -602,10 +748,12 @@
 		 * None of the BSA we care about events have EventData
 		 */
 		spin_lock_irqsave(&i2ob_evt_lock, flags);
-		unit = evt_msg[3];
-		evt = evt_msg[4];
+		evt_local = (struct i2o_reply *)evt_msg;
 		spin_unlock_irqrestore(&i2ob_evt_lock, flags);
 
+		unit = evt_local->header[3];
+		evt = evt_local->evt_indicator;
+
 		switch(evt)
 		{
 			/*
@@ -675,18 +823,43 @@
 				break;
 			}
 
+			/* 
+			 * We got a SCSI SMART event, we just log the relevant
+			 * information and let the user decide what they want
+			 * to do with the information.
+			 */
+			case I2O_EVT_IND_BSA_SCSI_SMART:
+			{
+				char buf[16];
+				printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",i2ob_dev[unit].i2odev->dev_name);
+				evt_local->data[16]='\0';
+				sprintf(buf,"%s",&evt_local->data[0]);
+				printk(KERN_INFO "      Disk Serial#:%s\n",buf);
+				printk(KERN_INFO "      ASC 0x%02x \n",evt_local->ASC);
+				printk(KERN_INFO "      ASCQ 0x%02x \n",evt_local->ASCQ);
+				break;
+			}
+		
+			/*
+			 *	Non event
+			 */
+			 
+			case 0:
+				break;
+				
 			/*
 			 * An event we didn't ask for.  Call the card manufacturer
 			 * and tell them to fix their firmware :)
 			 */
 			default:
-				printk(KERN_INFO "%s: Received event we didn't register for\n"
-					KERN_INFO "   Call I2O card manufacturer\n", 
-					i2ob_dev[unit].i2odev->dev_name);
+				printk(KERN_INFO "%s: Received event %d we didn't register for\n"
+					KERN_INFO "   Blame the I2O card manufacturer 8)\n", 
+					i2ob_dev[unit].i2odev->dev_name, evt);
 				break;
 		}
 	};
 
+	up_and_exit(&i2ob_thread_dead,0);
 	return 0;
 }
 
@@ -724,6 +897,34 @@
 	spin_unlock_irqrestore(&io_request_lock,flags);
 }
 
+static int i2ob_backlog_request(struct i2o_controller *c, struct i2ob_device *dev)
+{
+	u32 m;
+	struct i2ob_request *ireq;
+	
+	while((ireq=i2ob_backlog[c->unit])!=NULL)
+	{
+		int unit;
+
+		if(atomic_read(&i2ob_queues[c->unit]->queue_depth) > dev->depth/4)
+			break;
+
+		m = i2ob_get(dev);
+		if(m == 0xFFFFFFFF)
+			break;
+
+		i2ob_backlog[c->unit] = ireq->next;
+		if(i2ob_backlog[c->unit] == NULL)
+			i2ob_backlog_tail[c->unit] = NULL;
+			
+		unit = MINOR(ireq->req->rq_dev);
+		i2ob_send(m, dev, ireq, i2ob[unit].start_sect, unit);
+	}
+	if(i2ob_backlog[c->unit])
+		return 1;
+	return 0;
+}
+
 /*
  *	The I2O block driver is listed as one of those that pulls the
  *	front entry off the queue before processing it. This is important
@@ -731,6 +932,7 @@
  *	on us. We must unlink CURRENT in this routine before we return, if
  *	we use it.
  */
+
 static void i2ob_request(request_queue_t *q)
 {
 	struct request *req;
@@ -738,9 +940,8 @@
 	int unit;
 	struct i2ob_device *dev;
 	u32 m;
-
-	// printk(KERN_INFO "i2ob_request() called with queue %p\n", q);
-
+	
+	
 	while (!list_empty(&q->queue_head)) {
 		/*
 		 *	On an IRQ completion if there is an inactive
@@ -760,9 +961,16 @@
 		 *	generic IOP commit control. Certainly its not right 
 		 *	its global!  
 		 */
-		if(atomic_read(&i2ob_queues[dev->unit]->queue_depth)>=MAX_I2OB_DEPTH)
+		if(atomic_read(&i2ob_queues[dev->unit]->queue_depth) >= dev->depth)
 			break;
+		
+		/*
+		 *	Is the channel constipated ?
+		 */
 
+		if(i2ob_backlog[dev->unit]!=NULL)
+			break;
+			
 		/* Get a message */
 		m = i2ob_get(dev);
 
@@ -773,7 +981,7 @@
 			 */
 			if (!i2ob_timer_started)
 			{
-				printk(KERN_ERR "i2ob: starting timer\n");
+				DEBUG((KERN_ERR "i2ob: starting timer\n"));
 
 				/*
 				 * Set the timer_started flag to insure
@@ -795,6 +1003,7 @@
 				 */
 				 
 				add_timer(&i2ob_timer);
+				return;
 			}
 		}
 
@@ -804,7 +1013,7 @@
 		req->errors = 0;
 		blkdev_dequeue_request(req);	
 		req->sem = NULL;
-
+		
 		ireq = i2ob_queues[dev->unit]->i2ob_qhead;
 		i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
 		ireq->req = req;
@@ -892,13 +1101,7 @@
 	for( i = 15; i>=0 ; i--)
 	{
 		int m = minor+i;
-		kdev_t d = MKDEV(MAJOR_NR, m);
-		struct super_block *sb = get_super(d);
-		
-		sync_dev(d);
-		if(sb)
-			invalidate_inodes(sb);
-		invalidate_buffers(d);
+		invalidate_device(MKDEV(MAJOR_NR, m), 1);
 		i2ob_gendisk.part[m].start_sect = 0;
 		i2ob_gendisk.part[m].nr_sects = 0;
 	}
@@ -1009,7 +1212,8 @@
 		msg[2] = i2ob_context|0x40000000;
 		msg[3] = (u32)query_done;
 		msg[4] = 60<<16;
-		i2o_post_wait(dev->controller, msg, 20, 2);
+		DEBUG("Flushing...");
+		i2o_post_wait(dev->controller, msg, 20, 60);
 
 		/*
 		 *	Unlock the media
@@ -1019,14 +1223,18 @@
 		msg[2] = i2ob_context|0x40000000;
 		msg[3] = (u32)query_done;
 		msg[4] = -1;
+		DEBUG("Unlocking...");
 		i2o_post_wait(dev->controller, msg, 20, 2);
+		DEBUG("Unlocked.\n");
 	
 		/*
  		 * Now unclaim the device.
 		 */
+
 		if (i2o_release_device(dev->i2odev, &i2o_block_handler))
 			printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n");
-
+		
+		DEBUG("Unclaim\n");
 	}
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -1055,12 +1263,14 @@
 	{ 
 		u32 msg[6];
 		
+		DEBUG("Claim ");
 		if(i2o_claim_device(dev->i2odev, &i2o_block_handler))
 		{
 			dev->refcnt--;
 			printk(KERN_INFO "I2O Block: Could not open device\n");
 			return -EBUSY;
 		}
+		DEBUG("Claimed ");
 		
 		/*
 		 *	Mount the media if needed. Note that we don't use
@@ -1072,6 +1282,7 @@
 		msg[1] = I2O_CMD_BLOCK_MMOUNT<<24|HOST_TID<<12|dev->tid;
 		msg[4] = -1;
 		msg[5] = 0;
+		DEBUG("Mount ");
 		i2o_post_wait(dev->controller, msg, 24, 2);
 
 		/*
@@ -1080,7 +1291,9 @@
 		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
 		msg[1] = I2O_CMD_BLOCK_MLOCK<<24|HOST_TID<<12|dev->tid;
 		msg[4] = -1;
+		DEBUG("Lock ");
 		i2o_post_wait(dev->controller, msg, 20, 2);
+		DEBUG("Ready.\n");
 	}		
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -1132,7 +1345,8 @@
 	i2ob_query_device(dev, 0x0000, 5, &flags, 4);
 	i2ob_query_device(dev, 0x0000, 6, &status, 4);
 	i2ob_sizes[unit] = (int)(size>>10);
-	i2ob_hardsizes[unit] = blocksize;
+	for(i=unit; i <= unit+15 ; i++)
+		i2ob_hardsizes[i] = blocksize;
 	i2ob_gendisk.part[unit].nr_sects = size>>9;
 	i2ob[unit].nr_sects = (int)(size>>9);
 
@@ -1143,20 +1357,33 @@
 	/*
 	 * Max number of Scatter-Gather Elements
 	 */	
-	i2ob_dev[unit].max_segments = 
-		(d->controller->status_block->inbound_frame_size - 8)/2;
 
-	printk(KERN_INFO "Max Segments set to %d\n", 
-				i2ob_dev[unit].max_segments);
-	printk(KERN_INFO "Byte limit is %d.\n", limit);
-	
 	for(i=unit;i<=unit+15;i++)
 	{
-		i2ob_max_sectors[i]=MAX_SECTORS;
-		i2ob_dev[i].max_segments = 
-			(d->controller->status_block->inbound_frame_size - 8)/2;
+		if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.queue_buggy)
+		{
+			i2ob_max_sectors[i] = 32;
+			i2ob_dev[i].max_segments = 8;
+			i2ob_dev[i].depth = 4;
+		}
+		else if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.short_req)
+		{
+			i2ob_max_sectors[i] = 8;
+			i2ob_dev[i].max_segments = 8;
+		}
+		else
+		{
+			/* MAX_SECTORS was used but 255 is a dumb number for
+			   striped RAID */
+			i2ob_max_sectors[i]=256;
+			i2ob_dev[i].max_segments = (d->controller->status_block->inbound_frame_size - 8)/2;
+		}
 	}
 
+	printk(KERN_INFO "Max segments set to %d\n", 
+				i2ob_dev[unit].max_segments);
+	printk(KERN_INFO "Byte limit is %d.\n", limit);
+
 	i2ob_query_device(dev, 0x0000, 0, &type, 1);
 	
 	sprintf(d->dev_name, "%s%c", i2ob_gendisk.major_name, 'a' + (unit>>4));
@@ -1190,6 +1417,7 @@
 			printk(", %dMb cache", cachesize>>10);
 		else
 			printk(", %dKb cache", cachesize);
+		
 	}
 	printk(".\n");
 	printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", 
@@ -1277,53 +1505,94 @@
 /*
  * Probe the I2O subsytem for block class devices
  */
-static void i2ob_probe(void)
+static void i2ob_scan(int bios)
 {
 	int i;
-	int unit = 0;
 	int warned = 0;
+
+	struct i2o_device *d, *b=NULL;
+	struct i2o_controller *c;
+	struct i2ob_device *dev;
 		
 	for(i=0; i< MAX_I2O_CONTROLLERS; i++)
 	{
-		struct i2o_controller *c=i2o_find_controller(i);
-		struct i2o_device *d;
+		c=i2o_find_controller(i);
 	
 		if(c==NULL)
 			continue;
 
-		for(d=c->devices;d!=NULL;d=d->next)
-		{
+	/*
+	 *    The device list connected to the I2O Controller is doubly linked
+	 * Here we traverse the end of the list , and start claiming devices
+	 * from that end. This assures that within an I2O controller atleast
+	 * the newly created volumes get claimed after the older ones, thus
+	 * mapping to same major/minor (and hence device file name) after 
+	 * every reboot.
+	 * The exception being: 
+	 * 1. If there was a TID reuse.
+	 * 2. There was more than one I2O controller. 
+	 */
+
+	if(!bios)
+	{
+		for (d=c->devices;d!=NULL;d=d->next)
+		if(d->next == NULL)
+			b = d;
+	}
+	else
+		b = c->devices;
+
+	while(b != NULL)
+	{
+		d=b;
+		if(bios)
+			b = b->next;
+		else
+			b = b->prev;
+
 			if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
 				continue;
 
 			if(d->lct_data.user_tid != 0xFFF)
 				continue;
 
+			if(bios)
+			{
+				if(d->lct_data.bios_info != 0x80)
+					continue;
+				printk(KERN_INFO "Claiming as Boot device: Controller %d, TID %d\n", c->unit, d->lct_data.tid);
+			}
+			else
+			{
+				if(d->lct_data.bios_info == 0x80)
+					continue; /*Already claimed on pass 1 */
+			}
+
 			if(i2o_claim_device(d, &i2o_block_handler))
 			{
 				printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit,
 					d->lct_data.tid);
-				printk(KERN_WARNING "\tDevice refused claim! Skipping installation\n");
+				printk(KERN_WARNING "\t%sevice refused claim! Skipping installation\n", bios?"Boot d":"D");
 				continue;
 			}
 
-			if(unit<MAX_I2OB<<4)
+			if(scan_unit<MAX_I2OB<<4)
 			{
  				/*
 				 * Get the device and fill in the
 				 * Tid and controller.
 				 */
-				struct i2ob_device *dev=&i2ob_dev[unit];
+				dev=&i2ob_dev[scan_unit];
 				dev->i2odev = d; 
 				dev->controller = c;
 				dev->unit = c->unit;
 				dev->tid = d->lct_data.tid;
 
-				if(i2ob_install_device(c,d,unit))
+				if(i2ob_install_device(c,d,scan_unit))
 					printk(KERN_WARNING "Could not install I2O block device\n");
 				else
 				{
-					unit+=16;
+					scan_unit+=16;
 					i2ob_dev_count++;
 
 					/* We want to know when device goes away */
@@ -1333,7 +1602,7 @@
 			else
 			{
 				if(!warned++)
-					printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", unit>>4);
+					printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit>>4);
 			}
 			i2o_release_device(d, &i2o_block_handler);
 		}
@@ -1341,6 +1610,31 @@
 	}
 }
 
+static void i2ob_probe(void)
+{
+	/*
+	 *      Some overhead/redundancy involved here, while trying to
+	 *      claim the first boot volume encountered as /dev/i2o/hda
+	 *      everytime. All the i2o_controllers are searched and the
+	 *      first i2o block device marked as bootable is claimed
+	 *      If an I2O block device was booted off , the bios sets
+	 *      its bios_info field to 0x80, this what we search for.
+	 *      Assuming that the bootable volume is /dev/i2o/hda
+	 *      everytime will prevent any kernel panic while mounting
+	 *      root partition
+	 */
+
+	printk(KERN_INFO "i2o_block: Checking for Boot device...\n");
+	i2ob_scan(1);
+
+	/*
+	 *      Now the remainder.
+	 */
+	printk(KERN_INFO "i2o_block: Checking for I2O Block devices...\n");
+	i2ob_scan(0);
+}
+
+
 /*
  * New device notification handler.  Called whenever a new
  * I2O block storage device is added to the system.
@@ -1369,14 +1663,6 @@
 			break;
 	}
 
-	/*
-	 * Creating a RAID 5 volume takes a little while and the UTIL_CLAIM
-	 * will fail if we don't give the card enough time to do it's magic, 
-	 * so we just sleep for a little while and let it do it's thing
-	 */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(3*HZ);
-
 	if(i2o_claim_device(d, &i2o_block_handler))
 	{
 		printk(KERN_INFO 
@@ -1435,6 +1721,7 @@
 	if(unit >= MAX_I2OB<<4)
 	{
 		printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
+		spin_unlock_irqrestore(&io_request_lock, flags);
 		return;
 	}
 
@@ -1492,8 +1779,6 @@
 	i2ob_media_change_flag[unit] = 1;
 
 	i2ob_dev_count--;	
-
-	return;
 }
 
 /*
@@ -1540,8 +1825,11 @@
 			msg[2] = i2ob_context|0x40000000;
 			msg[3] = (u32)query_done;
 			msg[4] = 60<<16;
-			i2o_post_wait(dev->controller, msg, 20, 2);
+			
+			DEBUG("Flushing...");
+			i2o_post_wait(dev->controller, msg, 20, 60);
 
+			DEBUG("Unlocking...");
 			/*
 			 *	Unlock the media
 			 */
@@ -1551,20 +1839,21 @@
 			msg[3] = (u32)query_done;
 			msg[4] = -1;
 			i2o_post_wait(dev->controller, msg, 20, 2);
+			
+			DEBUG("Unlocked.\n");
 		}
 	}	
 }
 
 static struct block_device_operations i2ob_fops =
 {
-   open:       i2ob_open,
-   release:    i2ob_release,
-   ioctl:         i2ob_ioctl,
-   check_media_change:  i2ob_media_change,
-   revalidate:    i2ob_revalidate,
+	open:			i2ob_open,
+	release:		i2ob_release,
+	ioctl:			i2ob_ioctl,
+	check_media_change:	i2ob_media_change,
+	revalidate:		i2ob_revalidate,
 };
 
-
 static struct gendisk i2ob_gendisk = 
 {
 	MAJOR_NR,
@@ -1573,9 +1862,10 @@
 	1<<4,
 	i2ob,
 	i2ob_sizes,
-	0,
+	MAX_I2OB,
+	NULL,
 	NULL,
-	NULL
+	&i2ob_fops,
 };
 
 
@@ -1593,7 +1883,7 @@
 	int i;
 
 	printk(KERN_INFO "I2O Block Storage OSM v0.9\n");
-	printk(KERN_INFO "   (c) Copyright 1999, 2000 Red Hat Software.\n");
+	printk(KERN_INFO "   (c) Copyright 1999-2001 Red Hat Software.\n");
 	
 	/*
 	 *	Register the block device interfaces
@@ -1629,6 +1919,7 @@
 		i2ob_dev[i].tid = 0;
 		i2ob_dev[i].head = NULL;
 		i2ob_dev[i].tail = NULL;
+		i2ob_dev[i].depth = MAX_I2OB_DEPTH;
 		i2ob_blksizes[i] = 1024;
 		i2ob_max_sectors[i] = 2;
 	}
@@ -1683,7 +1974,13 @@
 		register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4,
 			&i2ob_fops, 0);
 	i2ob_probe();
-	
+
+	/*
+	 *	Adding i2ob_gendisk into the gendisk list.
+	 */	
+	i2ob_gendisk.next = gendisk_head;
+	gendisk_head = &i2ob_gendisk;
+
 	return 0;
 }
 
@@ -1695,9 +1992,20 @@
 
 void cleanup_module(void)
 {
-	struct gendisk **gdp;
+	struct gendisk *gdp;
 	int i;
 	
+	if(evt_running) {
+		printk(KERN_INFO "Killing I2O block threads...");
+		i = kill_proc(evt_pid, SIGTERM, 1);
+		if(!i) {
+			printk("waiting...");
+		}
+		/* Be sure it died */
+		down(&i2ob_thread_dead);
+		printk("done.\n");
+	}
+
 	/*
 	 * Unregister for updates from any devices..otherwise we still
 	 * get them and the core jumps to random memory :O
@@ -1713,6 +2021,18 @@
 	}
 	
 	/*
+	 *	We may get further callbacks for ourself. The i2o_core
+	 *	code handles this case reasonably sanely. The problem here
+	 *	is we shouldn't get them .. but a couple of cards feel 
+	 *	obliged to tell us stuff we dont care about.
+	 *
+	 *	This isnt ideal at all but will do for now.
+	 */
+	 
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ);
+	
+	/*
 	 *	Flush the OSM
 	 */
 
@@ -1729,28 +2049,20 @@
 	 */
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 
-	if(evt_running) {
-		i = kill_proc(evt_pid, SIGTERM, 1);
-		if(!i) {
-			int count = 5 * 100;
-			while(evt_running && --count) {
-				current->state = TASK_INTERRUPTIBLE;
-				schedule_timeout(1);
-			}
-	
-			if(!count)
-				printk(KERN_ERR "Giving up on i2oblock thread...\n");	
-		}
-	}
-
-
 	/*
 	 *	Why isnt register/unregister gendisk in the kernel ???
 	 */
 
-	for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
-		if (*gdp == &i2ob_gendisk)
-			break;
-
+	if (gendisk_head == &i2ob_gendisk) {
+		gendisk_head = i2ob_gendisk.next;
+		}
+	else {
+		for (gdp = gendisk_head; gdp; gdp = gdp->next)
+			if (gdp->next == &i2ob_gendisk)
+			{
+				gdp->next = i2ob_gendisk.next;
+				break;
+			}
+	}
 }
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
--- v2.4.4/linux/drivers/i2o/i2o_config.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/i2o/i2o_config.c	Tue May  1 16:10:37 2001
@@ -42,7 +42,6 @@
 
 static int i2o_cfg_context = -1;
 static void *page_buf;
-static void *i2o_buffer;
 static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
 struct wait_queue *i2o_wait_queue;
 
@@ -499,6 +498,7 @@
 	if(!res)
 	{
 		i2o_unlock_controller(c);
+		kfree(query);
 		return -ENOMEM;
 	}
 
@@ -517,16 +517,25 @@
 		msg[7] = 0xD4000000|(kcmd.qlen);
 		msg[8] = virt_to_bus(query);
 	}
-
-	token = i2o_post_wait(c, msg, 9*4, 10);
-	if(token)
+	/*
+	Wait for a considerable time till the Controller 
+	does its job before timing out. The controller might
+	take more time to process this request if there are
+	many devices connected to it.
+	*/
+	token = i2o_post_wait_mem(c, msg, 9*4, 400, query, res);
+	if(token < 0)
 	{
 		printk(KERN_DEBUG "token = %#10x\n", token);
 		i2o_unlock_controller(c);
-		kfree(res);
-		if(kcmd.qlen) kfree(query);
+		
+		if(token != -ETIMEDOUT)
+		{
+			kfree(res);
+			if(kcmd.qlen) kfree(query);
+		}
 
-		return -ETIMEDOUT;
+		return token;
 	}
 	i2o_unlock_controller(c);
 
@@ -595,17 +604,18 @@
 	msg[8]= virt_to_bus(buffer);
 
 //	printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_post_wait(c, msg, sizeof(msg), 60);
+	status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL);
 
 	i2o_unlock_controller(c);
-	kfree(buffer);
+	if(status != -ETIMEDOUT)
+		kfree(buffer);
 	
 	if (status != I2O_POST_WAIT_OK)
 	{
 		// it fails if you try and send frags out of order
 		// and for some yet unknown reasons too
 		printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status);
-		return -ETIMEDOUT;
+		return status;
 	}
 
 	return 0;
@@ -660,14 +670,15 @@
 	msg[8]= virt_to_bus(buffer);
 	
 //	printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_post_wait(c, msg, sizeof(msg), 60);
+	status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL);
 	i2o_unlock_controller(c);
 	
 	if (status != I2O_POST_WAIT_OK)
 	{
-		kfree(buffer);
+		if(status != -ETIMEDOUT)
+			kfree(buffer);
 		printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status);
-		return -ETIMEDOUT;
+		return status;
 	}
 	
 	__copy_to_user(kxfer.buf, buffer, fragsize);
@@ -787,13 +798,6 @@
 	struct i2o_evt_get kget;
 	unsigned int flags;
 
-	// access_ok doesn't check for NULL?!?!
-	if(!arg)
-		return -EFAULT;
-	
-	if(!access_ok(VERIFY_WRITE, uget,  sizeof(struct i2o_evt_get)))
-		return -EFAULT;
-
 	for(p = open_files; p; p = p->next)
 		if(p->q_id == id)
 			break;
@@ -812,8 +816,8 @@
 	kget.lost = p->q_lost;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
 
-	__copy_to_user(uget, &kget, sizeof(struct i2o_evt_get));
-
+	if(copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -958,8 +962,6 @@
 		kfree(page_buf);
 	if(i2o_cfg_context != -1)
 		i2o_remove_handler(&cfg_handler);
-	if(i2o_buffer)
-		kfree(i2o_buffer);
 }
  
 EXPORT_NO_SYMBOLS;
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
--- v2.4.4/linux/drivers/i2o/i2o_core.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/i2o/i2o_core.c	Tue May  1 16:10:37 2001
@@ -1,5 +1,5 @@
-/* 
- * Core I2O structure managment 
+/*
+ * Core I2O structure management 
  * 
  * (C) Copyright 1999   Red Hat Software 
  *
@@ -49,7 +49,7 @@
 
 #include "i2o_lan.h"
 
-// #define DRIVERDEBUG
+//#define DRIVERDEBUG
 
 #ifdef DRIVERDEBUG
 #define dprintk(s, args...) printk(s, ## args)
@@ -147,10 +147,12 @@
  */ 
 struct i2o_post_wait_data
 {
-	int status;
-	u32 id;
-	wait_queue_head_t *wq;
-	struct i2o_post_wait_data *next;
+	int *status;		/* Pointer to status block on caller stack */
+	int *complete;		/* Pointer to completion flag on caller stack */
+	u32 id;			/* Unique identifier */
+	wait_queue_head_t *wq;	/* Wake up for caller (NULL for dead) */
+	struct i2o_post_wait_data *next;	/* Chain */
+	void *mem[2];		/* Memory blocks to recover on failure path */
 };
 static struct i2o_post_wait_data *post_wait_queue = NULL;
 static u32 post_wait_id = 0;	// Unique ID for each post_wait
@@ -169,10 +171,10 @@
 	I2O_CLASS_EXECUTIVE
 };
 
-
 /*
- * Used when queing a reply to be handled later
+ * Used when queueing a reply to be handled later
  */
+ 
 struct reply_info
 {
 	struct i2o_controller *iop;
@@ -199,10 +201,12 @@
 static spinlock_t i2o_evt_lock = SPIN_LOCK_UNLOCKED;
 
 /*
- * Semaphore used to syncrhonize event handling thread with 
+ * Semaphore used to synchronize event handling thread with 
  * interrupt handler.
  */
-DECLARE_MUTEX(evt_sem);
+ 
+static DECLARE_MUTEX(evt_sem);
+static DECLARE_MUTEX_LOCKED(evt_dead);
 DECLARE_WAIT_QUEUE_HEAD(evt_wait);
 
 static struct notifier_block i2o_reboot_notifier =
@@ -212,6 +216,12 @@
         0
 };
 
+/*
+ *	Config options
+ */
+
+static int verbose = 0;
+MODULE_PARM(verbose, "i");
 
 /*
  * I2O Core reply handler
@@ -252,7 +262,7 @@
 	if(msg[2]&0x80000000)	// Post wait message
 	{
 		if (msg[4] >> 24)
-			status = -(msg[4] & 0xFFFF);
+			status = (msg[4] & 0xFFFF);
 		else
 			status = I2O_POST_WAIT_OK;
 	
@@ -369,6 +379,9 @@
 	d->controller=c;
 	d->owner=NULL;
 	d->next=c->devices;
+	d->prev=NULL;
+	if (c->devices != NULL)
+		c->devices->prev=d;
 	c->devices=d;
 	*d->dev_name = 0;
 
@@ -696,7 +709,7 @@
 {
 	down(&i2o_configuration_lock);
 	if (d->owner) {
-		printk(KERN_INFO "Device claim called, but dev allready owned by %s!",
+		printk(KERN_INFO "Device claim called, but dev already owned by %s!",
 		       h->name);
 		up(&i2o_configuration_lock);
 		return -EBUSY;
@@ -721,37 +734,59 @@
  *	Drop a claim by an OSM on a given I2O device. The handler is cleared
  *	and 0 is returned on success.
  *
+ *	AC - some devices seem to want to refuse an unclaim until they have
+ *	finished internal processing. It makes sense since you don't want a
+ *	new device to go reconfiguring the entire system until you are done.
+ *	Thus we are prepared to wait briefly.
  */
 
 int i2o_release_device(struct i2o_device *d, struct i2o_handler *h)
 {
 	int err = 0;
+	int tries;
 
 	down(&i2o_configuration_lock);
 	if (d->owner != h) {
-		printk(KERN_INFO "Claim release called, but not owned by %s!",
+		printk(KERN_INFO "Claim release called, but not owned by %s!\n",
 		       h->name);
 		up(&i2o_configuration_lock);
 		return -ENOENT;
 	}	
 
-	d->owner = NULL;
-
-	if(i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, 
-			   I2O_CLAIM_PRIMARY))
+	for(tries=0;tries<10;tries++)
 	{
-		err = -ENXIO;
-		d->owner = h;
-	}
+		d->owner = NULL;
 
+		/*
+		 *	If the controller takes a nonblocking approach to
+		 *	releases we have to sleep/poll for a few times.
+		 */
+		 
+		if((err=i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, I2O_CLAIM_PRIMARY)) )
+		{
+			err = -ENXIO;
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+		else
+		{
+			err=0;
+			break;
+		}
+	}
 	up(&i2o_configuration_lock);
 	return err;
 }
 
-/*
- * Called by OSMs to let the core know that they want to be
- * notified if the given device is deleted from the system.
+/**
+ * 	i2o_device_notify_on	-	Enable deletion notifiers
+ *	@d: device for notification
+ *	@h: handler to install
+ *
+ *	Called by OSMs to let the core know that they want to be
+ *	notified if the given device is deleted from the system.
  */
+
 int i2o_device_notify_on(struct i2o_device *d, struct i2o_handler *h)
 {
 	int i;
@@ -773,7 +808,11 @@
 	return 0;
 }
 
-/*
+/**
+ * 	i2o_device_notify_off	-	Remove deletion notifiers
+ *	@d: device for notification
+ *	@h: handler to remove
+ *
  * Called by OSMs to let the core know that they no longer
  * are interested in the fate of the given device.
  */
@@ -794,9 +833,18 @@
 	return -ENOENT;
 }
 
-/*
- * Event registration API
+/**
+ *	i2o_event_register	-	register interest in an event
+ * 	@c: Controller to register interest with
+ *	@tid: I2O task id
+ *	@init_context: initiator context to use with this notifier
+ *	@tr_context: transaction context to use with this notifier
+ *	@evt_mask: mask of events
+ *
+ *	Create and posts an event registration message to the task. No reply
+ *	is waited for, or expected. Errors in posting will be reported.
  */
+ 
 int i2o_event_register(struct i2o_controller *c, u32 tid, 
 		u32 init_context, u32 tr_context, u32 evt_mask)
 {
@@ -814,11 +862,13 @@
 }
 
 /*
- * Event ack API
+ * 	i2o_event_ack	-	acknowledge an event
+ *	@c: controller 
+ *	@msg: pointer to the UTIL_EVENT_REGISTER reply we received
  *
- * We just take a pointer to the original UTIL_EVENT_REGISTER reply
- * message and change the function code since that's what spec
- * describes an EventAck message looking like.
+ *	We just take a pointer to the original UTIL_EVENT_REGISTER reply
+ *	message and change the function code since that's what spec
+ *	describes an EventAck message looking like.
  */
  
 int i2o_event_ack(struct i2o_controller *c, u32 *msg)
@@ -850,12 +900,12 @@
 
 	while(1)
 	{
-		down_interruptible(&evt_sem);
-		if(signal_pending(current))
+		if(down_interruptible(&evt_sem))
 		{
 			dprintk(KERN_INFO "I2O event thread dead\n");
+			printk("exiting...");
 			evt_running = 0;
-			return 0;	
+			up_and_exit(&evt_dead, 0);
 		}
 
 		/* 
@@ -922,6 +972,10 @@
 					kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
 				int i;
 
+				if (d == NULL) {
+					printk(KERN_EMERG "i2oevtd: out of memory\n");
+					break;
+				}
 				memcpy(&d->lct_data, &msg[5], sizeof(i2o_lct_entry));
 	
 				d->next = NULL;
@@ -974,7 +1028,11 @@
 				printk(KERN_WARNING "%s: Warning notification received!"
 					"Check configuration for errors!\n", c->name);
 				break;
-	
+				
+			case I2O_EVT_IND_EVT_MASK_MODIFIED:
+				/* Well I guess that was us hey .. */
+				break;
+					
 			default:
 				printk(KERN_WARNING "%s: No handler for event (0x%08x)\n", c->name, msg[4]);
 				break;
@@ -1124,12 +1182,6 @@
 		m=(struct i2o_message *)bus_to_virt(mv);
 		msg=(u32*)m;
 
-		/*
-		 *	Temporary Debugging
-		 */
-		if(m->function==0x15)
-			printk(KERN_ERR "%s: UTFR!\n", c->name);
-
 		i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)];
 		if(i && i->reply)
 			i->reply(i,c,m);
@@ -1219,9 +1271,9 @@
 
 
 /**
- *	i2o_wait_message
+ *	i2o_wait_message	-	obtain an i2o message from the IOP
  *	@c: controller
- *	@why: explanation
+ *	@why: explanation 
  *
  *	This function waits up to 5 seconds for a message slot to be
  *	available. If no message is available it prints an error message
@@ -1266,9 +1318,11 @@
 	char str[22];
 	int ret;
 	int unit = d->lct_data.tid;
-	
-	printk(KERN_INFO "Target ID %d.\n", unit);
 
+	if(verbose==0)
+		return;
+		
+	printk(KERN_INFO "Target ID %d.\n", unit);
 	if((ret=i2o_query_scalar(c, unit, 0xF100, 3, buf, 16))>=0)
 	{
 		buf[16]=0;
@@ -1279,13 +1333,11 @@
 		buf[16]=0;
 		printk(KERN_INFO "     Device: %s\n", buf);
 	}
-#if 0
 	if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)
 	{
 		buf[16]=0;
 		printk(KERN_INFO "     Description: %s\n", buf);
 	}
-#endif	
 	if((ret=i2o_query_scalar(c, unit, 0xF100, 6, buf, 8))>=0)
 	{
 		buf[8]=0;
@@ -1581,7 +1633,7 @@
 
 
 /**
- *	i2o_reset_controller
+ *	i2o_reset_controller	-	reset an IOP
  *	@c: controller to reset
  *
  *	Reset the IOP into INIT state and wait until IOP gets into RESET state.
@@ -1601,7 +1653,10 @@
 	/* Quiesce all IOPs first */
 
 	for (iop = i2o_controller_chain; iop; iop = iop->next)
-		i2o_quiesce_controller(iop);
+	{
+		if(iop->type != I2O_TYPE_PCI || !iop->bus.pci.dpt)
+			i2o_quiesce_controller(iop);
+	}
 
 	m=i2o_wait_message(c, "AdapterReset");
 	if(m==0xFFFFFFFF)	
@@ -1628,19 +1683,19 @@
 
 	/* Wait for a reply */
 	time=jiffies;
-	while(status[0]==0)
+	while(*status==0)
 	{
 		if((jiffies-time)>=20*HZ)
 		{
 			printk(KERN_ERR "IOP reset timeout.\n");
-			kfree(status);
+			// Better to leak this for safety: kfree(status);
 			return -ETIMEDOUT;
 		}
 		schedule();
 		barrier();
 	}
 
-	if (status[0]==I2O_CMD_IN_PROGRESS)
+	if (*status==I2O_CMD_IN_PROGRESS)
 	{ 
 		/* 
 		 * Once the reset is sent, the IOP goes into the INIT state 
@@ -1799,7 +1854,7 @@
 	u32 msg[6];
 	int ret, size = sizeof(i2o_hrt);
 
-	/* Read first just the header to figure out the real size */
+	/* First read just the header to figure out the real size */
 
 	do  {
 		if (c->hrt == NULL) {
@@ -1816,7 +1871,18 @@
 		msg[4]= (0xD0000000 | size);	/* Simple transaction */
 		msg[5]= virt_to_bus(c->hrt);	/* Dump it here */
 
-		if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
+		ret = i2o_post_wait_mem(c, msg, sizeof(msg), 20, c->hrt, NULL);
+		
+		if(ret == -ETIMEDOUT)
+		{
+			/* The HRT block we used is in limbo somewhere. When the iop wakes up
+			   we will recover it */
+			c->hrt = NULL;
+			return ret;
+		}
+		
+		if(ret<0)
+		{
 			printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
 				c->name, -ret);	
 			return ret;
@@ -1845,14 +1911,15 @@
 static int i2o_systab_send(struct i2o_controller *iop)
 {
 	u32 msg[12];
-	u32 privmem[2];
-	u32 privio[2];
 	int ret;
+	u32 *privbuf = kmalloc(16, GFP_KERNEL);
+	if(privbuf == NULL)
+		return -ENOMEM;
 
-	privmem[0] = iop->status_block->current_mem_base;
-	privmem[1] = iop->status_block->current_mem_size;
-	privio[0] = iop->status_block->current_io_base;
-	privio[1] = iop->status_block->current_io_size;
+	privbuf[0] = iop->status_block->current_mem_base;
+	privbuf[1] = iop->status_block->current_mem_size;
+	privbuf[2] = iop->status_block->current_io_base;
+	privbuf[3] = iop->status_block->current_io_size;
 
 	msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
 	msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
@@ -1864,20 +1931,33 @@
  	 * Provide three SGL-elements:
  	 * System table (SysTab), Private memory space declaration and 
  	 * Private i/o space declaration  
+ 	 *
+ 	 * FIXME: provide these for controllers needing them
  	 */
 	msg[6] = 0x54000000 | sys_tbl_len;
 	msg[7] = virt_to_bus(sys_tbl);
 	msg[8] = 0x54000000 | 0;
-	msg[9] = virt_to_bus(privmem);
+	msg[9] = virt_to_bus(privbuf);
 	msg[10] = 0xD4000000 | 0;
-	msg[11] = virt_to_bus(privio);
+	msg[11] = virt_to_bus(privbuf+8);
 
-	if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
-		printk(KERN_INFO "%s: Unable to set SysTab (status=%#x).\n", 
+	ret=i2o_post_wait_mem(iop, msg, sizeof(msg), 120, privbuf, NULL);
+	
+	if(ret==-ETIMEDOUT)
+	{
+		printk(KERN_ERR "%s: SysTab setup timed out.\n", iop->name);
+	}
+	else if(ret<0)
+	{
+		printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", 
 			iop->name, -ret);
+		kfree(privbuf);
+	}
 	else
+	{
 		dprintk(KERN_INFO "%s: SysTab set.\n", iop->name);
-
+		kfree(privbuf);
+	}
 	i2o_status_get(iop); // Entered READY state
 
 	return ret;	
@@ -2162,7 +2242,16 @@
 		msg[6] = 0xD0000000|size;
 		msg[7] = virt_to_bus(c->lct);
 
-		if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
+		ret=i2o_post_wait_mem(c, msg, sizeof(msg), 120, c->lct, NULL);
+		
+		if(ret == -ETIMEDOUT)
+		{
+			c->lct = NULL;
+			return ret;
+		}
+		
+		if(ret<0)
+		{
 			printk(KERN_ERR "%s: LCT Get failed (status=%#x.\n", 
 				c->name, -ret);	
 			return ret;
@@ -2206,8 +2295,11 @@
 /*
  *	Bring a controller online into OPERATIONAL state. 
  */
+ 
 int i2o_online_controller(struct i2o_controller *iop)
 {
+	u32 v;
+	
 	if (i2o_systab_send(iop) < 0)
 		return -1;
 
@@ -2223,6 +2315,15 @@
 	if (i2o_lct_get(iop) < 0)
 		return -1;
 
+	/* Check battery status */
+	 
+	iop->battery = 0;
+	if(i2o_query_scalar(iop, ADAPTER_TID, 0x0000, 4, &v, 4)>=0)
+	{
+		if(v&16)
+			iop->battery = 1;
+	}
+
 	return 0;
 }
 
@@ -2346,83 +2447,134 @@
 	return 0;
 }
 
-/*
- * This core API allows an OSM to post a message and then be told whether
- * or not the system received a successful reply.  It is useful when
- * the OSM does not want to know the exact 3
+/**
+ * 	i2o_post_wait_mem	-	I2O query/reply with DMA buffers
+ *	@c: controller
+ *	@msg: message to send
+ *	@len: length of message
+ *	@timeout: time in seconds to wait
+ *	@mem1: attached memory buffer 1
+ *	@mem2: attached memory buffer 2
+ *
+ * 	This core API allows an OSM to post a message and then be told whether
+ *	or not the system received a successful reply. 
+ *
+ *	If the message times out then the value '-ETIMEDOUT' is returned. This
+ *	is a special case. In this situation the message may (should) complete
+ *	at an indefinite time in the future. When it completes it will use the
+ *	memory buffers attached to the request. If -ETIMEDOUT is returned then
+ *	the memory buffers must not be freed. Instead the event completion will
+ *	free them for you. In all other cases the buffers are your problem.
+ *
+ *	Pass NULL for unneeded buffers.
  */
-int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
+ 
+int i2o_post_wait_mem(struct i2o_controller *c, u32 *msg, int len, int timeout, void *mem1, void *mem2)
 {
 	DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);
-	int status = 0;
+	int complete = 0;
+	int status;
 	int flags = 0;
-	struct i2o_post_wait_data *p1, *p2;
 	struct i2o_post_wait_data *wait_data =
 		kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
 
 	if(!wait_data)
 		return -ENOMEM;
 
+	/*
+	 *	Create a new notification object
+	 */
+	wait_data->status = &status;
+	wait_data->complete = &complete;
+	wait_data->mem[0] = mem1;
+	wait_data->mem[1] = mem2;
 	/* 
-	 * The spin locking is needed to keep anyone from playing 
-	 * with the queue pointers and id while we do the same
+	 *	Queue the event with its unique id
 	 */
 	spin_lock_irqsave(&post_wait_lock, flags);
+
 	wait_data->next = post_wait_queue;
 	post_wait_queue = wait_data;
 	wait_data->id = (++post_wait_id) & 0x7fff;
-	spin_unlock_irqrestore(&post_wait_lock, flags);
-
 	wait_data->wq = &wq_i2o_post;
-	wait_data->status = -ETIMEDOUT;
 
+	spin_unlock_irqrestore(&post_wait_lock, flags);
+
+	/*
+	 *	Fill in the message id
+	 */
+	 
 	msg[2] = 0x80000000|(u32)core_context|((u32)wait_data->id<<16);
 	
+	/*
+	 *	Post the message to the controller. At some point later it 
+	 *	will return. If we time out before it returns then
+	 *	complete will be zero.  From the point post_this returns
+	 *	the wait_data may have been deleted.
+	 */
 	if ((status = i2o_post_this(c, msg, len))==0) {
-		interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);
-		status = wait_data->status;
+		sleep_on_timeout(&wq_i2o_post, HZ * timeout);
 	}  
-
-#ifdef DRIVERDEBUG
-	if(status == -ETIMEDOUT)
-		printk(KERN_INFO "%s: POST WAIT TIMEOUT\n",c->name);
-#endif
-
-	/* 
-	 * Remove the entry from the queue.
-	 * Since i2o_post_wait() may have been called again by
-	 * a different thread while we were waiting for this 
-	 * instance to complete, we're not guaranteed that 
-	 * this entry is at the head of the queue anymore, so 
-	 * we need to search for it, find it, and delete it.
-	 */
-	p2 = NULL;
+	else
+		return -EIO;
+		
+	if(signal_pending(current))
+		status = -EINTR;
+		
 	spin_lock_irqsave(&post_wait_lock, flags);
-	for(p1 = post_wait_queue; p1; p2 = p1, p1 = p1->next) {
-		if(p1 == wait_data) {
-			if(p2)
-				p2->next = p1->next;
-			else
-				post_wait_queue = p1->next;
-
-			break;
+	barrier();	/* Be sure we see complete as it is locked */
+	if(!complete)
+	{
+		/* 
+		 *	Mark the entry dead. We cannot remove it. This is important.
+		 *	When it does terminate (which it must do if the controller hasnt
+		 *	died..) then it will otherwise scribble on stuff.
+		 *	!complete lets us safely check if the entry is still
+		 *	allocated and thus we can write into it
+		 */
+		wait_data->wq = NULL;
+		status = -ETIMEDOUT;
+	}
+	else
+	{
+		/* Debugging check - remove me soon */
+		if(status == -ETIMEDOUT)
+		{
+			printk("TIMEDOUT BUG!\n");
+			status = -EIO;
 		}
 	}
+	/* And the wait_data is not leaked either! */	 
 	spin_unlock_irqrestore(&post_wait_lock, flags);
-	
-	kfree(wait_data);
-
 	return status;
 }
 
+/**
+ * 	i2o_post_wait		-	I2O query/reply
+ *	@c: controller
+ *	@msg: message to send
+ *	@len: length of message
+ *	@timeout: time in seconds to wait
+ *
+ * 	This core API allows an OSM to post a message and then be told whether
+ *	or not the system received a successful reply. 
+ */
+ 
+int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
+{
+	return i2o_post_wait_mem(c, msg, len, timeout, NULL, NULL);
+}
+
 /*
  * i2o_post_wait is completed and we want to wake up the 
  * sleeping proccess. Called by core's reply handler.
  */
+
 static void i2o_post_wait_complete(u32 context, int status)
 {
-	struct i2o_post_wait_data *p1 = NULL;
-
+	struct i2o_post_wait_data **p1, *q;
+	unsigned long flags;
+	
 	/* 
 	 * We need to search through the post_wait 
 	 * queue to see if the given message is still
@@ -2435,18 +2587,49 @@
 	 * Lock needed to keep anyone from moving queue pointers 
 	 * around while we're looking through them.
 	 */
-	spin_lock(&post_wait_lock);
-	for(p1 = post_wait_queue; p1; p1 = p1->next) {
-		if(p1->id == ((context >> 16) & 0x7fff)) {
-			p1->status = status;
-			wake_up_interruptible(p1->wq);
+
+	spin_lock_irqsave(&post_wait_lock, flags);
+
+	for(p1 = &post_wait_queue; *p1!=NULL; p1 = &((*p1)->next)) 
+	{
+		q = (*p1);
+		if(q->id == ((context >> 16) & 0x7fff)) {
+			/*
+			 *	Delete it 
+			 */
+			 
+			*p1 = q->next;
+			
+			/*
+			 *	Live or dead ?
+			 */
+			 
+			if(q->wq)
+			{
+				/* Live entry - wakeup and set status */
+				*q->status = status;
+				*q->complete = 1;
+				wake_up(q->wq);
+			}
+			else
+			{
+				/*
+				 *	Free resources. Caller is dead
+				 */
+				if(q->mem[0])
+					kfree(q->mem[0]);
+				if(q->mem[1])
+					kfree(q->mem[1]);
+				printk(KERN_WARNING "i2o_post_wait event completed after timeout.\n");
+			}
+			kfree(q);
 			spin_unlock(&post_wait_lock);
 			return;
 		}
 	}
 	spin_unlock(&post_wait_lock);
 
-	printk(KERN_DEBUG "i2o_post_wait reply after timeout!\n");
+	printk(KERN_DEBUG "i2o_post_wait: Bogus reply!\n");
 }
 
 /*	Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
@@ -2461,25 +2644,52 @@
                 void *oplist, int oplen, void *reslist, int reslen)
 {
 	u32 msg[9]; 
-	u8 *res = (u8 *)reslist;
 	u32 *res32 = (u32*)reslist;
 	u32 *restmp = (u32*)reslist;
 	int len = 0;
 	int i = 0;
 	int wait_status;
-
+	u32 *opmem, *resmem;
+	
+	/* Get DMAable memory */
+	opmem = kmalloc(oplen, GFP_KERNEL);
+	if(opmem == NULL)
+		return -ENOMEM;
+	memcpy(opmem, oplist, oplen);
+	
+	resmem = kmalloc(reslen, GFP_KERNEL);
+	if(resmem == NULL)
+	{
+		kfree(opmem);
+		return -ENOMEM;
+	}
+	
 	msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
 	msg[1] = cmd << 24 | HOST_TID << 12 | tid; 
 	msg[3] = 0;
 	msg[4] = 0;
 	msg[5] = 0x54000000 | oplen;	/* OperationList */
-	msg[6] = virt_to_bus(oplist);
+	msg[6] = virt_to_bus(opmem);
 	msg[7] = 0xD0000000 | reslen;	/* ResultList */
-	msg[8] = virt_to_bus(reslist);
+	msg[8] = virt_to_bus(resmem);
 
-	if((wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10)))
-		return wait_status; 	/* -DetailedStatus */
+	wait_status = i2o_post_wait_mem(iop, msg, sizeof(msg), 10, opmem, resmem);
+	
+	/*
+	 *	This only looks like a memory leak - don't "fix" it.	
+	 */
+	if(wait_status == -ETIMEDOUT)
+		return wait_status;
 
+	/* Query failed */
+	if(wait_status != 0)
+	{
+		kfree(resmem);
+		kfree(opmem);
+		return wait_status;
+	}
+	
+	memcpy(reslist, resmem, reslen);
 	/*
 	 * Calculate number of bytes of Result LIST
 	 * We need to loop through each Result BLOCK and grab the length
@@ -2500,13 +2710,13 @@
 			 *	If this is the only request,than we return an error
 			 */
 			if((res32[0]&0x0000FFFF) == 1)
-				return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
+			{
+				return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */
+			}
 		}
-
 		len += restmp[0] & 0x0000FFFF;	/* Length of res BLOCK */
 		restmp += restmp[0] & 0x0000FFFF;	/* Skip to next BLOCK */
 	}
-
 	return (len << 2);  /* bytes used by result list */
 }
 
@@ -2526,10 +2736,10 @@
 	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, 
 		opblk, sizeof(opblk), resblk, sizeof(resblk));
 		
-	if (size < 0)
-		return size;	
-
 	memcpy(buf, resblk+8, buflen);  /* cut off header */
+	
+	if(size>buflen)
+		return buflen;
 	return size;
 }
 
@@ -2570,6 +2780,8 @@
 				opblk, 12+buflen, resblk, sizeof(resblk));
 
 	kfree(opblk);
+	if(size>buflen)
+		return buflen;
 	return size;
 }
 
@@ -2614,6 +2826,8 @@
 				opblk, 10+ibuflen, resblk, reslen);
 
 	kfree(opblk);
+	if(size>reslen)
+		return reslen;
 	return size;
 }
 
@@ -2662,6 +2876,8 @@
 				opblk, 10+buflen, resblk, sizeof(resblk));
 
 	kfree(opblk);
+	if(size>buflen)
+		return buflen;
 	return size;
 }
 
@@ -3113,8 +3329,6 @@
 }
 
 
-#ifdef MODULE
-
 EXPORT_SYMBOL(i2o_controller_chain);
 EXPORT_SYMBOL(i2o_num_controllers);
 EXPORT_SYMBOL(i2o_find_controller);
@@ -3131,6 +3345,7 @@
 
 EXPORT_SYMBOL(i2o_post_this);
 EXPORT_SYMBOL(i2o_post_wait);
+EXPORT_SYMBOL(i2o_post_wait_mem);
 
 EXPORT_SYMBOL(i2o_query_scalar);
 EXPORT_SYMBOL(i2o_set_scalar);
@@ -3147,6 +3362,8 @@
 
 EXPORT_SYMBOL(i2o_get_class_name);
 
+#ifdef MODULE
+
 MODULE_AUTHOR("Red Hat Software");
 MODULE_DESCRIPTION("I2O Core");
 
@@ -3206,17 +3423,13 @@
 	 * If this is shutdown time, the thread has already been killed
 	 */
 	if(evt_running) {
+		printk("Terminating i2o threads...");
 		stat = kill_proc(evt_pid, SIGTERM, 1);
 		if(!stat) {
-			int count = 10 * 100;
-			while(evt_running && count--) {
-				current->state = TASK_INTERRUPTIBLE;
-				schedule_timeout(1);
-			}
-	
-			if(!count)
-				printk(KERN_ERR "i2o: Event thread still running!\n");
+			printk("waiting...");
+			down(&evt_dead);
 		}
+		printk("done.\n");
 	}
 
 #ifdef CONFIG_I2O_PCI_MODULE
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c
--- v2.4.4/linux/drivers/i2o/i2o_lan.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/i2o/i2o_lan.c	Sun May 20 12:11:38 2001
@@ -938,7 +938,7 @@
 	spin_unlock_irq(&priv->tx_lock);
 	return 0;
 }
-#endif CONFIG_NET_FC
+#endif /* CONFIG_NET_FC */
 
 /*
  * i2o_lan_packet_send(): Send a packet as is, including the MAC header.
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c
--- v2.4.4/linux/drivers/i2o/i2o_pci.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/i2o/i2o_pci.c	Tue May  1 16:11:29 2001
@@ -160,6 +160,10 @@
 
 	c->bus.pci.irq = -1;
 
+	c->bus.pci.queue_buggy = 0;
+	c->bus.pci.dpt = 0;
+	c->bus.pci.short_req = 0;
+
 	c->irq_mask = (volatile u32 *)(mem+0x34);
 	c->post_port = (volatile u32 *)(mem+0x40);
 	c->reply_port = (volatile u32 *)(mem+0x44);
@@ -175,6 +179,30 @@
 	
 	c->type = I2O_TYPE_PCI;
 
+	/*
+	 *	Cards that fall apart if you hit them with large I/O
+	 *	loads...
+	 */
+	 
+	if(dev->vendor == PCI_VENDOR_ID_NCR && dev->device == 0x0630)
+	{
+		c->bus.pci.short_req=1;
+		printk(KERN_INFO "I2O: Symbios FC920 workarounds activated.\n");
+	}
+	if(dev->subsystem_vendor == PCI_VENDOR_ID_PROMISE)
+	{
+		c->bus.pci.queue_buggy=1;
+		printk(KERN_INFO "I2O: Promise workarounds activated.\n");
+	}
+
+	/*
+	 *	Cards that go bananas if you quiesce them before you reset
+	 *	them
+	 */
+	 
+	if(dev->vendor == PCI_VENDOR_ID_DPT)
+		c->bus.pci.dpt=1;
+	
 	/* 
 	 * Enable Write Combining MTRR for IOP's memory region
 	 */
@@ -186,13 +214,12 @@
 * since the region contains the Messaging unit which shouldn't be cached.
 */
 	c->bus.pci.mtrr_reg1 = -1;
-	if(dev->vendor == PCI_VENDOR_ID_INTEL)
+	if(dev->vendor == PCI_VENDOR_ID_INTEL || dev->vendor == PCI_VENDOR_ID_DPT)
 	{
-	printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); 
-	c->bus.pci.mtrr_reg1 =
-		mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
-	if(c->bus.pci.mtrr_reg1< 0)
-		printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
+		printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); 
+		c->bus.pci.mtrr_reg1 =	mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
+		if(c->bus.pci.mtrr_reg1< 0)
+			printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
 	}
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c
--- v2.4.4/linux/drivers/i2o/i2o_proc.c	Fri Nov 17 16:51:47 2000
+++ linux/drivers/i2o/i2o_proc.c	Tue May  1 16:09:53 2001
@@ -2356,7 +2356,7 @@
 	len += sprintf(buf+len, "Packet orphan limit           : %d\n", work32[2]);
 
 	len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[3]);
-	len += sprintf(buf+len, "    [%s] HW CRC supression\n",
+	len += sprintf(buf+len, "    [%s] HW CRC suppression\n",
 			(work32[3]&0x00000004) ? "+" : "-");
 	len += sprintf(buf+len, "    [%s] HW IPv4 checksum\n",
 			(work32[3]&0x00000100) ? "+" : "-");
@@ -2368,7 +2368,7 @@
 			(work32[3]&0x00000800) ? "+" : "-");
 	len += sprintf(buf+len, "    [%s] HW ICMP checksum\n",
 			(work32[3]&0x00001000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback supression enable\n",
+	len += sprintf(buf+len, "    [%s] Loopback suppression enable\n",
 			(work32[3]&0x00002000) ? "+" : "-");
 
 	len += sprintf(buf+len, "Rx modes : 0x%08x\n", work32[4]);
diff -u --recursive --new-file v2.4.4/linux/drivers/i2o/i2o_scsi.c linux/drivers/i2o/i2o_scsi.c
--- v2.4.4/linux/drivers/i2o/i2o_scsi.c	Mon Oct 30 14:44:29 2000
+++ linux/drivers/i2o/i2o_scsi.c	Tue May  1 16:09:53 2001
@@ -262,7 +262,7 @@
 	
 	if(st)
 	{
-		/* An error has occured */
+		/* An error has occurred */
 
 		dprintk((KERN_DEBUG "SCSI error %08X", m[4]));
 			
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c
--- v2.4.4/linux/drivers/ide/alim15x3.c	Fri Apr 27 14:15:01 2001
+++ linux/drivers/ide/alim15x3.c	Sat May 19 17:43:06 2001
@@ -233,8 +233,8 @@
 }
 #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
 
-static byte m5229_revision	= 0;
-static byte chip_is_1543c_e	= 0;
+static byte m5229_revision;
+static byte chip_is_1543c_e;
 
 byte ali_proc = 0;
 static struct pci_dev *isa_dev;
@@ -689,7 +689,8 @@
 		 * M1543C or newer for DMAing
 		 */
 		hwif->dmaproc = &ali15x3_dmaproc;
-		hwif->autodma = 1;
+		if (!noautodma)
+			hwif->autodma = 1;
 	}
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c
--- v2.4.4/linux/drivers/ide/amd7409.c	Tue Nov  7 11:02:24 2000
+++ linux/drivers/ide/amd7409.c	Sat May 19 17:43:06 2001
@@ -455,7 +455,8 @@
 
 	if (hwif->dma_base) {
 		hwif->dmaproc = &amd7409_dmaproc;
-		hwif->autodma = 1;
+		if (!noautodma)
+			hwif->autodma = 1;
 	} else {
 		hwif->autodma = 0;
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/cy82c693.c linux/drivers/ide/cy82c693.c
--- v2.4.4/linux/drivers/ide/cy82c693.c	Tue Jun 20 07:52:36 2000
+++ linux/drivers/ide/cy82c693.c	Sat May 19 17:43:06 2001
@@ -442,7 +442,8 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &cy82c693_dmaproc;
-		hwif->autodma = 1;
+		if (!noautodma)
+			hwif->autodma = 1;
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/hd.c linux/drivers/ide/hd.c
--- v2.4.4/linux/drivers/ide/hd.c	Fri Feb 16 16:02:36 2001
+++ linux/drivers/ide/hd.c	Sat Apr 28 11:27:53 2001
@@ -892,13 +892,7 @@
 
 	for (i=max_p - 1; i >=0 ; i--) {
 		int minor = start + i;
-		kdev_t devi = MKDEV(MAJOR_NR, minor);
-		struct super_block *sb = get_super(devi); 
-
-		sync_dev(devi);
-		if (sb)
-			invalidate_inodes(sb);
-		invalidate_buffers(devi);
+		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
 		gdev->part[minor].start_sect = 0;
 		gdev->part[minor].nr_sects = 0;
 	}
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/hpt34x.c linux/drivers/ide/hpt34x.c
--- v2.4.4/linux/drivers/ide/hpt34x.c	Tue Jun 20 07:52:36 2000
+++ linux/drivers/ide/hpt34x.c	Sat May 19 17:43:06 2001
@@ -419,7 +419,11 @@
 		unsigned short pcicmd = 0;
 
 		pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
-		hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+		if (!noautodma)
+			hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+		else
+			hwif->autodma = 0;
+
 		hwif->dmaproc = &hpt34x_dmaproc;
 	} else {
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c
--- v2.4.4/linux/drivers/ide/hpt366.c	Sat Jan 27 08:45:58 2001
+++ linux/drivers/ide/hpt366.c	Sat May 19 17:43:06 2001
@@ -223,8 +223,8 @@
 byte hpt366_proc = 0;
 
 extern char *ide_xfer_verbose (byte xfer_rate);
-byte hpt363_shared_irq = 0;
-byte hpt363_shared_pin = 0;
+byte hpt363_shared_irq;
+byte hpt363_shared_pin;
 
 static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev)
 {
@@ -706,7 +706,10 @@
 		} else {
 			hwif->dmaproc = &hpt366_dmaproc;
 		}
-		hwif->autodma = 1;
+		if (!noautodma)
+			hwif->autodma = 1;
+		else
+			hwif->autodma = 0;
 	} else {
 		hwif->autodma = 0;
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c
--- v2.4.4/linux/drivers/ide/ide-pci.c	Thu Apr 19 22:57:06 2001
+++ linux/drivers/ide/ide-pci.c	Sun May 20 11:32:11 2001
@@ -581,7 +581,7 @@
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265))
 		{
 			printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n");
-			if(dev->bus->self->vendor == PCI_VENDOR_ID_INTEL &&
+			if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL &&
 				dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960)
 			{
 				printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n");
@@ -708,7 +708,8 @@
 				/*
  	 			 * Set up BM-DMA capability (PnP BIOS should have done this)
  	 			 */
-				hwif->autodma = 0;	/* default DMA off if we had to configure it here */
+		    		if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530))
+					hwif->autodma = 0;	/* default DMA off if we had to configure it here */
 				(void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
 				if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
 					printk("%s: %s error updating PCICMD\n", hwif->name, d->name);
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/ide-pnp.c linux/drivers/ide/ide-pnp.c
--- v2.4.4/linux/drivers/ide/ide-pnp.c	Wed May 24 18:38:26 2000
+++ linux/drivers/ide/ide-pnp.c	Tue May  1 16:06:23 2001
@@ -49,7 +49,7 @@
 
 /* ISA PnP device table entry */
 struct pnp_dev_t {
-	unsigned int vendor, device;
+	unsigned short card_vendor, card_device, vendor, device;
 	int (*init_fn)(struct pci_dev *dev, int enable);
 };
 
@@ -81,8 +81,9 @@
 
 /* Add your devices here :)) */
 struct pnp_dev_t idepnp_devices[] __initdata = {
-	/* Generic ESDI/IDE/ATA compatible hard disk controller
 */
-	{	ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
+  	/* Generic ESDI/IDE/ATA compatible hard disk controller */
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
 		pnpide_generic_init },
 	{	0 }
 };
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/ide.c linux/drivers/ide/ide.c
--- v2.4.4/linux/drivers/ide/ide.c	Wed Apr 11 19:06:12 2001
+++ linux/drivers/ide/ide.c	Tue May  1 16:05:00 2001
@@ -179,6 +179,8 @@
 static int	ide_lock;
 #endif /* __mc68000__ || CONFIG_APUS */
 
+int noautodma = 0;
+
 /*
  * ide_modules keeps track of the available IDE chipset/probe/driver modules.
  */
@@ -1762,11 +1764,7 @@
 	for (p = 0; p < (1<<PARTN_BITS); ++p) {
 		if (drive->part[p].nr_sects > 0) {
 			kdev_t devp = MKDEV(major, minor+p);
-			struct super_block * sb = get_super(devp);
-			fsync_dev          (devp);
-			if (sb)
-				invalidate_inodes(sb);
-			invalidate_buffers (devp);
+			invalidate_device(devp, 1);
 			set_blocksize(devp, 1024);
 		}
 		drive->part[p].start_sect = 0;
@@ -1983,9 +1981,7 @@
 		for (p = 0; p < (1<<PARTN_BITS); ++p) {
 			if (drive->part[p].nr_sects > 0) {
 				kdev_t devp = MKDEV(hwif->major, minor+p);
-				struct super_block * sb = get_super(devp);
-				if (sb) invalidate_inodes(sb);
-				invalidate_buffers (devp);
+				invalidate_device(devp, 0);
 			}
 		}
 #ifdef CONFIG_PROC_FS
@@ -2893,6 +2889,12 @@
 		return 1;
 	}
 #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+	if (!strcmp(s, "ide=nodma")) {
+		printk("IDE: Prevented DMA\n");
+		noautodma = 1;
+		return 1;
+	}
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 	if (!strcmp(s, "ide=reverse")) {
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/opti621.c linux/drivers/ide/opti621.c
--- v2.4.4/linux/drivers/ide/opti621.c	Tue Nov  7 11:02:24 2000
+++ linux/drivers/ide/opti621.c	Tue May  1 16:05:00 2001
@@ -118,7 +118,7 @@
 /* Uncommnent for disable read prefetch.
  * There is some readprefetch capatibility in hdparm,
  * but when I type hdparm -P 1 /dev/hda, I got errors
- * and till reset drive is inacessible.
+ * and till reset drive is inaccessible.
  * This (hw) read prefetch is safe on my drive.
  */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/osb4.c linux/drivers/ide/osb4.c
--- v2.4.4/linux/drivers/ide/osb4.c	Sun Feb  4 10:05:30 2001
+++ linux/drivers/ide/osb4.c	Tue May  1 16:05:00 2001
@@ -402,10 +402,16 @@
 #ifdef DEBUG
 	printk("%s: reg64 == 0x%08x\n", name, reg64);
 #endif
-	reg64 &= ~0x0000A000;
-#ifdef CONFIG_SMP
-	reg64 |= 0x00008000;
-#endif
+
+//	reg64 &= ~0x0000A000;
+//#ifdef CONFIG_SMP
+//	reg64 |= 0x00008000;
+//#endif
+	/* Assume the APIC was set up properly by the BIOS for now . If it
+	   wasnt we need to do a fix up _way_ earlier. Bits 15,10,3 control
+	   APIC enable, routing and decode */
+	   
+	reg64 &= ~0x00002000;	
 	pci_write_config_dword(isa_dev, 0x64, reg64);
 
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
@@ -441,7 +447,8 @@
 #else /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (hwif->dma_base) {
-		hwif->autodma = 1;
+		if (!noautodma)
+			hwif->autodma = 1;
 		hwif->dmaproc = &osb4_dmaproc;
 	} else {
 		hwif->autodma = 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- v2.4.4/linux/drivers/ide/pdc202xx.c	Thu Apr 19 22:57:06 2001
+++ linux/drivers/ide/pdc202xx.c	Tue May  1 16:05:00 2001
@@ -101,13 +101,6 @@
 	return(pdc202xx_dma_verbose(drive_pci));
 }
 
-char *pdc202xx_interrupt_verbose (u8 sc1d)
-{
-	char *p = NULL;
-	p += sprintf(p,"0x%02x        ", sc1d);
-	return (char *)p;
-}
-
 static char * pdc202xx_info (char *buf, struct pci_dev *dev)
 {
 	char *p = buf;
@@ -862,7 +855,8 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &pdc202xx_dmaproc;
-		hwif->autodma = 1;
+		if (!noautodma)
+			hwif->autodma = 1;
 	} else {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/rz1000.c linux/drivers/ide/rz1000.c
--- v2.4.4/linux/drivers/ide/rz1000.c	Thu Apr 13 22:54:26 2000
+++ linux/drivers/ide/rz1000.c	Tue May  1 16:05:00 2001
@@ -94,4 +94,4 @@
 		init_rz1000 (dev, "RZ1001");
 }
 
-#endif CONFIG_BLK_DEV_IDEPCI
+#endif /* CONFIG_BLK_DEV_IDEPCI */
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c
--- v2.4.4/linux/drivers/ide/sis5513.c	Tue Jan  2 16:58:45 2001
+++ linux/drivers/ide/sis5513.c	Sat May 19 17:43:06 2001
@@ -629,7 +629,8 @@
 			case PCI_DEVICE_ID_SI_5600:
 			case PCI_DEVICE_ID_SI_5597:
 			case PCI_DEVICE_ID_SI_5591:
-				hwif->autodma = 1;
+				if (!noautodma)
+					hwif->autodma = 1;
 				hwif->dmaproc = &sis5513_dmaproc;
 				break;
 #endif /* CONFIG_BLK_DEV_IDEDMA */
diff -u --recursive --new-file v2.4.4/linux/drivers/ide/slc90e66.c linux/drivers/ide/slc90e66.c
--- v2.4.4/linux/drivers/ide/slc90e66.c	Tue Mar  6 19:44:34 2001
+++ linux/drivers/ide/slc90e66.c	Sat May 19 17:43:06 2001
@@ -372,10 +372,10 @@
 	if (!hwif->dma_base)
 		return;
 
-#ifndef CONFIG_BLK_DEV_IDEDMA
 	hwif->autodma = 0;
-#else /* CONFIG_BLK_DEV_IDEDMA */
-	hwif->autodma = 1;
+#ifdef CONFIG_BLK_DEV_IDEDMA 
+	if (!noautodma)
+		hwif->autodma = 1;
 	hwif->dmaproc = &slc90e66_dmaproc;
 	hwif->speedproc = &slc90e66_tune_chipset;
 #endif /* !CONFIG_BLK_DEV_IDEDMA */
diff -u --recursive --new-file v2.4.4/linux/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c
--- v2.4.4/linux/drivers/ieee1394/video1394.c	Tue Jan  2 16:45:38 2001
+++ linux/drivers/ieee1394/video1394.c	Thu May 24 14:55:17 2001
@@ -302,12 +302,12 @@
 
 	d = (struct dma_iso_ctx *)kmalloc(sizeof(struct dma_iso_ctx), 
 					  GFP_KERNEL);
-	memset(d, 0, sizeof(struct dma_iso_ctx));
-
 	if (d==NULL) {
 		PRINT(KERN_ERR, ohci->id, "failed to allocate dma_iso_ctx");
 		return NULL;
 	}
+
+	memset(d, 0, sizeof(struct dma_iso_ctx));
 
 	d->ohci = (void *)ohci;
 	d->ctx = ctx;
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h
--- v2.4.4/linux/drivers/isdn/avmb1/avmcard.h	Thu Apr 19 22:30:16 2001
+++ linux/drivers/isdn/avmb1/avmcard.h	Sat May 19 17:54:14 2001
@@ -1,60 +1,8 @@
 /*
- * $Id: avmcard.h,v 1.8.6.1 2001/04/20 02:41:59 keil Exp $
+ * $Id: avmcard.h,v 1.8.6.3 2001/05/17 21:15:33 kai Exp $
  *
  * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  *
- * $Log: avmcard.h,v $
- * Revision 1.8.6.1  2001/04/20 02:41:59  keil
- * changes from mainstream
- *
- * Revision 1.8  2000/10/10 17:44:19  kai
- * changes from/for 2.2.18
- *
- * Revision 1.7  2000/01/25 14:33:38  calle
- * - Added Support AVM B1 PCI V4.0 (tested with prototype)
- *   - splitted up t1pci.c into b1dma.c for common function with b1pciv4
- *   - support for revision register
- *
- * Revision 1.6  1999/11/05 16:38:01  calle
- * Cleanups before kernel 2.4:
- * - Changed all messages to use card->name or driver->name instead of
- *   constant string.
- * - Moved some data from struct avmcard into new struct avmctrl_info.
- *   Changed all lowlevel capi driver to match the new structur.
- *
- * Revision 1.5  1999/09/07 09:02:53  calle
- * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
- * DATA_B3_IND is always directly after the CAPI message. The "Data" member
- * ist never used inside the kernel.
- *
- * Revision 1.4  1999/08/04 10:10:08  calle
- * Bugfix: corrected /proc functions, added structure for new AVM cards.
- *
- * Revision 1.3  1999/07/23 08:41:47  calle
- * prepared for new AVM cards.
- *
- * Revision 1.2  1999/07/05 15:09:45  calle
- * - renamed "appl_release" to "appl_released".
- * - version und profile data now cleared on controller reset
- * - extended /proc interface, to allow driver and controller specific
- *   informations to include by driver hackers.
- *
- * Revision 1.1  1999/07/01 15:26:22  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
- *
  */
 
 #ifndef _AVMCARD_H_
@@ -62,7 +10,6 @@
 
 #define	AVMB1_PORTLEN		0x1f
 #define AVM_MAXVERSION		8
-#define AVM_NAPPS		30
 #define AVM_NCCI_PER_CHANNEL	4
 
 /*
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c
--- v2.4.4/linux/drivers/isdn/avmb1/b1.c	Thu Apr 19 22:30:16 2001
+++ linux/drivers/isdn/avmb1/b1.c	Sat May 19 17:54:14 2001
@@ -120,6 +120,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/capi.h>
+#include <linux/kernelcapi.h>
 #include <asm/io.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
@@ -129,7 +130,7 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.20.6.4 $";
+static char *revision = "$Revision: 1.20.6.6 $";
 
 /* ------------------------------------------------------------- */
 
@@ -374,7 +375,7 @@
 	cli();
 	b1_setinterrupt(port, card->irq, card->cardtype);
 	b1_put_byte(port, SEND_INIT);
-	b1_put_word(port, AVM_NAPPS);
+	b1_put_word(port, CAPI_MAXAPPL);
 	b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
 	b1_put_word(port, ctrl->cnr - 1);
 	restore_flags(flags);
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c
--- v2.4.4/linux/drivers/isdn/avmb1/b1dma.c	Thu Apr 19 22:30:16 2001
+++ linux/drivers/isdn/avmb1/b1dma.c	Sat May 19 17:54:14 2001
@@ -65,6 +65,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/capi.h>
+#include <linux/kernelcapi.h>
 #include <asm/io.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
@@ -74,7 +75,7 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.11.6.4 $";
+static char *revision = "$Revision: 1.11.6.6 $";
 
 /* ------------------------------------------------------------- */
 
@@ -731,7 +732,7 @@
 	_put_byte(&p, 0);
 	_put_byte(&p, 0);
 	_put_byte(&p, SEND_INIT);
-	_put_word(&p, AVM_NAPPS);
+	_put_word(&p, CAPI_MAXAPPL);
 	_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
 	_put_word(&p, card->cardnr - 1);
 	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c
--- v2.4.4/linux/drivers/isdn/avmb1/b1isa.c	Sun Mar 25 18:20:44 2001
+++ linux/drivers/isdn/avmb1/b1isa.c	Sat May 19 17:54:14 2001
@@ -95,7 +95,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.10.6.4 $";
+static char *revision = "$Revision: 1.10.6.5 $";
 
 /* ------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- v2.4.4/linux/drivers/isdn/avmb1/b1pci.c	Thu Apr 19 22:30:16 2001
+++ linux/drivers/isdn/avmb1/b1pci.c	Sat May 19 17:54:14 2001
@@ -125,7 +125,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.29.6.3 $";
+static char *revision = "$Revision: 1.29.6.4 $";
 
 /* ------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c
--- v2.4.4/linux/drivers/isdn/avmb1/b1pcmcia.c	Sun Mar 25 18:20:44 2001
+++ linux/drivers/isdn/avmb1/b1pcmcia.c	Sat May 19 17:54:14 2001
@@ -102,7 +102,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.12.6.3 $";
+static char *revision = "$Revision: 1.12.6.4 $";
 
 /* ------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c
--- v2.4.4/linux/drivers/isdn/avmb1/c4.c	Thu Apr 19 22:30:16 2001
+++ linux/drivers/isdn/avmb1/c4.c	Sat May 19 17:54:14 2001
@@ -112,6 +112,7 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/capi.h>
+#include <linux/kernelcapi.h>
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -121,7 +122,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.20.6.6 $";
+static char *revision = "$Revision: 1.20.6.8 $";
 
 #undef CONFIG_C4_DEBUG
 #undef CONFIG_C4_POLLDEBUG
@@ -851,7 +852,7 @@
 	_put_byte(&p, 0);
 	_put_byte(&p, 0);
 	_put_byte(&p, SEND_INIT);
-	_put_word(&p, AVM_NAPPS);
+	_put_word(&p, CAPI_MAXAPPL);
 	_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
 	_put_word(&p, card->cardnr - 1);
 	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.4.4/linux/drivers/isdn/avmb1/capi.c	Wed Apr 18 11:49:13 2001
+++ linux/drivers/isdn/avmb1/capi.c	Sat May 19 17:54:14 2001
@@ -1,238 +1,10 @@
 /*
- * $Id: capi.c,v 1.44.6.9 2001/04/08 17:51:42 kai Exp $
+ * $Id: capi.c,v 1.44.6.11 2001/05/17 20:41:51 kai Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
- * $Log: capi.c,v $
- * Revision 1.44.6.9  2001/04/08 17:51:42  kai
- * merge various fixes from HEAD (found by the CHECKER project)
- *
- * Revision 1.44.6.8  2001/03/21 08:52:21  kai
- * merge from main branch: fix buffer for revision string (calle)
- *
- * Revision 1.44.6.7  2001/03/15 15:11:24  kai
- * *** empty log message ***
- *
- * Revision 1.44.6.6  2001/03/13 16:17:07  kai
- * spelling fixes from 2.4.3-pre
- *
- * Revision 1.44.6.5  2001/02/13 11:43:29  kai
- * more compatility changes for 2.2.19
- *
- * Revision 1.44.6.4  2001/02/10 14:41:20  kai
- * Changes from kernel tree
- *
- * Revision 1.44.6.3  2000/12/17 22:45:08  kai
- * That's hopefully it for test13-4
- *
- * Revision 1.44.6.2  2000/12/14 23:04:12  kai
- * Makefile changes and the like for 2.4.0-test13-pre1
- * No compatiblity code for older kernels yet, but note the branch
- *
- * Revision 1.45  2000/12/02 19:47:29  kai
- * Change the Makefiles to new style.
- * There may be problems there that I missed, so this shouldn't go into
- * an offical kernel any time soon.
- * However, if I didn't commit it, we wouldn't find the bugs...
- *
- * Revision 1.44  2000/11/25 17:00:59  kai
- * compatibility cleanup - final part for the time being
- *
- * Revision 1.43  2000/11/23 20:45:14  kai
- * fixed module_init/exit stuff
- * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
- *
- * Revision 1.42  2000/11/19 17:03:55  kai
- * compatibility cleanup - part 5
- *
- * Revision 1.41  2000/11/01 14:05:02  calle
- * - use module_init/module_exit from linux/init.h.
- * - all static struct variables are initialized with "membername:" now.
- * - avm_cs.c, let it work with newer pcmcia-cs.
- *
- * Revision 1.40  2000/10/24 15:15:04  calle
- * Workaround: pppd calls restoretty before reseting the ldisc and
- *   ldisc "ppp_sync" didn't support this. So we call n_tty_ioctl
- *   in the driver ioctl function. (remember: driver ioctl function is
- *   only called if ldisc ioctl function did not handle the call)
- *
- * Revision 1.39  2000/07/24 13:42:50  calle
- * - lock_kernel/unlock_kernel for _release functions. (from 2.4)
- *
- * Revision 1.38  2000/07/24 08:49:09  calle
- * - Bugfix: capiminor_del_all_ack completely wrong :-(
- *
- * Revision 1.37  2000/07/20 10:22:27  calle
- * - Made procfs function cleaner and removed variable "begin".
- *
- * Revision 1.36  2000/06/29 13:59:35  calle
- * - call to devfs_register was wrong
- *
- * Revision 1.35  2000/06/19 15:11:24  keil
- * avoid use of freed structs
- * changes from 2.4.0-ac21
- *
- * Revision 1.34  2000/06/18 16:09:54  keil
- * more changes for 2.4
- *
- * Revision 1.33  2000/05/18 16:35:43  calle
- * Uaaahh. Bad memory leak fixed.
- *
- * Revision 1.32  2000/04/21 12:38:42  calle
- * Bugfix: error in proc_ functions, begin-off => off-begin
- *
- * Revision 1.31  2000/04/03 13:29:24  calle
- * make Tim Waugh happy (module unload races in 2.3.99-pre3).
- * no real problem there, but now it is much cleaner ...
- *
- * Revision 1.30  2000/03/19 12:31:36  calle
- * PPP over CAPI raw driver disabled for now, ppp_generic has been changed.
- *
- * Revision 1.29  2000/03/13 17:48:13  calle
- * removed unused variable.
- *
- * Revision 1.28  2000/03/08 17:06:33  calle
- * - changes for devfs and 2.3.49
- * - capifs now configurable (no need with devfs)
- * - New Middleware ioctl CAPI_NCCI_GETUNIT
- * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs)
- *
- * Revision 1.27  2000/03/06 18:00:23  calle
- * - Middleware extention now working with 2.3.49 (capifs).
- * - Fixed typos in debug section of capi.c
- * - Bugfix: Makefile corrected for b1pcmcia.c
- *
- * Revision 1.26  2000/03/03 16:48:38  calle
- * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI)
- *   It is now possible to create a connection with a CAPI2.0 applikation
- *   and than to handle the data connection from /dev/capi/ (capifs) and also
- *   using async or sync PPP on this connection.
- *   The two major device number 190 and 191 are not confirmed yet,
- *   but I want to save the code in cvs, before I go on.
- *
- * Revision 1.25  2000/03/03 16:37:11  kai
- * incorporated some cosmetic changes from the official kernel tree back
- * into CVS
- *
- * Revision 1.24  2000/03/03 15:50:42  calle
- * - kernel CAPI:
- *   - Changed parameter "param" in capi_signal from __u32 to void *.
- *   - rewrote notifier handling in kcapi.c
- *   - new notifier NCCI_UP and NCCI_DOWN
- * - User CAPI:
- *   - /dev/capi20 is now a cloning device.
- *   - middleware extentions prepared.
- * - capidrv.c
- *   - locking of list operations and module count updates.
- *
- * Revision 1.23  2000/02/26 01:00:53  keil
- * changes from 2.3.47
- *
- * Revision 1.22  1999/11/13 21:27:16  keil
- * remove KERNELVERSION
- *
- * Revision 1.21  1999/09/10 17:24:18  calle
- * Changes for proposed standard for CAPI2.0:
- * - AK148 "Linux Exention"
- *
- * Revision 1.20  1999/09/07 09:02:53  calle
- * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
- * DATA_B3_IND is always directly after the CAPI message. The "Data" member
- * ist never used inside the kernel.
- *
- * Revision 1.19  1999/07/09 15:05:42  keil
- * compat.h is now isdn_compat.h
- *
- * Revision 1.18  1999/07/06 07:42:01  calle
- * - changes in /proc interface
- * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
- *
- * Revision 1.17  1999/07/01 15:26:30  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
- *
- * Revision 1.16  1999/07/01 08:22:57  keil
- * compatibility macros now in <linux/isdn_compat.h>
- *
- * Revision 1.15  1999/06/21 15:24:11  calle
- * extend information in /proc.
- *
- * Revision 1.14  1999/06/10 16:51:03  calle
- * Bugfix: open/release of control device was not handled correct.
- *
- * Revision 1.13  1998/08/28 04:32:25  calle
- * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1
- * driver running with 2.1.118.
- *
- * Revision 1.12  1998/05/26 22:39:34  he
- * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
- * concap typo
- * cleared dev.tbusy in isdn_net BCONN status callback
- *
- * Revision 1.11  1998/03/09 17:46:37  he
- * merged in 2.1.89 changes
- *
- * Revision 1.10  1998/02/13 07:09:13  calle
- * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
- *
- * Revision 1.9  1998/01/31 11:14:44  calle
- * merged changes to 2.0 tree, prepare 2.1.82 to work.
- *
- * Revision 1.8  1997/11/04 06:12:08  calle
- * capi.c: new read/write in file_ops since 2.1.60
- * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
- * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
- * compat.h: added #define LinuxVersionCode
- *
- * Revision 1.7  1997/10/11 10:29:34  calle
- * llseek() parameters changed in 2.1.56.
- *
- * Revision 1.6  1997/10/01 09:21:15  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.5  1997/08/21 23:11:55  fritz
- * Added changes for kernels >= 2.1.45
- *
- * Revision 1.4  1997/05/27 15:17:50  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.3  1997/05/18 09:24:14  calle
- * added verbose disconnect reason reporting to avmb1.
- * some fixes in capi20 interface.
- * changed info messages for B1-PCI
- *
- * Revision 1.2  1997/03/05 21:17:59  fritz
- * Added capi_poll for compiling under 2.1.27
- *
- * Revision 1.1  1997/03/04 21:50:29  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
- *
  */
 
 #include <linux/config.h>
@@ -271,7 +43,7 @@
 #include "capifs.h"
 #endif
 
-static char *revision = "$Revision: 1.44.6.9 $";
+static char *revision = "$Revision: 1.44.6.11 $";
 
 MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/capidev.h linux/drivers/isdn/avmb1/capidev.h
--- v2.4.4/linux/drivers/isdn/avmb1/capidev.h	Mon Nov 27 16:53:43 2000
+++ linux/drivers/isdn/avmb1/capidev.h	Sat May 19 17:54:14 2001
@@ -1,55 +1,9 @@
 /*
- * $Id: capidev.h,v 1.6 2000/11/25 17:00:59 kai Exp $
+ * $Id: capidev.h,v 1.6.6.1 2001/05/17 20:41:51 kai Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- * $Log: capidev.h,v $
- * Revision 1.6  2000/11/25 17:00:59  kai
- * compatibility cleanup - final part for the time being
- *
- * Revision 1.5  2000/03/03 15:50:42  calle
- * - kernel CAPI:
- *   - Changed parameter "param" in capi_signal from __u32 to void *.
- *   - rewrote notifier handling in kcapi.c
- *   - new notifier NCCI_UP and NCCI_DOWN
- * - User CAPI:
- *   - /dev/capi20 is now a cloning device.
- *   - middleware extentions prepared.
- * - capidrv.c
- *   - locking of list operations and module count updates.
- *
- * Revision 1.4  1999/07/01 15:26:32  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
- *
- * Revision 1.3  1999/07/01 08:22:58  keil
- * compatibility macros now in <linux/isdn_compat.h>
- *
- * Revision 1.2  1999/06/21 15:24:13  calle
- * extend information in /proc.
- *
- * Revision 1.1  1997/03/04 21:50:30  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
  *
  */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c
--- v2.4.4/linux/drivers/isdn/avmb1/capidrv.c	Wed Apr 18 11:49:13 2001
+++ linux/drivers/isdn/avmb1/capidrv.c	Sat May 19 17:54:14 2001
@@ -1,211 +1,10 @@
 /*
- * $Id: capidrv.c,v 1.39.6.5 2001/04/08 17:51:42 kai Exp $
+ * $Id: capidrv.c,v 1.39.6.6 2001/05/17 20:41:51 kai Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  *
- * $Log: capidrv.c,v $
- * Revision 1.39.6.5  2001/04/08 17:51:42  kai
- * merge various fixes from HEAD (found by the CHECKER project)
- *
- * Revision 1.39.6.4  2001/03/21 08:52:21  kai
- * merge from main branch: fix buffer for revision string (calle)
- *
- * Revision 1.39.6.3  2001/03/13 16:17:07  kai
- * spelling fixes from 2.4.3-pre
- *
- * Revision 1.39.6.2  2001/02/13 11:43:29  kai
- * more compatility changes for 2.2.19
- *
- * Revision 1.39.6.1  2001/02/10 14:41:20  kai
- * Changes from kernel tree
- *
- * Revision 1.39  2000/11/23 20:45:14  kai
- * fixed module_init/exit stuff
- * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
- *
- * Revision 1.38  2000/11/14 08:43:07  calle
- * Bugfix for v110. Connectparamters where setup for sync ...
- *
- * Revision 1.37  2000/11/01 14:05:02  calle
- * - use module_init/module_exit from linux/init.h.
- * - all static struct variables are initialized with "membername:" now.
- * - avm_cs.c, let it work with newer pcmcia-cs.
- *
- * Revision 1.36  2000/06/26 15:13:41  keil
- * features should be or'ed
- *
- * Revision 1.35  2000/06/19 15:11:25  keil
- * avoid use of freed structs
- * changes from 2.4.0-ac21
- *
- * Revision 1.34  2000/06/19 13:13:55  calle
- * Added Modemsupport!
- *
- * Revision 1.33  2000/05/06 00:52:36  kai
- * merged changes from kernel tree
- * fixed timer and net_device->name breakage
- *
- * Revision 1.32  2000/04/07 15:19:58  calle
- * remove warnings
- *
- * Revision 1.31  2000/04/06 15:01:25  calle
- * Bugfix: crash in capidrv.c when reseting a capi controller.
- * - changed code order on remove of controller.
- * - using tq_schedule for notifier in kcapi.c.
- * - now using spin_lock_irqsave() and spin_unlock_irqrestore().
- * strange: sometimes even MP hang on unload of isdn.o ...
- *
- * Revision 1.30  2000/03/03 15:50:42  calle
- * - kernel CAPI:
- *   - Changed parameter "param" in capi_signal from __u32 to void *.
- *   - rewrote notifier handling in kcapi.c
- *   - new notifier NCCI_UP and NCCI_DOWN
- * - User CAPI:
- *   - /dev/capi20 is now a cloning device.
- *   - middleware extentions prepared.
- * - capidrv.c
- *   - locking of list operations and module count updates.
- *
- * Revision 1.29  1999/12/06 17:13:06  calle
- * Added controller watchdog.
- *
- * Revision 1.28  1999/11/05 16:22:37  calle
- * Bugfix: Missing break in switch on ISDN_CMD_HANGUP.
- *
- * Revision 1.27  1999/09/16 15:13:04  calle
- * forgot to change paramter type of contr for lower_callback ...
- *
- * Revision 1.26  1999/08/06 07:41:16  calle
- * Added the "vbox patch". if (si1 == 1) si2 = 0;
- *
- * Revision 1.25  1999/08/04 10:10:11  calle
- * Bugfix: corrected /proc functions, added structure for new AVM cards.
- *
- * Revision 1.24  1999/07/20 06:48:02  calle
- * Bugfix: firmware version check for D2 trace was too restrictiv.
- *
- * Revision 1.23  1999/07/09 15:05:44  keil
- * compat.h is now isdn_compat.h
- *
- * Revision 1.22  1999/07/06 07:24:14  calle
- * Bugfix: call to kfree_skb in capidrv_signal was too early,
- *         thanks to Lars Heete <hel@admin.de>.
- *
- * Revision 1.21  1999/07/01 15:26:34  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
- *
- * Revision 1.20  1999/07/01 08:22:59  keil
- * compatibility macros now in <linux/isdn_compat.h>
- *
- * Revision 1.19  1999/06/29 16:16:54  calle
- * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
- * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
- * isdnlog should check returncode of read(2) calls.
- *
- * Revision 1.18  1999/06/21 15:24:15  calle
- * extend information in /proc.
- *
- * Revision 1.17  1999/06/10 16:53:55  calle
- * Removing of module b1pci will now remove card from lower level.
- *
- * Revision 1.16  1999/05/31 11:50:33  calle
- * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed
- *         on failure, result in data block with DATA_B3 header transmitted
- *
- * Revision 1.15  1999/05/25 21:26:16  calle
- * Include CAPI-Channelallocation (leased lines) from the 2.0 tree.
- *
- * Revision 1.14  1999/05/22 07:55:06  calle
- * Added *V110* to AVM B1 driver.
- *
- * Revision 1.13  1998/06/26 15:12:55  fritz
- * Added handling of STAT_ICALL with incomplete CPN.
- * Added AT&L for ttyI emulator.
- * Added more locking stuff in tty_write.
- *
- * Revision 1.12  1998/03/29 16:06:03  calle
- * changes from 2.0 tree merged.
- *
- * Revision 1.3.2.10  1998/03/20 14:38:24  calle
- * capidrv: prepared state machines for suspend/resume/hold
- * capidrv: fix bug in state machine if B1/T1 is out of nccis
- * b1capi: changed some errno returns.
- * b1capi: detect if you try to add same T1 to different io address.
- * b1capi: change number of nccis depending on number of channels.
- * b1lli: cosmetics
- *
- * Revision 1.3.2.9  1998/03/20 09:01:12  calle
- * Changes capi_register handling to get full support for 30 bchannels.
- *
- * Revision 1.3.2.8  1998/03/18 17:51:28  calle
- * added controller number to error messages
- *
- * Revision 1.3.2.7  1998/02/27 15:40:47  calle
- * T1 running with slow link. bugfix in capi_release.
- *
- * Revision 1.11  1998/02/13 07:09:15  calle
- * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
- *
- * Revision 1.10  1998/02/02 19:52:23  calle
- * Fixed vbox (audio) acceptb.
- *
- * Revision 1.9  1998/01/31 11:14:45  calle
- * merged changes to 2.0 tree, prepare 2.1.82 to work.
- *
- * Revision 1.8  1997/11/04 06:12:09  calle
- * capi.c: new read/write in file_ops since 2.1.60
- * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
- * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
- * compat.h: added #define LinuxVersionCode
- *
- * Revision 1.7  1997/10/11 10:36:34  calle
- * Added isdnlog support. patch to isdnlog needed.
- *
- * Revision 1.6  1997/10/11 10:25:55  calle
- * New interface for lowlevel drivers. BSENT with nr. of bytes sent,
- * allow sending without ACK.
- *
- * Revision 1.5  1997/10/01 09:21:16  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.4  1997/07/13 12:22:43  calle
- * bug fix for more than one controller in connect_req.
- * debugoutput now with contrnr.
- *
- * Revision 1.3  1997/05/18 09:24:15  calle
- * added verbose disconnect reason reporting to avmb1.
- * some fixes in capi20 interface.
- * changed info messages for B1-PCI
- *
- * Revision 1.2  1997/03/05 21:19:59  fritz
- * Removed include of config.h (mkdep stated this is unneded).
- *
- * Revision 1.1  1997/03/04 21:50:31  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
- *
  */
 
 #include <linux/module.h>
@@ -234,7 +33,7 @@
 #include "capicmd.h"
 #include "capidrv.h"
 
-static char *revision = "$Revision: 1.39.6.5 $";
+static char *revision = "$Revision: 1.39.6.6 $";
 static int debugmode = 0;
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/capidrv.h linux/drivers/isdn/avmb1/capidrv.h
--- v2.4.4/linux/drivers/isdn/avmb1/capidrv.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/avmb1/capidrv.h	Sat May 19 17:54:14 2001
@@ -1,30 +1,9 @@
 /*
- * $Id: capidrv.h,v 1.2 1998/03/29 16:06:06 calle Exp $
+ * $Id: capidrv.h,v 1.2.8.1 2001/05/17 20:41:51 kai Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- * $Log: capidrv.h,v $
- * Revision 1.2  1998/03/29 16:06:06  calle
- * changes from 2.0 tree merged.
- *
- * Revision 1.1.2.1  1998/03/20 14:38:28  calle
- * capidrv: prepared state machines for suspend/resume/hold
- * capidrv: fix bug in state machine if B1/T1 is out of nccis
- * b1capi: changed some errno returns.
- * b1capi: detect if you try to add same T1 to different io address.
- * b1capi: change number of nccis depending on number of channels.
- * b1lli: cosmetics
- *
- * Revision 1.1  1997/03/04 21:50:33  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
  *
  */
 #ifndef __CAPIDRV_H__
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c
--- v2.4.4/linux/drivers/isdn/avmb1/capifs.c	Sun Mar 25 18:20:44 2001
+++ linux/drivers/isdn/avmb1/capifs.c	Thu May 24 15:42:58 2001
@@ -1,86 +1,9 @@
 /*
- * $Id: capifs.c,v 1.14.6.5 2001/03/21 08:52:21 kai Exp $
- * 
+ * $Id: capifs.c,v 1.14.6.7 2001/05/24 08:29:08 kai Exp $
+ *
  * (c) Copyright 2000 by Carsten Paeth (calle@calle.de)
  *
  * Heavily based on devpts filesystem from H. Peter Anvin
- * 
- * $Log: capifs.c,v $
- * Revision 1.14.6.5  2001/03/21 08:52:21  kai
- * merge from main branch: fix buffer for revision string (calle)
- *
- * Revision 1.14.6.4  2001/03/15 15:11:24  kai
- * *** empty log message ***
- *
- * Revision 1.14.6.3  2001/02/13 11:43:29  kai
- * more compatility changes for 2.2.19
- *
- * Revision 1.14.6.2  2001/02/10 14:41:20  kai
- * Changes from kernel tree
- *
- * Revision 1.14.6.1  2000/11/28 12:02:45  kai
- * MODULE_DEVICE_TABLE for 2.4
- *
- * Revision 1.14.2.1  2000/11/26 17:47:53  kai
- * added PCI_DEV_TABLE for 2.4
- *
- * Revision 1.14  2000/11/23 20:45:14  kai
- * fixed module_init/exit stuff
- * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
- *
- * Revision 1.13  2000/11/18 16:17:25  kai
- * change from 2.4 tree
- *
- * Revision 1.12  2000/11/01 14:05:02  calle
- * - use module_init/module_exit from linux/init.h.
- * - all static struct variables are initialized with "membername:" now.
- * - avm_cs.c, let it work with newer pcmcia-cs.
- *
- * Revision 1.11  2000/10/24 15:08:47  calle
- * Too much includes.
- *
- * Revision 1.10  2000/10/12 10:12:35  calle
- * Bugfix: second iput(inode) on umount, destroies a foreign inode.
- *
- * Revision 1.9  2000/08/20 07:30:13  keil
- * changes for 2.4
- *
- * Revision 1.8  2000/07/20 10:23:13  calle
- * Include isdn_compat.h for people that don't use -p option of std2kern.
- *
- * Revision 1.7  2000/06/18 16:09:54  keil
- * more changes for 2.4
- *
- * Revision 1.6  2000/04/03 13:29:25  calle
- * make Tim Waugh happy (module unload races in 2.3.99-pre3).
- * no real problem there, but now it is much cleaner ...
- *
- * Revision 1.5  2000/03/13 17:49:52  calle
- * make it running with 2.3.51.
- *
- * Revision 1.4  2000/03/08 17:06:33  calle
- * - changes for devfs and 2.3.49
- * - capifs now configurable (no need with devfs)
- * - New Middleware ioctl CAPI_NCCI_GETUNIT
- * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs)
- *
- * Revision 1.3  2000/03/06 18:00:23  calle
- * - Middleware extention now working with 2.3.49 (capifs).
- * - Fixed typos in debug section of capi.c
- * - Bugfix: Makefile corrected for b1pcmcia.c
- *
- * Revision 1.2  2000/03/06 09:17:07  calle
- * - capifs: fileoperations now in inode (change for 2.3.49)
- * - Config.in: Middleware extention not a tristate, uups.
- *
- * Revision 1.1  2000/03/03 16:48:38  calle
- * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI)
- *   It is now possible to create a connection with a CAPI2.0 applikation
- *   and than to handle the data connection from /dev/capi/ (capifs) and also
- *   using async or sync PPP on this connection.
- *   The two major device number 190 and 191 are not confirmed yet,
- *   but I want to save the code in cvs, before I go on.
- *
  *
  */
 
@@ -105,7 +28,7 @@
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.de>");
 
-static char *revision = "$Revision: 1.14.6.5 $";
+static char *revision = "$Revision: 1.14.6.7 $";
 
 struct capifs_ncci {
 	struct inode *inode;
@@ -142,6 +65,7 @@
 static int capifs_root_readdir(struct file *,void *,filldir_t);
 static struct dentry *capifs_root_lookup(struct inode *,struct dentry *);
 static int capifs_revalidate(struct dentry *, int);
+static struct inode *capifs_new_inode(struct super_block *sb);
 
 static struct file_operations capifs_root_operations = {
 	read:		generic_read_dir,
@@ -285,24 +209,11 @@
 
 	kfree(sbi->nccis);
 	kfree(sbi);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-	MOD_DEC_USE_COUNT;
-#endif
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
-static void capifs_write_inode(struct inode *inode) { };
-#else
 static int capifs_statfs(struct super_block *sb, struct statfs *buf);
-#endif
-static void capifs_read_inode(struct inode *inode);
 
 static struct super_operations capifs_sops = {
-	read_inode:	capifs_read_inode,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-	write_inode:	capifs_write_inode,
-#endif
 	put_super:	capifs_put_super,
 	statfs:		capifs_statfs,
 };
@@ -373,10 +284,6 @@
 	struct dentry * root;
 	struct capifs_sb_info *sbi;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-	MOD_INC_USE_COUNT;
-	lock_super(s);
-#endif
 	/* Super block already completed? */
 	if (s->s_root)
 		goto out;
@@ -411,7 +318,14 @@
 	/*
 	 * Get the root inode and dentry, but defer checking for errors.
 	 */
-	root_inode = iget(s, 1); /* inode 1 == root directory */
+	root_inode = capifs_new_inode(s);
+	if (root_inode) {
+		root_inode->i_ino = 1;
+		root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
+		root_inode->i_op = &capifs_root_inode_operations;
+		root_inode->i_fop = &capifs_root_operations;
+		root_inode->i_nlink = 2;
+	} 
 	root = d_alloc_root(root_inode);
 
 	/*
@@ -452,34 +366,11 @@
 	mounts = s;
 
 out:	/* Success ... somebody else completed the super block for us. */ 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-	unlock_super(s);
-#endif
 	return s;
 fail:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
-#endif
 	return NULL;
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
-	struct statfs tmp;
-
-	tmp.f_type = CAPIFS_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
-}
-#else
 static int capifs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	buf->f_type = CAPIFS_SUPER_MAGIC;
@@ -492,47 +383,20 @@
 	buf->f_namelen = NAME_MAX;
 	return 0;
 }
-#endif
 
-static void capifs_read_inode(struct inode *inode)
+static struct inode *capifs_new_inode(struct super_block *sb)
 {
-	ino_t ino = inode->i_ino;
-	struct capifs_sb_info *sbi = SBI(inode->i_sb);
-
-	inode->i_mode = 0;
-	inode->i_nlink = 0;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	inode->i_blocks = 0;
-	inode->i_blksize = 1024;
-	inode->i_uid = inode->i_gid = 0;
-
-	if ( ino == 1 ) {
-		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
-		inode->i_op = &capifs_root_inode_operations;
-		inode->i_fop = &capifs_root_operations;
-		inode->i_nlink = 2;
-		return;
-	} 
-
-	ino -= 2;
-	if ( ino >= sbi->max_ncci )
-		return;		/* Bogus */
-	
-	init_special_inode(inode, S_IFCHR, 0);
-
-	return;
+	struct inode *inode = new_inode(sb);
+	if (inode) {
+		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		inode->i_blocks = 0;
+		inode->i_blksize = 1024;
+		inode->i_uid = inode->i_gid = 0;
+	}
+	return inode;
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,51)
-static struct file_system_type capifs_fs_type = {
-	"capifs",
-	0,
-	capifs_read_super,
-	NULL
-};
-#else
 static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
-#endif
 
 void capifs_new_ncci(char type, unsigned int num, kdev_t device)
 {
@@ -553,14 +417,16 @@
 				break;
 			}
 		}
+		if ( ino >= sbi->max_ncci )
+			continue;
 
-		if ((np->inode = iget(sb, ino+2)) != 0) {
+		if ((np->inode = capifs_new_inode(sb)) != NULL) {
 			struct inode *inode = np->inode;
 			inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
 			inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
-			inode->i_mode = sbi->mode | S_IFCHR;
-			inode->i_rdev = np->kdev;
-			inode->i_nlink++;
+			inode->i_nlink = 1;
+			inode->i_ino = ino + 2;
+			init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
 		}
 	}
 }
@@ -612,11 +478,7 @@
 		MOD_DEC_USE_COUNT;
 		return err;
 	}
-#ifdef MODULE
-        printk(KERN_NOTICE "capifs: Rev %s: loaded\n", rev);
-#else
-	printk(KERN_NOTICE "capifs: Rev %s: started\n", rev);
-#endif
+        printk(KERN_NOTICE "capifs: Rev %s\n", rev);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/capiutil.c linux/drivers/isdn/avmb1/capiutil.c
--- v2.4.4/linux/drivers/isdn/avmb1/capiutil.c	Sun Mar 25 18:20:44 2001
+++ linux/drivers/isdn/avmb1/capiutil.c	Sat May 19 17:54:14 2001
@@ -1,93 +1,10 @@
 /*
- * $Id: capiutil.c,v 1.13.6.2 2001/03/15 15:11:24 kai Exp $
+ * $Id: capiutil.c,v 1.13.6.3 2001/05/17 20:41:51 kai Exp $
  *
  * CAPI 2.0 convert capi message to capi message struct
  *
  * From CAPI 2.0 Development Kit AVM 1995 (msg.c)
  * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- * $Log: capiutil.c,v $
- * Revision 1.13.6.2  2001/03/15 15:11:24  kai
- * *** empty log message ***
- *
- * Revision 1.13.6.1  2001/02/13 11:43:29  kai
- * more compatility changes for 2.2.19
- *
- * Revision 1.13  2000/11/23 20:45:14  kai
- * fixed module_init/exit stuff
- * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
- *
- * Revision 1.12  2000/11/01 14:05:02  calle
- * - use module_init/module_exit from linux/init.h.
- * - all static struct variables are initialized with "membername:" now.
- * - avm_cs.c, let it work with newer pcmcia-cs.
- *
- * Revision 1.11  2000/03/03 15:50:42  calle
- * - kernel CAPI:
- *   - Changed parameter "param" in capi_signal from __u32 to void *.
- *   - rewrote notifier handling in kcapi.c
- *   - new notifier NCCI_UP and NCCI_DOWN
- * - User CAPI:
- *   - /dev/capi20 is now a cloning device.
- *   - middleware extentions prepared.
- * - capidrv.c
- *   - locking of list operations and module count updates.
- *
- * Revision 1.10  1999/08/31 11:19:54  paul
- * various spelling corrections (new checksums may be needed, Karsten!)
- *
- * Revision 1.9  1999/07/09 15:05:46  keil
- * compat.h is now isdn_compat.h
- *
- * Revision 1.8  1999/07/01 15:26:37  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
- *
- * Revision 1.7  1999/07/01 08:23:01  keil
- * compatibility macros now in <linux/isdn_compat.h>
- *
- * Revision 1.6  1997/11/04 06:12:12  calle
- * capi.c: new read/write in file_ops since 2.1.60
- * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
- * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
- * compat.h: added #define LinuxVersionCode
- *
- * Revision 1.5  1997/10/01 09:21:19  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.4  1997/08/10 07:43:55  calle
- * forgot to export symbol capi_info2str for 2.1.x
- *
- * Revision 1.3  1997/05/18 09:24:18  calle
- * added verbose disconnect reason reporting to avmb1.
- * some fixes in capi20 interface.
- * changed info messages for B1-PCI
- *
- * Revision 1.2  1997/03/05 21:22:13  fritz
- * Fix: Symbols have to be exported unconditionally.
- *
- * Revision 1.1  1997/03/04 21:50:34  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
  *
  */
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c
--- v2.4.4/linux/drivers/isdn/avmb1/kcapi.c	Sun Mar 25 18:20:44 2001
+++ linux/drivers/isdn/avmb1/kcapi.c	Sat May 19 17:54:14 2001
@@ -148,7 +148,7 @@
 #include <linux/b1lli.h>
 #endif
 
-static char *revision = "$Revision: 1.21.6.5 $";
+static char *revision = "$Revision: 1.21.6.6 $";
 
 /* ------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c
--- v2.4.4/linux/drivers/isdn/avmb1/t1isa.c	Sun Mar 25 18:20:44 2001
+++ linux/drivers/isdn/avmb1/t1isa.c	Sat May 19 17:54:14 2001
@@ -109,6 +109,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/capi.h>
+#include <linux/kernelcapi.h>
 #include <linux/init.h>
 #include <asm/io.h>
 #include "capicmd.h"
@@ -116,7 +117,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.16.6.4 $";
+static char *revision = "$Revision: 1.16.6.6 $";
 
 /* ------------------------------------------------------------- */
 
@@ -410,7 +411,7 @@
 	cli();
 	b1_setinterrupt(port, card->irq, card->cardtype);
 	b1_put_byte(port, SEND_INIT);
-	b1_put_word(port, AVM_NAPPS);
+	b1_put_word(port, CAPI_MAXAPPL);
 	b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
 	b1_put_word(port, ctrl->cnr - 1);
 	restore_flags(flags);
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c
--- v2.4.4/linux/drivers/isdn/avmb1/t1pci.c	Wed Apr 18 11:49:13 2001
+++ linux/drivers/isdn/avmb1/t1pci.c	Sat May 19 17:54:14 2001
@@ -94,7 +94,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.13.6.3 $";
+static char *revision = "$Revision: 1.13.6.5 $";
 
 #undef CONFIG_T1PCI_DEBUG
 #undef CONFIG_T1PCI_POLLDEBUG
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/eicon/bri.c linux/drivers/isdn/eicon/bri.c
--- v2.4.4/linux/drivers/isdn/eicon/bri.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/eicon/bri.c	Sat May 19 17:43:06 2001
@@ -21,8 +21,7 @@
  *
  */
 
-#include <sys/types.h>
-
+#include "eicon.h"
 #include "sys.h"
 #include "idi.h"
 #include "divas.h"
@@ -33,9 +32,6 @@
 #include "adapter.h"
 #include "uxio.h"
 
-#define PCI_COMMAND	0x04
-#define PCI_STATUS	0x06
-#define PCI_LATENCY	0x0D
 #define PCI_BADDR0	0x10
 #define PCI_BADDR1	0x14
 #define PCI_BADDR2	0x18
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/eicon/common.c linux/drivers/isdn/eicon/common.c
--- v2.4.4/linux/drivers/isdn/eicon/common.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/eicon/common.c	Sat May 19 17:43:06 2001
@@ -22,6 +22,7 @@
  */
 
 
+#include "eicon.h"
 #include "sys.h"
 #include "idi.h"
 #include "constant.h"
@@ -30,19 +31,14 @@
 #include "pr_pc.h"
 
 #include "uxio.h"
-#include <sys/types.h>
-
-#define MAX_ADDR_LEN
 
 #define DIVAS_LOAD_CMD		0x02
 #define DIVAS_START_CMD		0x03
 #define DIVAS_IRQ_RESET		0xC18
 #define DIVAS_IRQ_RESET_VAL	0xFE
 
-#define	PCI_COMMAND	0x04
-#define	PCI_STATUS	0x06
-#define	PCI_LATENCY	0x0D
-#define PCI_INTERRUPT	0x3C
+#define	PCI_LATENCY	PCI_LATENCY_TIMER
+#define PCI_INTERRUPT	PCI_INTERRUPT_LINE
 
 #define TEST_INT_DIVAS		0x11
 #define TEST_INT_DIVAS_BRI	0x12
@@ -93,7 +89,7 @@
         }
 
         if (tablelength > 0)
-          bcopy((caddr_t)DIDD_Table, (caddr_t)table, tablelength);
+          bcopy((void *)DIDD_Table, (void *)table, tablelength);
 
 	return;
 }
@@ -103,7 +99,7 @@
         if (tablelength > sizeof(DIDD_Table))
           tablelength = sizeof(DIDD_Table);
 
-	bcopy((caddr_t)table, (caddr_t)DIDD_Table, tablelength);
+	bcopy((void *)table, (void *)DIDD_Table, tablelength);
 
 	return;
 }
@@ -573,7 +569,7 @@
 
 		b = card->cfg.irq;
 
-		UxPciConfigWrite(card->hw, sizeof(b), PCI_INTERRUPT, &b);
+		UxPciConfigWrite(card->hw, sizeof(b), PCI_INTERRUPT_LINE, &b);
 
 		if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
 		{
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- v2.4.4/linux/drivers/isdn/eicon/eicon.h	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/eicon/eicon.h	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.23.6.2 2001/02/13 11:43:30 kai Exp $
+/* $Id: eicon.h,v 1.23.6.3 2001/05/17 21:15:33 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  *
@@ -147,9 +147,11 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
+#include <linux/pci.h>
 
 #include <linux/isdn.h>
 #include <linux/isdnif.h>
+
 
 typedef struct {
   __u16 length __attribute__ ((packed)); /* length of data/parameter field */
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/eicon/kprintf.c linux/drivers/isdn/eicon/kprintf.c
--- v2.4.4/linux/drivers/isdn/eicon/kprintf.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/eicon/kprintf.c	Sat May 19 17:43:06 2001
@@ -27,13 +27,11 @@
  */
 
 
+#include "eicon.h"
 #include "sys.h"
 #include <stdarg.h>
 #undef MAX
 #undef MIN
-
-#include <sys/types.h>
-#include <sys/param.h>
 
 #include "divas.h"
 #include "divalog.h"
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/hysdn/boardergo.c linux/drivers/isdn/hysdn/boardergo.c
--- v2.4.4/linux/drivers/isdn/hysdn/boardergo.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hysdn/boardergo.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: boardergo.c,v 1.5.6.3 2001/03/13 16:17:09 kai Exp $
+/* $Id: boardergo.c,v 1.5.6.4 2001/04/20 02:42:00 keil Exp $
 
  * Linux driver for HYSDN cards, specific routines for ergo type boards.
  *
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/hysdn/hycapi.c linux/drivers/isdn/hysdn/hycapi.c
--- v2.4.4/linux/drivers/isdn/hysdn/hycapi.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hysdn/hycapi.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: hycapi.c,v 1.8.6.1 2001/02/16 16:43:30 kai Exp $
+/* $Id: hycapi.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $
  *
  * Linux driver for HYSDN cards, CAPI2.0-Interface.
  * written by Ulrich Albrecht (u.albrecht@hypercope.de) for Hypercope GmbH
@@ -41,7 +41,7 @@
 #include "hysdn_defs.h"
 #include <linux/kernelcapi.h>
 
-static char hycapi_revision[]="$Revision: 1.11 $";
+static char hycapi_revision[]="$Revision: 1.8.6.2 $";
 
 unsigned int hycapi_enable = 0xffffffff; 
 MODULE_PARM(hycapi_enable, "i");
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/hysdn/hysdn_defs.h linux/drivers/isdn/hysdn/hysdn_defs.h
--- v2.4.4/linux/drivers/isdn/hysdn/hysdn_defs.h	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hysdn/hysdn_defs.h	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_defs.h,v 1.5.6.1 2000/11/28 12:02:47 kai Exp $
+/* $Id: hysdn_defs.h,v 1.5.6.2 2001/04/20 02:42:00 keil Exp $
 
  * Linux driver for HYSDN cards, global definitions and exported vars and functions.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/hysdn/hysdn_net.c linux/drivers/isdn/hysdn/hysdn_net.c
--- v2.4.4/linux/drivers/isdn/hysdn/hysdn_net.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hysdn/hysdn_net.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_net.c,v 1.8.6.1 2001/02/16 16:43:30 kai Exp $
+/* $Id: hysdn_net.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $
 
  * Linux driver for HYSDN cards, net (ethernet type) handling routines.
  *
@@ -41,7 +41,7 @@
 MODULE_PARM(hynet_enable, "i");
 
 /* store the actual version for log reporting */
-char *hysdn_net_revision = "$Revision: 1.10 $";
+char *hysdn_net_revision = "$Revision: 1.8.6.2 $";
 
 #define MAX_SKB_BUFFERS 20	/* number of buffers for keeping TX-data */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/hysdn/hysdn_procconf.c linux/drivers/isdn/hysdn/hysdn_procconf.c
--- v2.4.4/linux/drivers/isdn/hysdn/hysdn_procconf.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hysdn/hysdn_procconf.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_procconf.c,v 1.8.6.1 2001/03/13 16:17:09 kai Exp $
+/* $Id: hysdn_procconf.c,v 1.8.6.2 2001/04/20 02:42:00 keil Exp $
 
  * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
@@ -31,7 +31,7 @@
 
 #include "hysdn_defs.h"
 
-static char *hysdn_procconf_revision = "$Revision: 1.8.6.1 $";
+static char *hysdn_procconf_revision = "$Revision: 1.8.6.2 $";
 
 #define INFO_OUT_LEN 80		/* length of info line including lf */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/hysdn/hysdn_sched.c linux/drivers/isdn/hysdn/hysdn_sched.c
--- v2.4.4/linux/drivers/isdn/hysdn/hysdn_sched.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hysdn/hysdn_sched.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_sched.c,v 1.5.6.1 2001/03/13 16:17:09 kai Exp $
+/* $Id: hysdn_sched.c,v 1.5.6.2 2001/04/20 02:42:00 keil Exp $
 
  * Linux driver for HYSDN cards, scheduler routines for handling exchange card <-> pc.
  *
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.4.4/linux/drivers/isdn/isdn_common.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/isdn_common.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.114.6.10 2001/04/08 19:14:00 kai Exp $
+/* $Id: isdn_common.c,v 1.114.6.11 2001/04/20 02:41:58 keil Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -51,7 +51,7 @@
 
 isdn_dev *dev;
 
-static char *isdn_revision = "$Revision: 1.114.6.10 $";
+static char *isdn_revision = "$Revision: 1.114.6.11 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.4.4/linux/drivers/isdn/isdn_net.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/isdn_net.c	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.140.6.3 2001/02/07 11:31:30 kai Exp $
+/* $Id: isdn_net.c,v 1.140.6.4 2001/04/20 02:41:58 keil Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -190,7 +190,7 @@
 static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
 static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
 
-char *isdn_net_revision = "$Revision: 1.144 $";
+char *isdn_net_revision = "$Revision: 1.140.6.4 $";
 
  /*
   * Code for raw-networking over ISDN
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h
--- v2.4.4/linux/drivers/isdn/isdn_net.h	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/isdn_net.h	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.h,v 1.19 2000/06/21 09:54:29 keil Exp $
+/* $Id: isdn_net.h,v 1.19.6.1 2001/04/20 02:41:58 keil Exp $
 
  * header for Linux ISDN subsystem, network related functions (linklevel).
  *
diff -u --recursive --new-file v2.4.4/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.4.4/linux/drivers/isdn/isdn_ppp.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/isdn_ppp.c	Tue May 22 10:23:16 2001
@@ -819,7 +819,7 @@
 		      kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
 			printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
 			for (j = 0; j < i; j++)
-				kfree(ippp_table[i]);
+				kfree(ippp_table[j]);
 			return -1;
 		}
 		memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
diff -u --recursive --new-file v2.4.4/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c
--- v2.4.4/linux/drivers/macintosh/via-cuda.c	Sun Sep 17 09:48:05 2000
+++ linux/drivers/macintosh/via-cuda.c	Tue May  1 16:05:00 2001
@@ -170,7 +170,7 @@
     }
 
     /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
-    /* for us by the the main VIA driver in arch/m68k/mac/via.c        */
+    /* for us by the main VIA driver in arch/m68k/mac/via.c        */
 
 #ifndef CONFIG_MAC
     via[IFR] = 0x7f; eieio();	/* clear interrupts by writing 1s */
diff -u --recursive --new-file v2.4.4/linux/drivers/md/md.c linux/drivers/md/md.c
--- v2.4.4/linux/drivers/md/md.c	Fri Apr  6 10:42:55 2001
+++ linux/drivers/md/md.c	Sun May 20 11:34:05 2001
@@ -1097,7 +1097,7 @@
 	}
 	memset(rdev, 0, sizeof(*rdev));
 
-	if (get_super(newdev)) {
+	if (is_mounted(newdev)) {
 		printk("md: can not import %s, has active inodes!\n",
 			partition_name(newdev));
 		err = -EBUSY;
@@ -1735,7 +1735,7 @@
  	}
  
  	/* this shouldn't be needed as above would have fired */
-	if (!ro && get_super(dev)) {
+	if (!ro && is_mounted(dev)) {
 		printk (STILL_MOUNTED, mdidx(mddev));
 		OUT(-EBUSY);
 	}
@@ -2464,7 +2464,7 @@
 	int ret;
 
 	fsync_dev(mddev_to_kdev(mddev));
-	ret = md_error(mddev_to_kdev(mddev), dev);
+	ret = md_error(mddev, dev);
 	return ret;
 }
 
@@ -2938,13 +2938,11 @@
 }
 
 
-int md_error (kdev_t dev, kdev_t rdev)
+int md_error (mddev_t *mddev, kdev_t rdev)
 {
-	mddev_t *mddev;
 	mdk_rdev_t * rrdev;
 	int rc;
 
-	mddev = kdev_to_mddev(dev);
 /*	printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
  */
 	if (!mddev) {
@@ -2999,7 +2997,7 @@
 	int sz = 0;
 	unsigned long max_blocks, resync, res, dt, db, rt;
 
-	resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);
+	resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
 	max_blocks = mddev->sb->size;
 
 	/*
@@ -3044,7 +3042,7 @@
 	 */
 	dt = ((jiffies - mddev->resync_mark) / HZ);
 	if (!dt) dt++;
-	db = resync - mddev->resync_mark_cnt;
+	db = resync - (mddev->resync_mark_cnt/2);
 	rt = (dt * ((max_blocks-resync) / (db/100+1)))/100;
 	
 	sz += sprintf(page + sz, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
@@ -3219,7 +3217,7 @@
 
 void md_done_sync(mddev_t *mddev, int blocks, int ok)
 {
-	/* another "blocks" (1K) blocks have been synced */
+	/* another "blocks" (512byte) blocks have been synced */
 	atomic_sub(blocks, &mddev->recovery_active);
 	wake_up(&mddev->recovery_wait);
 	if (!ok) {
@@ -3232,7 +3230,7 @@
 int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
 {
 	mddev_t *mddev2;
-	unsigned int max_blocks, currspeed,
+	unsigned int max_sectors, currspeed,
 		j, window, err, serialize;
 	kdev_t read_disk = mddev_to_kdev(mddev);
 	unsigned long mark[SYNC_MARKS];
@@ -3269,7 +3267,7 @@
 
 	mddev->curr_resync = 1;
 
-	max_blocks = mddev->sb->size;
+	max_sectors = mddev->sb->size<<1;
 
 	printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev));
 	printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec/disc.\n",
@@ -3293,23 +3291,23 @@
 	/*
 	 * Tune reconstruction:
 	 */
-	window = MAX_READAHEAD*(PAGE_SIZE/1024);
-	printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",window,max_blocks);
+	window = MAX_READAHEAD*(PAGE_SIZE/512);
+	printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",window/2,max_sectors/2);
 
 	atomic_set(&mddev->recovery_active, 0);
 	init_waitqueue_head(&mddev->recovery_wait);
 	last_check = 0;
-	for (j = 0; j < max_blocks;) {
-		int blocks;
+	for (j = 0; j < max_sectors;) {
+		int sectors;
 
-		blocks = mddev->pers->sync_request(mddev, j);
+		sectors = mddev->pers->sync_request(mddev, j);
 
-		if (blocks < 0) {
-			err = blocks;
+		if (sectors < 0) {
+			err = sectors;
 			goto out;
 		}
-		atomic_add(blocks, &mddev->recovery_active);
-		j += blocks;
+		atomic_add(sectors, &mddev->recovery_active);
+		j += sectors;
 		mddev->curr_resync = j;
 
 		if (last_check + window > j)
@@ -3327,7 +3325,7 @@
 			mark_cnt[next] = j - atomic_read(&mddev->recovery_active);
 			last_mark = next;
 		}
-			
+
 
 		if (md_signal_pending(current)) {
 			/*
@@ -3352,7 +3350,7 @@
 		if (md_need_resched(current))
 			schedule();
 
-		currspeed = (j-mddev->resync_mark_cnt)/((jiffies-mddev->resync_mark)/HZ +1) +1;
+		currspeed = (j-mddev->resync_mark_cnt)/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
 
 		if (currspeed > sysctl_speed_limit_min) {
 			current->nice = 19;
diff -u --recursive --new-file v2.4.4/linux/drivers/md/raid1.c linux/drivers/md/raid1.c
--- v2.4.4/linux/drivers/md/raid1.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/md/raid1.c	Thu May 24 15:40:59 2001
@@ -298,7 +298,7 @@
 	md_spin_unlock_irq(&conf->device_lock);
 }
 
-static int raid1_map (mddev_t *mddev, kdev_t *rdev, unsigned long size)
+static int raid1_map (mddev_t *mddev, kdev_t *rdev)
 {
 	raid1_conf_t *conf = mddev_to_conf(mddev);
 	int i, disks = MD_SB_DISKS;
@@ -388,7 +388,7 @@
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
 	if (!uptodate)
-		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);
+		md_error (r1_bh->mddev, bh->b_dev);
 	else
 		/*
 		 * Set R1BH_Uptodate in our master buffer_head, so that
@@ -602,7 +602,7 @@
 
 		bh_req = &r1_bh->bh_req;
 		memcpy(bh_req, bh, sizeof(*bh));
-		bh_req->b_blocknr = bh->b_rsector / sectors;
+		bh_req->b_blocknr = bh->b_rsector;
 		bh_req->b_dev = mirror->dev;
 		bh_req->b_rdev = mirror->dev;
 	/*	bh_req->b_rsector = bh->n_rsector; */
@@ -646,7 +646,7 @@
  	/*
  	 * prepare mirrored mbh (fields ordered for max mem throughput):
  	 */
-		mbh->b_blocknr    = bh->b_rsector / sectors;
+		mbh->b_blocknr    = bh->b_rsector;
 		mbh->b_dev        = conf->mirrors[i].dev;
 		mbh->b_rdev	  = conf->mirrors[i].dev;
 		mbh->b_rsector	  = bh->b_rsector;
@@ -832,6 +832,7 @@
 	struct mirror_info *tmp, *sdisk, *fdisk, *rdisk, *adisk;
 	mdp_super_t *sb = mddev->sb;
 	mdp_disk_t *failed_desc, *spare_desc, *added_desc;
+	mdk_rdev_t *spare_rdev, *failed_rdev;
 
 	print_raid1_conf(conf);
 	md_spin_lock_irq(&conf->device_lock);
@@ -989,6 +990,16 @@
 		/*
 		 * do the switch finally
 		 */
+		spare_rdev = find_rdev_nr(mddev, spare_desc->number);
+		failed_rdev = find_rdev_nr(mddev, failed_desc->number);
+
+		/* There must be a spare_rdev, but there may not be a
+		 * failed_rdev.  That slot might be empty...
+		 */
+		spare_rdev->desc_nr = failed_desc->number;
+		if (failed_rdev)
+			failed_rdev->desc_nr = spare_desc->number;
+		
 		xchg_values(*spare_desc, *failed_desc);
 		xchg_values(*fdisk, *sdisk);
 
@@ -1127,7 +1138,6 @@
 				int disks = MD_SB_DISKS;
 				struct buffer_head *bhl, *mbh;
 				raid1_conf_t *conf;
-				int sectors = bh->b_size >> 9;
 				
 				conf = mddev_to_conf(mddev);
 				bhl = raid1_alloc_bh(conf, conf->raid_disks); /* don't really need this many */
@@ -1157,7 +1167,7 @@
 					mbh->b_blocknr    = bh->b_blocknr;
 					mbh->b_dev        = conf->mirrors[i].dev;
 					mbh->b_rdev	  = conf->mirrors[i].dev;
-					mbh->b_rsector	  = bh->b_blocknr * sectors;
+					mbh->b_rsector	  = bh->b_blocknr;
 					mbh->b_state      = (1<<BH_Req) | (1<<BH_Dirty) |
 						(1<<BH_Mapped) | (1<<BH_Lock);
 					atomic_set(&mbh->b_count, 1);
@@ -1184,14 +1194,15 @@
 				}
 			} else {
 				dev = bh->b_dev;
-				raid1_map (mddev, &bh->b_dev, bh->b_size >> 9);
+				raid1_map (mddev, &bh->b_dev);
 				if (bh->b_dev == dev) {
 					printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr);
-					md_done_sync(mddev, bh->b_size>>10, 0);
+					md_done_sync(mddev, bh->b_size>>9, 0);
 				} else {
 					printk (REDIRECT_SECTOR,
 						partition_name(bh->b_dev), bh->b_blocknr);
 					bh->b_rdev = bh->b_dev;
+					bh->b_rsector = bh->b_blocknr; 
 					generic_make_request(READ, bh);
 				}
 			}
@@ -1200,8 +1211,7 @@
 		case READ:
 		case READA:
 			dev = bh->b_dev;
-		
-			raid1_map (mddev, &bh->b_dev, bh->b_size >> 9);
+			raid1_map (mddev, &bh->b_dev);
 			if (bh->b_dev == dev) {
 				printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr);
 				raid1_end_bh_io(r1_bh, 0);
@@ -1209,6 +1219,7 @@
 				printk (REDIRECT_SECTOR,
 					partition_name(bh->b_dev), bh->b_blocknr);
 				bh->b_rdev = bh->b_dev;
+				bh->b_rsector = bh->b_blocknr;
 				generic_make_request (r1_bh->cmd, bh);
 			}
 			break;
@@ -1294,7 +1305,7 @@
  * issue suitable write requests
  */
 
-static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr)
+static int raid1_sync_request (mddev_t *mddev, unsigned long sector_nr)
 {
 	raid1_conf_t *conf = mddev_to_conf(mddev);
 	struct mirror_info *mirror;
@@ -1302,9 +1313,10 @@
 	struct buffer_head *bh;
 	int bsize;
 	int disk;
+	int block_nr;
 
 	spin_lock_irq(&conf->segment_lock);
-	if (!block_nr) {
+	if (!sector_nr) {
 		/* initialize ...*/
 		int buffs;
 		conf->start_active = 0;
@@ -1324,9 +1336,9 @@
 		if (conf->cnt_ready || conf->cnt_active)
 			MD_BUG();
 	}
-	while ((block_nr<<1) >= conf->start_pending) {
+	while (sector_nr >= conf->start_pending) {
 		PRINTK("wait .. sect=%lu start_active=%d ready=%d pending=%d future=%d, cnt_done=%d active=%d ready=%d pending=%d future=%d\n",
-			block_nr<<1, conf->start_active, conf->start_ready, conf->start_pending, conf->start_future,
+			sector_nr, conf->start_active, conf->start_ready, conf->start_pending, conf->start_future,
 			conf->cnt_done, conf->cnt_active, conf->cnt_ready, conf->cnt_pending, conf->cnt_future);
 		wait_event_lock_irq(conf->wait_done,
 					!conf->cnt_active,
@@ -1372,11 +1384,11 @@
 	r1_bh->cmd = SPECIAL;
 	bh = &r1_bh->bh_req;
 
-	bh->b_blocknr = block_nr;
-	bsize = 1024;
-	while (!(bh->b_blocknr & 1) && bsize < PAGE_SIZE
-			&& (bh->b_blocknr+2)*(bsize>>10) < mddev->sb->size) {
-		bh->b_blocknr >>= 1;
+	block_nr = sector_nr;
+	bsize = 512;
+	while (!(block_nr & 1) && bsize < PAGE_SIZE
+			&& (block_nr+2)*(bsize>>9) < (mddev->sb->size *2)) {
+		block_nr >>= 1;
 		bsize <<= 1;
 	}
 	bh->b_size = bsize;
@@ -1392,13 +1404,14 @@
 		BUG();
 	bh->b_end_io = end_sync_read;
 	bh->b_private = r1_bh;
-	bh->b_rsector = block_nr<<1;
+	bh->b_blocknr = sector_nr;
+	bh->b_rsector = sector_nr;
 	init_waitqueue_head(&bh->b_wait);
 
 	generic_make_request(READ, bh);
 	md_sync_acct(bh->b_dev, bh->b_size/512);
 
-	return (bsize >> 10);
+	return (bsize >> 9);
 
 nomem:
 	raid1_shrink_buffers(conf);
@@ -1415,7 +1428,7 @@
 	 * We don't do much here, just schedule handling by raid1d
 	 */
 	if (!uptodate)
-		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);
+		md_error (r1_bh->mddev, bh->b_dev);
 	else
 		set_bit(R1BH_Uptodate, &r1_bh->state);
 	raid1_reschedule_retry(r1_bh);
@@ -1426,80 +1439,17 @@
  	struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private);
 	
 	if (!uptodate)
- 		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);
+ 		md_error (r1_bh->mddev, bh->b_dev);
 	if (atomic_dec_and_test(&r1_bh->remaining)) {
 		mddev_t *mddev = r1_bh->mddev;
- 		unsigned long sect = bh->b_blocknr * (bh->b_size>>9);
+ 		unsigned long sect = bh->b_blocknr;
 		int size = bh->b_size;
 		raid1_free_buf(r1_bh);
 		sync_request_done(sect, mddev_to_conf(mddev));
-		md_done_sync(mddev,size>>10, uptodate);
+		md_done_sync(mddev,size>>9, uptodate);
 	}
 }
 
-/*
- * This will catch the scenario in which one of the mirrors was
- * mounted as a normal device rather than as a part of a raid set.
- *
- * check_consistency is very personality-dependent, eg. RAID5 cannot
- * do this check, it uses another method.
- */
-static int __check_consistency (mddev_t *mddev, int row)
-{
-	raid1_conf_t *conf = mddev_to_conf(mddev);
-	int disks = MD_SB_DISKS;
-	kdev_t dev;
-	struct buffer_head *bh = NULL;
-	int i, rc = 0;
-	char *buffer = NULL;
-
-	for (i = 0; i < disks; i++) {
-		printk("(checking disk %d)\n",i);
-		if (!conf->mirrors[i].operational)
-			continue;
-		printk("(really checking disk %d)\n",i);
-		dev = conf->mirrors[i].dev;
-		set_blocksize(dev, 4096);
-		if ((bh = bread(dev, row / 4, 4096)) == NULL)
-			break;
-		if (!buffer) {
-			buffer = (char *) __get_free_page(GFP_KERNEL);
-			if (!buffer)
-				break;
-			memcpy(buffer, bh->b_data, 4096);
-		} else if (memcmp(buffer, bh->b_data, 4096)) {
-			rc = 1;
-			break;
-		}
-		bforget(bh);
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-		bh = NULL;
-	}
-	if (buffer)
-		free_page((unsigned long) buffer);
-	if (bh) {
-		dev = bh->b_dev;
-		bforget(bh);
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-	}
-	return rc;
-}
-
-static int check_consistency (mddev_t *mddev)
-{
-	if (__check_consistency(mddev, 0))
-/*
- * we do not do this currently, as it's perfectly possible to
- * have an inconsistent array when it's freshly created. Only
- * newly written data has to be consistent.
- */
-		return 0;
-
-	return 0;
-}
-
 #define INVALID_LEVEL KERN_WARNING \
 "raid1: md%d: raid level not set to mirroring (%d)\n"
 
@@ -1530,9 +1480,6 @@
 #define NONE_OPERATIONAL KERN_ERR \
 "raid1: no operational mirrors for md%d\n"
 
-#define RUNNING_CKRAID KERN_ERR \
-"raid1: detected mirror differences -- running resync\n"
-
 #define ARRAY_IS_ACTIVE KERN_INFO \
 "raid1: raid set md%d active with %d out of %d mirrors\n"
 
@@ -1714,17 +1661,6 @@
 		start_recovery = 1;
 	}
 
-	if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) {
-		/*
-		 * we do sanity checks even if the device says
-		 * it's clean ...
-		 */
-		if (check_consistency(mddev)) {
-			printk(RUNNING_CKRAID);
-			sb->state &= ~(1 << MD_SB_CLEAN);
-		}
-	}
-
 	{
 		const char * name = "raid1d";
 
@@ -1794,7 +1730,6 @@
 #undef OPERATIONAL
 #undef SPARE
 #undef NONE_OPERATIONAL
-#undef RUNNING_CKRAID
 #undef ARRAY_IS_ACTIVE
 
 static int raid1_stop_resync (mddev_t *mddev)
diff -u --recursive --new-file v2.4.4/linux/drivers/md/raid5.c linux/drivers/md/raid5.c
--- v2.4.4/linux/drivers/md/raid5.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/md/raid5.c	Thu May 24 15:40:59 2001
@@ -156,9 +156,9 @@
 			return 1;
 		memset(bh, 0, sizeof (struct buffer_head));
 		init_waitqueue_head(&bh->b_wait);
-		page = alloc_page(priority);
-		bh->b_data = page_address(page);
-		if (!bh->b_data) {
+		if ((page = alloc_page(priority)))
+			bh->b_data = page_address(page);
+		else {
 			kfree(bh);
 			return 1;
 		}
@@ -412,7 +412,7 @@
 			spin_lock_irqsave(&conf->device_lock, flags);
 		}
 	} else {
-		md_error(mddev_to_kdev(conf->mddev), bh->b_dev);
+		md_error(conf->mddev, bh->b_dev);
 		clear_bit(BH_Uptodate, &bh->b_state);
 	}
 	clear_bit(BH_Lock, &bh->b_state);
@@ -440,7 +440,7 @@
 
 	md_spin_lock_irqsave(&conf->device_lock, flags);
 	if (!uptodate)
-		md_error(mddev_to_kdev(conf->mddev), bh->b_dev);
+		md_error(conf->mddev, bh->b_dev);
 	clear_bit(BH_Lock, &bh->b_state);
 	set_bit(STRIPE_HANDLE, &sh->state);
 	__release_stripe(conf, sh);
@@ -886,7 +886,7 @@
 			}
 		}
 		if (syncing) {
-			md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,0);
+			md_done_sync(conf->mddev, (sh->size>>9) - sh->sync_redone,0);
 			clear_bit(STRIPE_SYNCING, &sh->state);
 			syncing = 0;
 		}			
@@ -1051,15 +1051,15 @@
 			action[failed_num] = WRITE+1;
 			locked++;
 			set_bit(STRIPE_INSYNC, &sh->state);
-			if (conf->disks[i].operational)
-				md_sync_acct(conf->disks[i].dev, bh->b_size>>9);
+			if (conf->disks[failed_num].operational)
+				md_sync_acct(conf->disks[failed_num].dev, bh->b_size>>9);
 			else if (conf->spare)
 				md_sync_acct(conf->spare->dev, bh->b_size>>9);
 
 		}
 	}
 	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
-		md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,1);
+		md_done_sync(conf->mddev, (sh->size>>9) - sh->sync_redone,1);
 		clear_bit(STRIPE_SYNCING, &sh->state);
 	}
 	
@@ -1153,13 +1153,13 @@
 	return correct_size;
 }
 
-static int raid5_sync_request (mddev_t *mddev, unsigned long block_nr)
+static int raid5_sync_request (mddev_t *mddev, unsigned long sector_nr)
 {
 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
 	struct stripe_head *sh;
 	int sectors_per_chunk = conf->chunk_size >> 9;
-	unsigned long stripe = (block_nr<<1)/sectors_per_chunk;
-	int chunk_offset = (block_nr<<1) % sectors_per_chunk;
+	unsigned long stripe = sector_nr/sectors_per_chunk;
+	int chunk_offset = sector_nr % sectors_per_chunk;
 	int dd_idx, pd_idx;
 	unsigned long first_sector;
 	int raid_disks = conf->raid_disks;
@@ -1167,9 +1167,9 @@
 	int redone = 0;
 	int bufsize;
 
-	sh = get_active_stripe(conf, block_nr<<1, 0, 0);
+	sh = get_active_stripe(conf, sector_nr, 0, 0);
 	bufsize = sh->size;
-	redone = block_nr-(sh->sector>>1);
+	redone = sector_nr - sh->sector;
 	first_sector = raid5_compute_sector(stripe*data_disks*sectors_per_chunk
 		+ chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf);
 	sh->pd_idx = pd_idx;
@@ -1182,7 +1182,7 @@
 	handle_stripe(sh);
 	release_stripe(sh);
 
-	return (bufsize>>10)-redone;
+	return (bufsize>>9)-redone;
 }
 
 /*
@@ -1256,76 +1256,6 @@
 	printk("raid5: resync finished.\n");
 }
 
-static int __check_consistency (mddev_t *mddev, int row)
-{
-	raid5_conf_t *conf = mddev->private;
-	kdev_t dev;
-	struct buffer_head *bh[MD_SB_DISKS], *tmp = NULL;
-	int i, ret = 0, nr = 0, count;
-	struct buffer_head *bh_ptr[MAX_XOR_BLOCKS];
-
-	if (conf->working_disks != conf->raid_disks)
-		goto out;
-	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-	tmp->b_size = 4096;
-	tmp->b_page = alloc_page(GFP_KERNEL);
-	tmp->b_data = page_address(tmp->b_page);
-	if (!tmp->b_data)
-		goto out;
-	md_clear_page(tmp->b_data);
-	memset(bh, 0, MD_SB_DISKS * sizeof(struct buffer_head *));
-	for (i = 0; i < conf->raid_disks; i++) {
-		dev = conf->disks[i].dev;
-		set_blocksize(dev, 4096);
-		bh[i] = bread(dev, row / 4, 4096);
-		if (!bh[i])
-			break;
-		nr++;
-	}
-	if (nr == conf->raid_disks) {
-		bh_ptr[0] = tmp;
-		count = 1;
-		for (i = 1; i < nr; i++) {
-			bh_ptr[count++] = bh[i];
-			if (count == MAX_XOR_BLOCKS) {
-				xor_block(count, &bh_ptr[0]);
-				count = 1;
-			}
-		}
-		if (count != 1) {
-			xor_block(count, &bh_ptr[0]);
-		}
-		if (memcmp(tmp->b_data, bh[0]->b_data, 4096))
-			ret = 1;
-	}
-	for (i = 0; i < conf->raid_disks; i++) {
-		dev = conf->disks[i].dev;
-		if (bh[i]) {
-			bforget(bh[i]);
-			bh[i] = NULL;
-		}
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-	}
-	free_page((unsigned long) tmp->b_data);
-out:
-	if (tmp)
-		kfree(tmp);
-	return ret;
-}
-
-static int check_consistency (mddev_t *mddev)
-{
-	if (__check_consistency(mddev, 0))
-/*
- * We are not checking this currently, as it's legitimate to have
- * an inconsistent array, at creation time.
- */
-		return 0;
-
-	return 0;
-}
-
 static int raid5_run (mddev_t *mddev)
 {
 	raid5_conf_t *conf;
@@ -1485,12 +1415,6 @@
 		start_recovery = 1;
 	}
 
-	if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN)) &&
-			check_consistency(mddev)) {
-		printk(KERN_ERR "raid5: detected raid-5 superblock xor inconsistency -- running resync\n");
-		sb->state &= ~(1 << MD_SB_CLEAN);
-	}
-
 	{
 		const char * name = "raid5d";
 
@@ -1704,6 +1628,7 @@
 	struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk;
 	mdp_super_t *sb = mddev->sb;
 	mdp_disk_t *failed_desc, *spare_desc, *added_desc;
+	mdk_rdev_t *spare_rdev, *failed_rdev;
 
 	print_raid5_conf(conf);
 	md_spin_lock_irq(&conf->device_lock);
@@ -1875,6 +1800,16 @@
 		/*
 		 * do the switch finally
 		 */
+		spare_rdev = find_rdev_nr(mddev, spare_desc->number);
+		failed_rdev = find_rdev_nr(mddev, failed_desc->number);
+
+		/* There must be a spare_rdev, but there may not be a
+		 * failed_rdev.  That slot might be empty...
+		 */
+		spare_rdev->desc_nr = failed_desc->number;
+		if (failed_rdev)
+			failed_rdev->desc_nr = spare_desc->number;
+		
 		xchg_values(*spare_desc, *failed_desc);
 		xchg_values(*fdisk, *sdisk);
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-aimslab.c linux/drivers/media/radio/radio-aimslab.c
--- v2.4.4/linux/drivers/media/radio/radio-aimslab.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-aimslab.c	Sat May 19 17:43:06 2001
@@ -42,6 +42,7 @@
 #endif
 
 static int io = CONFIG_RADIO_RTRACK_PORT; 
+static int radio_nr = -1;
 static int users = 0;
 static struct semaphore lock;
 
@@ -345,7 +346,7 @@
 
 	rtrack_radio.priv=&rtrack_unit;
 	
-	if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 2);
 		return -EINVAL;
@@ -371,6 +372,7 @@
 MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-aztech.c linux/drivers/media/radio/radio-aztech.c
--- v2.4.4/linux/drivers/media/radio/radio-aztech.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-aztech.c	Sat May 19 17:43:06 2001
@@ -40,6 +40,7 @@
 #endif
 
 static int io = CONFIG_RADIO_AZTECH_PORT; 
+static int radio_nr = -1;
 static int radio_wait_time = 1000;
 static int users = 0;
 static struct semaphore lock;
@@ -297,7 +298,7 @@
 	init_MUTEX(&lock);
 	aztech_radio.priv=&aztech_unit;
 	
-	if(video_register_device(&aztech_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io,2);
 		return -EINVAL;
@@ -312,6 +313,7 @@
 MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the Aztech radio card.");
 MODULE_PARM(io, "i");
+MODULE_PARM(radio_nr, "i");
 MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)");
 
 EXPORT_NO_SYMBOLS;
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-cadet.c linux/drivers/media/radio/radio-cadet.c
--- v2.4.4/linux/drivers/media/radio/radio-cadet.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-cadet.c	Sat May 19 17:43:06 2001
@@ -35,6 +35,7 @@
 #define RDS_BUFFER 256
 
 static int io=-1;		/* default to isapnp activation */
+static int radio_nr = -1;
 static int users=0;
 static int curtuner=0;
 static int tunestat=0;
@@ -616,7 +617,7 @@
 	}
 	if (!request_region(io,2,"cadet"))
 		return -EBUSY;
-	if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1) {
+	if(video_register_device(&cadet_radio,VFL_TYPE_RADIO,radio_nr)==-1) {
 		release_region(io,2);
 		return -EINVAL;
 	}
@@ -630,6 +631,7 @@
 MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
+MODULE_PARM(radio_nr, "i");
 
 static struct isapnp_device_id id_table[] __devinitdata = {
 	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-gemtek.c linux/drivers/media/radio/radio-gemtek.c
--- v2.4.4/linux/drivers/media/radio/radio-gemtek.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-gemtek.c	Sat May 19 17:43:06 2001
@@ -30,6 +30,7 @@
 #endif
 
 static int io = CONFIG_RADIO_GEMTEK_PORT; 
+static int radio_nr = -1;
 static int users = 0;
 static spinlock_t lock;
 
@@ -272,7 +273,7 @@
 
 	gemtek_radio.priv=&gemtek_unit;
 	
-	if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 4);
 		return -EINVAL;
@@ -295,6 +296,7 @@
 MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard)).");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-maestro.c linux/drivers/media/radio/radio-maestro.c
--- v2.4.4/linux/drivers/media/radio/radio-maestro.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-maestro.c	Sat May 19 17:43:06 2001
@@ -61,6 +61,8 @@
 
 #define BITS2FREQ(x)	((x) * FREQ_STEP - FREQ_IF)
 
+static int radio_nr = -1;
+MODULE_PARM(radio_nr, "i");
 
 
 static int radio_open(struct video_device *, int);
@@ -359,7 +361,7 @@
 	init_MUTEX(&radio_unit.lock);
 	
 	if(radio_power_on(&radio_unit)) {
-		if(video_register_device(&maestro_radio, VFL_TYPE_RADIO)==-1) {
+		if(video_register_device(&maestro_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
 			printk("radio-maestro: can't register device!");
 			return 0;
 		}
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-maxiradio.c linux/drivers/media/radio/radio-maxiradio.c
--- v2.4.4/linux/drivers/media/radio/radio-maxiradio.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-maxiradio.c	Sat May 19 17:43:06 2001
@@ -56,6 +56,9 @@
 /* TEA5757 pin mappings */
 const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ;
 
+static int radio_nr = -1;
+MODULE_PARM(radio_nr, "i");
+
 
 #define FREQ_LO		 50*16000
 #define FREQ_HI		150*16000
@@ -331,7 +334,7 @@
 	init_MUTEX(&radio_unit.lock);
 	maxiradio_radio.priv = &radio_unit;
 
-	if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO)==-1) {
+	if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
 	        printk("radio-maxiradio: can't register device!");
 	        goto err_out_free_region;
 	}
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-miropcm20.c linux/drivers/media/radio/radio-miropcm20.c
--- v2.4.4/linux/drivers/media/radio/radio-miropcm20.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/media/radio/radio-miropcm20.c	Sat May 19 17:43:06 2001
@@ -30,6 +30,8 @@
 #include "../../sound/aci.h"
 
 static int users = 0;
+static int radio_nr = -1;
+MODULE_PARM(radio_nr, "i");
 
 struct pcm20_device
 {
@@ -258,7 +260,7 @@
 
 static int __init pcm20_init(void)
 {
-	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 		return -EINVAL;
 		
 	if(attach_aci_rds()<0) {
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-rtrack2.c linux/drivers/media/radio/radio-rtrack2.c
--- v2.4.4/linux/drivers/media/radio/radio-rtrack2.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-rtrack2.c	Sat May 19 17:43:06 2001
@@ -23,6 +23,7 @@
 #endif
 
 static int io = CONFIG_RADIO_RTRACK2_PORT; 
+static int radio_nr = -1;
 static int users = 0;
 static spinlock_t lock;
 
@@ -238,7 +239,7 @@
 	rtrack2_radio.priv=&rtrack2_unit;
 
 	spin_lock_init(&lock);	
-	if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 4);
 		return -EINVAL;
@@ -257,6 +258,7 @@
 MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-sf16fmi.c linux/drivers/media/radio/radio-sf16fmi.c
--- v2.4.4/linux/drivers/media/radio/radio-sf16fmi.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-sf16fmi.c	Sat May 19 17:43:06 2001
@@ -37,6 +37,7 @@
 #endif
 
 static int io = CONFIG_RADIO_SF16FMI_PORT; 
+static int radio_nr = -1;
 static int users = 0;
 static struct semaphore lock;
 
@@ -304,7 +305,7 @@
 	
 	init_MUTEX(&lock);
 	
-	if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 2);
 		return -EINVAL;
@@ -321,6 +322,7 @@
 MODULE_DESCRIPTION("A driver for the SF16MI radio.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-terratec.c linux/drivers/media/radio/radio-terratec.c
--- v2.4.4/linux/drivers/media/radio/radio-terratec.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-terratec.c	Sat May 19 17:43:06 2001
@@ -50,6 +50,7 @@
 /*******************************************************************/
 
 static int io = CONFIG_RADIO_TERRATEC_PORT; 
+static int radio_nr = -1;
 static int users = 0;
 static spinlock_t lock;
 
@@ -318,7 +319,7 @@
 	
 	spin_lock_init(&lock);
 	
-	if(video_register_device(&terratec_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io,2);
 		return -EINVAL;
@@ -339,6 +340,7 @@
 MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-trust.c linux/drivers/media/radio/radio-trust.c
--- v2.4.4/linux/drivers/media/radio/radio-trust.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-trust.c	Sat May 19 17:43:06 2001
@@ -31,6 +31,7 @@
 #endif
 
 static int io = CONFIG_RADIO_TRUST_PORT; 
+static int radio_nr = -1;
 static int ioval = 0xf;
 static int users = 0;
 static __u16 curvol;
@@ -303,7 +304,7 @@
 		printk(KERN_ERR "trust: port 0x%x already in use\n", io);
 		return -EBUSY;
 	}
-	if(video_register_device(&trust_radio, VFL_TYPE_RADIO)==-1)
+	if(video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 2);
 		return -EINVAL;
@@ -332,6 +333,7 @@
 MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-typhoon.c linux/drivers/media/radio/radio-typhoon.c
--- v2.4.4/linux/drivers/media/radio/radio-typhoon.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-typhoon.c	Sat May 19 17:43:06 2001
@@ -321,10 +321,12 @@
 MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
 MODULE_PARM(mutefreq, "i");
 MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
 static int io = -1;
+static int radio_nr = -1;
 
 #ifdef MODULE
 static unsigned long mutefreq = 0;
@@ -356,7 +358,7 @@
 	}
 
 	typhoon_radio.priv = &typhoon_unit;
-	if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
+	if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) == -1)
 	{
 		release_region(io, 8);
 		return -EINVAL;
diff -u --recursive --new-file v2.4.4/linux/drivers/media/radio/radio-zoltrix.c linux/drivers/media/radio/radio-zoltrix.c
--- v2.4.4/linux/drivers/media/radio/radio-zoltrix.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-zoltrix.c	Sat May 19 17:43:06 2001
@@ -39,6 +39,7 @@
 #endif
 
 static int io = CONFIG_RADIO_ZOLTRIX_PORT;
+static int radio_nr = -1;
 static int users = 0;
 
 struct zol_device {
@@ -365,7 +366,7 @@
 		return -EBUSY;
 	}
 
-	if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1)
+	if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) == -1)
 	{
 		release_region(io, 2);
 		return -EINVAL;
@@ -394,6 +395,7 @@
 MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)");
+MODULE_PARM(radio_nr, "i");
 
 EXPORT_NO_SYMBOLS;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/adv7175.c linux/drivers/media/video/adv7175.c
--- v2.4.4/linux/drivers/media/video/adv7175.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/media/video/adv7175.c	Sat May 19 17:43:06 2001
@@ -0,0 +1,478 @@
+#define DEBUGLEVEL 0
+/* 
+    adv7175 - adv7175a video encoder driver version 0.0.3
+
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+       - some corrections for Pinnacle Systems Inc. DC10plus card.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <linux/types.h>
+#include <linux/wrapper.h>
+
+#include <linux/videodev.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include <linux/i2c-old.h>
+
+#include <linux/video_encoder.h>
+
+#if (DEBUGLEVEL > 0)
+#define DEBUG(x...)  x		/* Debug driver */
+#else
+#define DEBUG(x...)
+#endif
+
+/* ----------------------------------------------------------------------- */
+
+struct adv7175 {
+	struct i2c_bus *bus;
+	int addr;
+	unsigned char reg[128];
+
+	int norm;
+	int input;
+	int enable;
+	int bright;
+	int contrast;
+	int hue;
+	int sat;
+};
+
+#define   I2C_ADV7175        0xd4
+#define   I2C_ADV7176        0x54
+
+static char adv7175_name[] = "adv7175";
+static char adv7176_name[] = "adv7176";
+static char unknown_name[] = "UNKNOWN";
+
+#if (DEBUGLEVEL > 0)
+static char *inputs[] = { "pass_through", "play_back", "color_bar" };
+static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
+#endif
+
+#define I2C_DELAY   10
+
+/* ----------------------------------------------------------------------- */
+
+static int adv7175_write(struct adv7175 *dev, unsigned char subaddr, unsigned char data)
+{
+	int ack;
+
+	LOCK_I2C_BUS(dev->bus);
+
+	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
+	ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
+	dev->reg[subaddr] = data;
+	i2c_stop(dev->bus);
+	UNLOCK_I2C_BUS(dev->bus);
+	return ack;
+}
+
+static unsigned char adv7175_read(struct adv7175 *dev, unsigned char subaddr)
+{
+	unsigned char data;
+
+	LOCK_I2C_BUS(dev->bus);
+
+	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
+	i2c_sendbyte(dev->bus, dev->addr + 1, I2C_DELAY);
+	data = i2c_readbyte(dev->bus, 1);
+	dev->reg[subaddr] = data;
+	i2c_stop(dev->bus);
+	UNLOCK_I2C_BUS(dev->bus);
+	return data;
+}
+
+static int adv7175_write_block(struct adv7175 *dev,
+			       unsigned const char *data, unsigned int len)
+{
+	int ack = 0;
+	unsigned subaddr;
+
+	while (len > 1) {
+		LOCK_I2C_BUS(dev->bus);
+		i2c_start(dev->bus);
+		i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+		ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
+		ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
+		len -= 2;
+		while (len > 1 && *data == ++subaddr) {
+			data++;
+			ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
+			len -= 2;
+		}
+		i2c_stop(dev->bus);
+		UNLOCK_I2C_BUS(dev->bus);
+	}
+	return ack;
+}
+
+/* ----------------------------------------------------------------------- */
+// Output filter:  S-Video  Composite
+
+#define MR050       0x11	//0x09
+#define MR060       0x14	//0x0c
+
+//---------------------------------------------------------------------------
+
+#define TR0MODE     0x46
+#define TR0RST	    0x80
+
+#define TR1CAPT	    0x80
+#define TR1PLAY	    0x00
+
+static const unsigned char init_common[] = {
+
+	0x00, MR050,		/* MR0, PAL enabled */
+	0x01, 0x00,		/* MR1 */
+	0x02, 0x0c,		/* subc. freq. */
+	0x03, 0x8c,		/* subc. freq. */
+	0x04, 0x79,		/* subc. freq. */
+	0x05, 0x26,		/* subc. freq. */
+	0x06, 0x40,		/* subc. phase */
+
+	0x07, TR0MODE,		/* TR0, 16bit */
+	0x08, 0x21,		/*  */
+	0x09, 0x00,		/*  */
+	0x0a, 0x00,		/*  */
+	0x0b, 0x00,		/*  */
+	0x0c, TR1CAPT,		/* TR1 */
+	0x0d, 0x4f,		/* MR2 */
+	0x0e, 0x00,		/*  */
+	0x0f, 0x00,		/*  */
+	0x10, 0x00,		/*  */
+	0x11, 0x00,		/*  */
+	0x12, 0x00,		/* MR3 */
+	0x24, 0x00,		/*  */
+};
+
+static const unsigned char init_pal[] = {
+	0x00, MR050,		/* MR0, PAL enabled */
+	0x01, 0x00,		/* MR1 */
+	0x02, 0x0c,		/* subc. freq. */
+	0x03, 0x8c,		/* subc. freq. */
+	0x04, 0x79,		/* subc. freq. */
+	0x05, 0x26,		/* subc. freq. */
+	0x06, 0x40,		/* subc. phase */
+};
+
+static const unsigned char init_ntsc[] = {
+	0x00, MR060,		/* MR0, NTSC enabled */
+	0x01, 0x00,		/* MR1 */
+	0x02, 0x55,		/* subc. freq. */
+	0x03, 0x55,		/* subc. freq. */
+	0x04, 0x55,		/* subc. freq. */
+	0x05, 0x25,		/* subc. freq. */
+	0x06, 0x1a,		/* subc. phase */
+};
+
+static int adv7175_attach(struct i2c_device *device)
+{
+	int i;
+	struct adv7175 *encoder;
+	char *dname;
+
+	MOD_INC_USE_COUNT;
+
+	device->data = encoder = kmalloc(sizeof(struct adv7175), GFP_KERNEL);
+	if (encoder == NULL) {
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+
+
+	memset(encoder, 0, sizeof(struct adv7175));
+	if ((device->addr == I2C_ADV7175) || (device->addr == (I2C_ADV7175 + 2))) {
+		dname = adv7175_name;
+	} else if ((device->addr == I2C_ADV7176) || (device->addr == (I2C_ADV7176 + 2))) {
+		dname = adv7176_name;
+	} else {
+		// We should never get here!!!
+		dname = unknown_name;
+	}
+	strcpy(device->name, dname);
+	encoder->bus = device->bus;
+	encoder->addr = device->addr;
+	encoder->norm = VIDEO_MODE_PAL;
+	encoder->input = 0;
+	encoder->enable = 1;
+
+	i = adv7175_write_block(encoder, init_common, sizeof(init_common));
+	if (i >= 0) {
+		i = adv7175_write(encoder, 0x07, TR0MODE | TR0RST);
+		i = adv7175_write(encoder, 0x07, TR0MODE);
+		i = adv7175_read(encoder, 0x12);
+		printk(KERN_INFO "%s_attach: %s rev. %d at 0x%02x\n",
+		       device->name, dname, i & 1, device->addr);
+	}
+	if (i < 0) {
+		printk(KERN_ERR "%s_attach: init error %d\n", device->name,
+		       i);
+	}
+
+	return 0;
+}
+
+
+static int adv7175_detach(struct i2c_device *device)
+{
+	kfree(device->data);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int adv7175_command(struct i2c_device *device, unsigned int cmd,
+			   void *arg)
+{
+	struct adv7175 *encoder = device->data;
+
+	switch (cmd) {
+
+	case ENCODER_GET_CAPABILITIES:
+		{
+			struct video_encoder_capability *cap = arg;
+
+			cap->flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC
+			    // | VIDEO_ENCODER_SECAM
+			    // | VIDEO_ENCODER_CCIR
+			    ;
+			cap->inputs = 2;
+			cap->outputs = 1;
+		}
+		break;
+
+	case ENCODER_SET_NORM:
+		{
+			int iarg = *(int *) arg;
+
+			if (encoder->norm != iarg) {
+				switch (iarg) {
+
+				case VIDEO_MODE_NTSC:
+					adv7175_write_block(encoder,
+							    init_ntsc,
+							    sizeof
+							    (init_ntsc));
+					if (encoder->input == 0)
+						adv7175_write(encoder, 0x0d, 0x4f);	// Enable genlock
+					adv7175_write(encoder, 0x07,
+						      TR0MODE | TR0RST);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE);
+					break;
+
+				case VIDEO_MODE_PAL:
+					adv7175_write_block(encoder,
+							    init_pal,
+							    sizeof
+							    (init_pal));
+					if (encoder->input == 0)
+						adv7175_write(encoder, 0x0d, 0x4f);	// Enable genlock
+					adv7175_write(encoder, 0x07,
+						      TR0MODE | TR0RST);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE);
+					break;
+
+				case VIDEO_MODE_SECAM:	// WARNING! ADV7176 does not support SECAM.
+					// This is an attempt to convert SECAM->PAL (typically
+					// it does not work due to genlock: when decoder
+					// is in SECAM and encoder in in PAL the subcarrier
+					// can not be syncronized with horizontal frequency)
+					adv7175_write_block(encoder,
+							    init_pal,
+							    sizeof
+							    (init_pal));
+					if (encoder->input == 0)
+						adv7175_write(encoder, 0x0d, 0x49);	// Disable genlock
+					adv7175_write(encoder, 0x07,
+						      TR0MODE | TR0RST);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE);
+					break;
+				default:
+					printk(KERN_ERR
+					       "%s: illegal norm: %d\n",
+					       device->name, iarg);
+					return -EINVAL;
+
+				}
+				DEBUG(printk
+				      (KERN_INFO "%s: switched to %s\n",
+				       device->name, norms[iarg]));
+				encoder->norm = iarg;
+			}
+		}
+		break;
+
+	case ENCODER_SET_INPUT:
+		{
+			int iarg = *(int *) arg;
+
+			/* RJ: *iarg = 0: input is from SAA7110
+			   *iarg = 1: input is from ZR36060
+			   *iarg = 2: color bar */
+
+			if (encoder->input != iarg) {
+				switch (iarg) {
+
+				case 0:
+					adv7175_write(encoder, 0x01, 0x00);
+					adv7175_write(encoder, 0x0c, TR1CAPT);	/* TR1 */
+					if (encoder->norm ==
+					    VIDEO_MODE_SECAM)
+						adv7175_write(encoder, 0x0d, 0x49);	// Disable genlock
+					else
+						adv7175_write(encoder, 0x0d, 0x4f);	// Enable genlock
+					adv7175_write(encoder, 0x07,
+						      TR0MODE | TR0RST);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE);
+					//udelay(10);
+					break;
+
+				case 1:
+					adv7175_write(encoder, 0x01, 0x00);
+					adv7175_write(encoder, 0x0c, TR1PLAY);	/* TR1 */
+					adv7175_write(encoder, 0x0d, 0x49);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE | TR0RST);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE);
+					//udelay(10);
+					break;
+
+				case 2:
+					adv7175_write(encoder, 0x01, 0x80);
+					adv7175_write(encoder, 0x0d, 0x49);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE | TR0RST);
+					adv7175_write(encoder, 0x07,
+						      TR0MODE);
+					//udelay(10);
+					break;
+
+				default:
+					printk(KERN_ERR
+					       "%s: illegal input: %d\n",
+					       device->name, iarg);
+					return -EINVAL;
+
+				}
+				DEBUG(printk
+				      (KERN_INFO "%s: switched to %s\n",
+				       device->name, inputs[iarg]));
+				encoder->input = iarg;
+			}
+		}
+		break;
+
+	case ENCODER_SET_OUTPUT:
+		{
+			int *iarg = arg;
+
+			/* not much choice of outputs */
+			if (*iarg != 0) {
+				return -EINVAL;
+			}
+		}
+		break;
+
+	case ENCODER_ENABLE_OUTPUT:
+		{
+			int *iarg = arg;
+
+			encoder->enable = !!*iarg;
+			adv7175_write(encoder, 0x61,
+				      (encoder->
+				       reg[0x61] & 0xbf) | (encoder->
+							    enable ? 0x00 :
+							    0x40));
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver i2c_driver_adv7175 = {
+	"adv7175",		/* name */
+	I2C_DRIVERID_VIDEOENCODER,	/* ID */
+	I2C_ADV7175, I2C_ADV7175 + 3,
+
+	adv7175_attach,
+	adv7175_detach,
+	adv7175_command
+};
+
+static struct i2c_driver i2c_driver_adv7176 = {
+	"adv7175",		/* name */
+	I2C_DRIVERID_VIDEOENCODER,	/* ID */
+	I2C_ADV7176, I2C_ADV7176 + 3,
+
+	adv7175_attach,
+	adv7175_detach,
+	adv7175_command
+};
+
+EXPORT_NO_SYMBOLS;
+
+static int adv7175_init(void)
+{
+	int res_adv7175 = 0, res_adv7176 = 0;
+	res_adv7175 = i2c_register_driver(&i2c_driver_adv7175);
+	res_adv7176 = i2c_register_driver(&i2c_driver_adv7176);
+	return (res_adv7175 | res_adv7176);	// Any idea how to make it better?
+}
+
+static void adv7175_exit(void)
+{
+	i2c_unregister_driver(&i2c_driver_adv7176);
+	i2c_unregister_driver(&i2c_driver_adv7175);
+}
+
+module_init(adv7175_init);
+module_exit(adv7175_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/bt819.c linux/drivers/media/video/bt819.c
--- v2.4.4/linux/drivers/media/video/bt819.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/media/video/bt819.c	Sat May 19 17:43:06 2001
@@ -0,0 +1,496 @@
+/* 
+    bt819 - BT819A VideoStream Decoder (Rockwell Part)
+
+    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Modifications for LML33/DC10plus unified driver
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+    
+    This code was modify/ported from the saa7111 driver written
+    by Dave Perks.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+
+#include <linux/videodev.h>
+
+#include <linux/i2c-old.h>
+#include <linux/video_decoder.h>
+
+#define DEBUG(x)       x	/* Debug driver */
+
+/* ----------------------------------------------------------------------- */
+
+struct bt819 {
+	struct i2c_bus *bus;
+	int addr;
+	unsigned char reg[32];
+
+	int initialized;
+	int norm;
+	int input;
+	int enable;
+	int bright;
+	int contrast;
+	int hue;
+	int sat;
+};
+
+struct timing {
+	int hactive;
+	int hdelay;
+	int vactive;
+	int vdelay;
+	int hscale;
+	int vscale;
+};
+
+struct timing timing_data[] = {
+	{864 - 24, 2, 623, 1, 0x0504, 0x0000},
+	{858 - 24, 2, 523, 1, 0x00f8, 0x0000},
+//      { 858-68, 64, 523, 1, 0x00f8, 0x0000 },
+};
+
+#define   I2C_BT819        0x8a
+
+#define   I2C_DELAY   10
+
+/* ----------------------------------------------------------------------- */
+
+static int bt819_write(struct bt819 *dev, unsigned char subaddr,
+		       unsigned char data)
+{
+	int ack;
+
+	LOCK_I2C_BUS(dev->bus);
+	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
+	ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
+	dev->reg[subaddr] = data;
+	i2c_stop(dev->bus);
+	UNLOCK_I2C_BUS(dev->bus);
+	return ack;
+}
+
+static int bt819_setbit(struct bt819 *dev, int subaddr, int bit, int data)
+{
+	return bt819_write(dev, subaddr, (dev->reg[subaddr] & ~(1 << bit)) | (data ? (1 << bit) : 0));
+}
+
+static int bt819_write_block(struct bt819 *dev, unsigned const char *data,
+			     unsigned int len)
+{
+	int ack;
+	unsigned subaddr;
+
+	ack = 0;
+	while (len > 1) {
+		LOCK_I2C_BUS(dev->bus);
+		i2c_start(dev->bus);
+		i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+		ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
+		ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++),
+				 I2C_DELAY);
+		len -= 2;
+		while (len > 1 && *data == ++subaddr) {
+			data++;
+			ack =
+			    i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
+			len -= 2;
+		}
+		i2c_stop(dev->bus);
+		UNLOCK_I2C_BUS(dev->bus);
+	}
+	return ack;
+}
+
+static int bt819_read(struct bt819 *dev, unsigned char subaddr)
+{
+	int data;
+
+	LOCK_I2C_BUS(dev->bus);
+	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
+	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY);
+	data = i2c_readbyte(dev->bus, 1);
+	i2c_stop(dev->bus);
+	UNLOCK_I2C_BUS(dev->bus);
+	return data;
+}
+
+static int bt819_init(struct i2c_device *device)
+{
+	struct bt819 *decoder;
+
+	static unsigned char init[] = {
+		//0x1f, 0x00,     /* Reset */
+		0x01, 0x59,	/* 0x01 input format */
+		0x02, 0x00,	/* 0x02 temporal decimation */
+		0x03, 0x12,	/* 0x03 Cropping msb */
+		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
+		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
+		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
+		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
+		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
+		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
+		0x0a, 0x00,	/* 0x0a Brightness control */
+		0x0b, 0x30,	/* 0x0b Miscellaneous control */
+		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
+		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
+		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
+		0x0f, 0x00,	/* 0x0f Hue control */
+		0x12, 0x04,	/* 0x12 Output Format */
+		0x13, 0x20,	/* 0x13 Vertial Scaling msb 0x60, */
+		0x14, 0x00,	/* 0x14 Vertial Scaling lsb */
+		0x16, 0x04,	/* 0x16 Video Timing Polarity 0x02, */
+		0x18, 0x68,	/* 0x18 AGC Delay */
+		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
+		0x1a, 0x80,	/* 0x1a ADC Interface */
+	};
+
+	struct timing *timing;
+
+	decoder = device->data;
+	timing = &timing_data[decoder->norm];
+
+	init[3 * 2 - 1] = (((timing->vdelay >> 8) & 0x03) << 6) |
+	    (((timing->vactive >> 8) & 0x03) << 4) |
+	    (((timing->hdelay >> 8) & 0x03) << 2) |
+	    ((timing->hactive >> 8) & 0x03);
+	init[4 * 2 - 1] = timing->vdelay & 0xff;
+	init[5 * 2 - 1] = timing->vactive & 0xff;
+	init[6 * 2 - 1] = timing->hdelay & 0xff;
+	init[7 * 2 - 1] = timing->hactive & 0xff;
+	init[8 * 2 - 1] = timing->hscale >> 8;
+	init[9 * 2 - 1] = timing->hscale & 0xff;
+
+	bt819_write(decoder, 0x1f, 0x00);
+	mdelay(1);
+	return bt819_write_block(decoder, init, sizeof(init));
+
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int bt819_attach(struct i2c_device *device)
+{
+	int i;
+	struct bt819 *decoder;
+
+	MOD_INC_USE_COUNT;
+
+	device->data = decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
+	if (decoder == NULL) {
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+
+	memset(decoder, 0, sizeof(struct bt819));
+	strcpy(device->name, "bt819");
+	decoder->bus = device->bus;
+	decoder->addr = device->addr;
+	decoder->norm = VIDEO_MODE_NTSC;
+	decoder->input = 0;
+	decoder->enable = 1;
+	decoder->bright = 32768;
+	decoder->contrast = 32768;
+	decoder->hue = 32768;
+	decoder->sat = 32768;
+	decoder->initialized = 0;
+
+	i = bt819_init(device);
+	if (i < 0) {
+		printk(KERN_ERR "%s: bt819_attach: init status %d\n",
+		       decoder->bus->name, i);
+	} else {
+		printk(KERN_INFO "%s: bt819_attach: chip version %x\n",
+		       decoder->bus->name, bt819_read(decoder,
+						      0x17) & 0x0f);
+	}
+	return 0;
+}
+
+static int bt819_detach(struct i2c_device *device)
+{
+	kfree(device->data);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int bt819_command(struct i2c_device *device, unsigned int cmd, void *arg)
+{
+	int temp;
+
+	struct bt819 *decoder = device->data;
+	//return 0;
+
+	if (!decoder->initialized) {	// First call to bt819_init could be
+		bt819_init(device);	// without #FRST = 0
+		decoder->initialized = 1;
+	}
+
+	switch (cmd) {
+
+	case DECODER_GET_CAPABILITIES:
+		{
+			struct video_decoder_capability *cap = arg;
+
+			cap->flags
+			    = VIDEO_DECODER_PAL
+			    | VIDEO_DECODER_NTSC | VIDEO_DECODER_CCIR;
+			cap->inputs = 8;
+			cap->outputs = 1;
+		}
+		break;
+
+	case DECODER_GET_STATUS:
+		{
+			int *iarg = arg;
+			int status;
+			int res;
+
+			status = bt819_read(decoder, 0x00);
+			res = 0;
+			if ((status & 0x80)) {
+				res |= DECODER_STATUS_GOOD;
+			}
+			switch (decoder->norm) {
+			case VIDEO_MODE_NTSC:
+				res |= DECODER_STATUS_NTSC;
+				break;
+			case VIDEO_MODE_PAL:
+				res |= DECODER_STATUS_PAL;
+				break;
+			default:
+			case VIDEO_MODE_AUTO:
+				if ((status & 0x10)) {
+					res |= DECODER_STATUS_PAL;
+				} else {
+					res |= DECODER_STATUS_NTSC;
+				}
+				break;
+			}
+			res |= DECODER_STATUS_COLOR;
+			*iarg = res;
+
+			DEBUG(printk(KERN_INFO "%s-bt819: get status %x\n",
+				     decoder->bus->name, *iarg));
+		}
+		break;
+
+	case DECODER_SET_NORM:
+		{
+			int *iarg = arg;
+			struct timing *timing;
+
+			DEBUG(printk(KERN_INFO "%s-bt819: set norm %x\n",
+				     decoder->bus->name, *iarg));
+
+			if (*iarg == VIDEO_MODE_NTSC) {
+				bt819_setbit(decoder, 0x01, 0, 1);
+				bt819_setbit(decoder, 0x01, 1, 0);
+				bt819_write(decoder, 0x18, 0x68);
+				bt819_write(decoder, 0x19, 0x5d);
+				//bt819_setbit(decoder, 0x1a,  5, 1);
+				timing = &timing_data[VIDEO_MODE_NTSC];
+			} else {
+				bt819_setbit(decoder, 0x01, 0, 1);
+				bt819_setbit(decoder, 0x01, 1, 1);
+				bt819_write(decoder, 0x18, 0x7f);
+				bt819_write(decoder, 0x19, 0x72);
+				//bt819_setbit(decoder, 0x1a,  5, 0);
+				timing = &timing_data[VIDEO_MODE_PAL];
+			}
+
+			bt819_write(decoder, 0x03,
+				    (((timing->vdelay >> 8) & 0x03) << 6) |
+				    (((timing->
+				       vactive >> 8) & 0x03) << 4) |
+				    (((timing->
+				       hdelay >> 8) & 0x03) << 2) |
+				    ((timing->hactive >> 8) & 0x03));
+			bt819_write(decoder, 0x04, timing->vdelay & 0xff);
+			bt819_write(decoder, 0x05, timing->vactive & 0xff);
+			bt819_write(decoder, 0x06, timing->hdelay & 0xff);
+			bt819_write(decoder, 0x07, timing->hactive & 0xff);
+			bt819_write(decoder, 0x08, timing->hscale >> 8);
+			bt819_write(decoder, 0x09, timing->hscale & 0xff);
+			decoder->norm = *iarg;
+		}
+		break;
+
+	case DECODER_SET_INPUT:
+		{
+			int *iarg = arg;
+
+			DEBUG(printk(KERN_INFO "%s-bt819: set input %x\n",
+				     decoder->bus->name, *iarg));
+
+			if (*iarg < 0 || *iarg > 7) {
+				return -EINVAL;
+			}
+
+			if (decoder->input != *iarg) {
+				decoder->input = *iarg;
+				/* select mode */
+				if (decoder->input == 0) {
+					bt819_setbit(decoder, 0x0b, 6, 0);
+					bt819_setbit(decoder, 0x1a, 1, 1);
+				} else {
+					bt819_setbit(decoder, 0x0b, 6, 1);
+					bt819_setbit(decoder, 0x1a, 1, 0);
+				}
+			}
+		}
+		break;
+
+	case DECODER_SET_OUTPUT:
+		{
+			int *iarg = arg;
+
+			DEBUG(printk(KERN_INFO "%s-bt819: set output %x\n",
+				     decoder->bus->name, *iarg));
+
+			/* not much choice of outputs */
+			if (*iarg != 0) {
+				return -EINVAL;
+			}
+		}
+		break;
+
+	case DECODER_ENABLE_OUTPUT:
+		{
+			int *iarg = arg;
+			int enable = (*iarg != 0);
+
+			DEBUG(printk
+			      (KERN_INFO "%s-bt819: enable output %x\n",
+			       decoder->bus->name, *iarg));
+
+			if (decoder->enable != enable) {
+				decoder->enable = enable;
+
+				if (decoder->enable) {
+					bt819_setbit(decoder, 0x16, 7, 0);
+				} else {
+					bt819_setbit(decoder, 0x16, 7, 1);
+				}
+			}
+		}
+		break;
+
+	case DECODER_SET_PICTURE:
+		{
+			struct video_picture *pic = arg;
+
+			DEBUG(printk
+			      (KERN_INFO
+			       "%s-bt819: set picture brightness %d contrast %d colour %d\n",
+			       decoder->bus->name, pic->brightness,
+			       pic->contrast, pic->colour));
+
+
+			if (decoder->bright != pic->brightness) {
+				/* We want -128 to 127 we get 0-65535 */
+				decoder->bright = pic->brightness;
+				bt819_write(decoder, 0x0a,
+					    (decoder->bright >> 8) - 128);
+			}
+
+			if (decoder->contrast != pic->contrast) {
+				/* We want 0 to 511 we get 0-65535 */
+				decoder->contrast = pic->contrast;
+				bt819_write(decoder, 0x0c,
+					    (decoder->
+					     contrast >> 7) & 0xff);
+				bt819_setbit(decoder, 0x0b, 2,
+					     ((decoder->
+					       contrast >> 15) & 0x01));
+			}
+
+			if (decoder->sat != pic->colour) {
+				/* We want 0 to 511 we get 0-65535 */
+				decoder->sat = pic->colour;
+				bt819_write(decoder, 0x0d,
+					    (decoder->sat >> 7) & 0xff);
+				bt819_setbit(decoder, 0x0b, 1,
+					     ((decoder->
+					       sat >> 15) & 0x01));
+
+				temp = (decoder->sat * 201) / 237;
+				bt819_write(decoder, 0x0e,
+					    (temp >> 7) & 0xff);
+				bt819_setbit(decoder, 0x0b, 0,
+					     (temp >> 15) & 0x01);
+			}
+
+			if (decoder->hue != pic->hue) {
+				/* We want -128 to 127 we get 0-65535 */
+				decoder->hue = pic->hue;
+				bt819_write(decoder, 0x0f,
+					    128 - (decoder->hue >> 8));
+			}
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver i2c_driver_bt819 = {
+	"bt819",		/* name */
+	I2C_DRIVERID_VIDEODECODER,	/* ID */
+	I2C_BT819, I2C_BT819 + 1,
+
+	bt819_attach,
+	bt819_detach,
+	bt819_command
+};
+
+EXPORT_NO_SYMBOLS;
+
+static int bt819_setup(void)
+{
+	return i2c_register_driver(&i2c_driver_bt819);
+}
+
+static void bt819_exit(void)
+{
+	i2c_unregister_driver(&i2c_driver_bt819);
+}
+
+module_init(bt819_setup);
+module_exit(bt819_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/bt856.c linux/drivers/media/video/bt856.c
--- v2.4.4/linux/drivers/media/video/bt856.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/media/video/bt856.c	Sat May 19 17:43:06 2001
@@ -0,0 +1,303 @@
+/* 
+    bt856 - BT856A Digital Video Encoder (Rockwell Part)
+
+    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Modifications for LML33/DC10plus unified driver
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+    
+    This code was modify/ported from the saa7111 driver written
+    by Dave Perks.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <linux/types.h>
+#include <linux/wrapper.h>
+
+#include <linux/videodev.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include <linux/i2c-old.h>
+#include <linux/video_encoder.h>
+
+#define DEBUG(x)   x		/* Debug driver */
+
+/* ----------------------------------------------------------------------- */
+
+struct bt856 {
+	struct i2c_bus *bus;
+	int addr;
+	unsigned char reg[128];
+
+	int norm;
+	int enable;
+	int bright;
+	int contrast;
+	int hue;
+	int sat;
+};
+
+#define   I2C_BT856        0x88
+
+#define I2C_DELAY   10
+
+/* ----------------------------------------------------------------------- */
+
+static int bt856_write(struct bt856 *dev, unsigned char subaddr,
+		       unsigned char data)
+{
+	int ack;
+
+	LOCK_I2C_BUS(dev->bus);
+
+	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
+	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
+	ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
+	dev->reg[subaddr] = data;
+	i2c_stop(dev->bus);
+	UNLOCK_I2C_BUS(dev->bus);
+	return ack;
+}
+
+static int bt856_setbit(struct bt856 *dev, int subaddr, int bit, int data)
+{
+	return bt856_write(dev, subaddr,(dev->reg[subaddr] & ~(1 << bit)) | (data ? (1 << bit) : 0));
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int bt856_attach(struct i2c_device *device)
+{
+	struct bt856 *encoder;
+
+	/* This chip is not on the buz card but at the same address saa7185 */
+	//if (memcmp(device->bus->name, "buz", 3) == 0 || memcmp(device->bus->name, "zr36057", 6) == 0)
+	//   return 1;
+
+	MOD_INC_USE_COUNT;
+	device->data = encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
+
+	if (encoder == NULL) {
+		MOD_DEC_USE_COUNT;
+		return -ENOMEM;
+	}
+
+
+	memset(encoder, 0, sizeof(struct bt856));
+	strcpy(device->name, "bt856");
+	encoder->bus = device->bus;
+	encoder->addr = device->addr;
+	encoder->norm = VIDEO_MODE_NTSC;
+	encoder->enable = 1;
+
+	DEBUG(printk(KERN_INFO "%s-bt856: attach\n", encoder->bus->name));
+
+	bt856_write(encoder, 0xdc, 0x18);
+	bt856_write(encoder, 0xda, 0);
+	bt856_write(encoder, 0xde, 0);
+
+	bt856_setbit(encoder, 0xdc, 3, 1);
+	//bt856_setbit(encoder, 0xdc, 6, 0);
+	bt856_setbit(encoder, 0xdc, 4, 1);
+
+	switch (encoder->norm) {
+
+	case VIDEO_MODE_NTSC:
+		bt856_setbit(encoder, 0xdc, 2, 0);
+		break;
+
+	case VIDEO_MODE_PAL:
+		bt856_setbit(encoder, 0xdc, 2, 1);
+		break;
+	}
+
+	bt856_setbit(encoder, 0xdc, 1, 1);
+	bt856_setbit(encoder, 0xde, 4, 0);
+	bt856_setbit(encoder, 0xde, 3, 1);
+	return 0;
+}
+
+
+static int bt856_detach(struct i2c_device *device)
+{
+	kfree(device->data);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int bt856_command(struct i2c_device *device, unsigned int cmd,
+			 void *arg)
+{
+	struct bt856 *encoder = device->data;
+
+	switch (cmd) {
+
+	case ENCODER_GET_CAPABILITIES:
+		{
+			struct video_encoder_capability *cap = arg;
+
+			DEBUG(printk
+			      (KERN_INFO "%s-bt856: get capabilities\n",
+			       encoder->bus->name));
+
+			cap->flags
+			    = VIDEO_ENCODER_PAL
+			    | VIDEO_ENCODER_NTSC | VIDEO_ENCODER_CCIR;
+			cap->inputs = 2;
+			cap->outputs = 1;
+		}
+		break;
+
+	case ENCODER_SET_NORM:
+		{
+			int *iarg = arg;
+
+			DEBUG(printk(KERN_INFO "%s-bt856: set norm %d\n",
+				     encoder->bus->name, *iarg));
+
+			switch (*iarg) {
+
+			case VIDEO_MODE_NTSC:
+				bt856_setbit(encoder, 0xdc, 2, 0);
+				break;
+
+			case VIDEO_MODE_PAL:
+				bt856_setbit(encoder, 0xdc, 2, 1);
+				bt856_setbit(encoder, 0xda, 0, 0);
+				//bt856_setbit(encoder, 0xda, 0, 1);
+				break;
+
+			default:
+				return -EINVAL;
+
+			}
+			encoder->norm = *iarg;
+		}
+		break;
+
+	case ENCODER_SET_INPUT:
+		{
+			int *iarg = arg;
+
+			DEBUG(printk(KERN_INFO "%s-bt856: set input %d\n",
+				     encoder->bus->name, *iarg));
+
+			/*     We only have video bus.
+			   *iarg = 0: input is from bt819
+			   *iarg = 1: input is from ZR36060 */
+
+			switch (*iarg) {
+
+			case 0:
+				bt856_setbit(encoder, 0xde, 4, 0);
+				bt856_setbit(encoder, 0xde, 3, 1);
+				bt856_setbit(encoder, 0xdc, 3, 1);
+				bt856_setbit(encoder, 0xdc, 6, 0);
+				break;
+			case 1:
+				bt856_setbit(encoder, 0xde, 4, 0);
+				bt856_setbit(encoder, 0xde, 3, 1);
+				bt856_setbit(encoder, 0xdc, 3, 1);
+				bt856_setbit(encoder, 0xdc, 6, 1);
+				break;
+			case 2:	// Color bar
+				bt856_setbit(encoder, 0xdc, 3, 0);
+				bt856_setbit(encoder, 0xde, 4, 1);
+				break;
+			default:
+				return -EINVAL;
+
+			}
+		}
+		break;
+
+	case ENCODER_SET_OUTPUT:
+		{
+			int *iarg = arg;
+
+			DEBUG(printk(KERN_INFO "%s-bt856: set output %d\n",
+				     encoder->bus->name, *iarg));
+
+			/* not much choice of outputs */
+			if (*iarg != 0) {
+				return -EINVAL;
+			}
+		}
+		break;
+
+	case ENCODER_ENABLE_OUTPUT:
+		{
+			int *iarg = arg;
+
+			encoder->enable = !!*iarg;
+
+			DEBUG(printk
+			      (KERN_INFO "%s-bt856: enable output %d\n",
+			       encoder->bus->name, encoder->enable));
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver i2c_driver_bt856 = {
+	"bt856",		/* name */
+	I2C_DRIVERID_VIDEOENCODER,	/* ID */
+	I2C_BT856, I2C_BT856 + 1,
+	bt856_attach,
+	bt856_detach,
+	bt856_command
+};
+
+EXPORT_NO_SYMBOLS;
+
+static int bt856_init(void)
+{
+	return i2c_register_driver(&i2c_driver_bt856);
+}
+
+static void bt856_exit(void)
+{
+	i2c_unregister_driver(&i2c_driver_bt856);
+}
+
+module_init(bt856_init);
+module_exit(bt856_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c
--- v2.4.4/linux/drivers/media/video/bttv-driver.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/bttv-driver.c	Sat May 19 17:43:06 2001
@@ -69,6 +69,9 @@
 static unsigned int gbuffers = 2;
 static unsigned int gbufsize = BTTV_MAX_FBUF;
 static unsigned int combfilter = 0;
+static int video_nr = -1;
+static int radio_nr = -1;
+static int vbi_nr = -1;
 unsigned int bttv_debug = 0;
 unsigned int bttv_verbose = 1;
 unsigned int bttv_gpio = 0;
@@ -94,6 +97,10 @@
 MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
 MODULE_PARM(combfilter,"i");
 
+MODULE_PARM(video_nr,"i");
+MODULE_PARM(radio_nr,"i");
+MODULE_PARM(vbi_nr,"i");
+
 MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards");
 MODULE_AUTHOR("Ralph  Metzler & Marcus Metzler & Gerd Knorr");
 
@@ -2435,16 +2442,16 @@
 {
 	audio(btv, AUDIO_MUTE, 1);
         
-	if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
+	if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
 		return -1;
-	if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI)<0) 
+	if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) 
         {
 	        video_unregister_device(&btv->video_dev);
 		return -1;
 	}
 	if (btv->has_radio)
 	{
-		if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) 
+		if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO, radio_nr)<0) 
                 {
 		        video_unregister_device(&btv->vbi_dev);
 		        video_unregister_device(&btv->video_dev);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/bw-qcam.c linux/drivers/media/video/bw-qcam.c
--- v2.4.4/linux/drivers/media/video/bw-qcam.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/bw-qcam.c	Sat May 19 17:43:06 2001
@@ -83,10 +83,12 @@
 
 static unsigned int maxpoll=250;   /* Maximum busy-loop count for qcam I/O */
 static unsigned int yieldlines=4;  /* Yield after this many during capture */
+static int video_nr = -1;
 
 #if LINUX_VERSION_CODE >= 0x020117
 MODULE_PARM(maxpoll,"i");
 MODULE_PARM(yieldlines,"i");   
+MODULE_PARM(video_nr,"i");
 #endif
 
 extern __inline__ int read_lpstatus(struct qcam_device *q)
@@ -962,7 +964,7 @@
 	
 	printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
 	
-	if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
+	if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
 	{
 		parport_unregister_device(qcam->pdev);
 		kfree(qcam);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/c-qcam.c linux/drivers/media/video/c-qcam.c
--- v2.4.4/linux/drivers/media/video/c-qcam.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/c-qcam.c	Sat May 19 17:43:06 2001
@@ -69,6 +69,7 @@
 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
 static int probe = 2;
 static int force_rgb = 0;
+static int video_nr = -1;
 
 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
 {
@@ -815,7 +816,7 @@
 
 	parport_release(qcam->pdev);
 	
-	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
+	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
 	{
 		printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
 		       qcam->pport->name);
@@ -881,6 +882,7 @@
 MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "i");
 MODULE_PARM(probe, "i");
 MODULE_PARM(force_rgb, "i");
+MODULE_PARM(video_nr,"i");
 
 module_init(cqcam_init);
 module_exit(cqcam_cleanup);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/cpia.c linux/drivers/media/video/cpia.c
--- v2.4.4/linux/drivers/media/video/cpia.c	Fri Apr  6 10:42:55 2001
+++ linux/drivers/media/video/cpia.c	Sat May 19 17:43:06 2001
@@ -52,7 +52,10 @@
 extern int cpia_usb_init(void);
 #endif
 
+static int video_nr = -1;
+
 #ifdef MODULE
+MODULE_PARM(video_nr,"i");
 MODULE_AUTHOR("Scott J. Bertin <sbertin@mindspring.com> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <jerdfelt@valinux.com>");
 MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
 MODULE_SUPPORTED_DEVICE("video");
@@ -540,6 +543,8 @@
 static int cpia_write_proc(struct file *file, const char *buffer,
                            unsigned long count, void *data)
 {
+	return -EINVAL;
+#if 0
 	struct cam_data *cam = data;
 	struct cam_params new_params;
 	int retval, find_colon;
@@ -1250,6 +1255,7 @@
 	up(&cam->param_lock);
 	
 	return retval;
+#endif
 }
 
 static void create_proc_cpia_cam(struct cam_data *cam)
@@ -3180,7 +3186,7 @@
 	camera->lowlevel_data = lowlevel;
 	
 	/* register v4l device */
-	if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER) == -1) {
+	if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
 		kfree(camera);
 		unlock_kernel();
 		printk(KERN_DEBUG "video_register_device failed\n");
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/planb.c linux/drivers/media/video/planb.c
--- v2.4.4/linux/drivers/media/video/planb.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/planb.c	Sat May 19 17:43:06 2001
@@ -69,9 +69,11 @@
 static volatile struct planb_registers *planb_regs;
 
 static int def_norm = PLANB_DEF_NORM;	/* default norm */
+static int video_nr = -1;
 
 MODULE_PARM(def_norm, "i");
 MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
+MODULE_PARM(video_nr,"i");
 
 /* ------------------ PlanB Exported Functions ------------------ */
 static long planb_write(struct video_device *, const char *, unsigned long, int);
@@ -2168,7 +2170,7 @@
 	pb->intr_mask = PLANB_FRM_IRQ;
 	enable_irq(pb->irq);
 
-	if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER)<0)
+	if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER, video_nr)<0)
 		return -1;
 
 	return 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/pms.c linux/drivers/media/video/pms.c
--- v2.4.4/linux/drivers/media/video/pms.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/pms.c	Thu May 24 15:14:08 2001
@@ -41,6 +41,7 @@
 	struct video_picture picture;
 	int height;
 	int width;
+	struct semaphore lock;
 };
 
 struct i2c_info
@@ -64,6 +65,7 @@
 static int io_port		=	0x250;
 static int data_port		=	0x251;
 static int mem_base		=	0xC8000;
+static int video_nr             =       -1;
 
 	
 
@@ -738,8 +740,10 @@
 				return -EFAULT;
 			if(v<0 || v>3)
 				return -EINVAL;
+			down(&pd->lock);		
 			pms_videosource(v&1);
 			pms_vcrinput(v>>1);
+			up(&pd->lock);
 			return 0;
 		}
 		case VIDIOCGTUNER:
@@ -779,6 +783,7 @@
 				return -EFAULT;
 			if(v.tuner)
 				return -EINVAL;
+			down(&pd->lock);
 			switch(v.mode)
 			{
 				case VIDEO_MODE_AUTO:
@@ -802,8 +807,10 @@
 					pms_format(2);
 					break;
 				default:
+					up(&pd->lock);
 					return -EINVAL;
 			}
+			up(&pd->lock);
 			return 0;
 		}
 		case VIDIOCGPICT:
@@ -827,10 +834,12 @@
 			 *	Now load the card.
 			 */
 
+			down(&pd->lock);
 			pms_brightness(p.brightness>>8);
 			pms_hue(p.hue>>8);
 			pms_colour(p.colour>>8);
 			pms_contrast(p.contrast>>8);	
+			up(&pd->lock);
 			return 0;
 		}
 		case VIDIOCSWIN:
@@ -848,8 +857,9 @@
 				return -EINVAL;
 			pd->width=vw.width;
 			pd->height=vw.height;
+			down(&pd->lock);
 			pms_resolution(pd->width, pd->height);
-			/* Ok we figured out what to use from our wide choice */
+			up(&pd->lock);			/* Ok we figured out what to use from our wide choice */
 			return 0;
 		}
 		case VIDIOCGWIN:
@@ -892,8 +902,9 @@
 	struct pms_device *pd=(struct pms_device *)v;
 	int len;
 	
-	/* FIXME: semaphore this */
+	down(&pd->lock);
 	len=pms_capture(pd, buf, (pd->picture.depth==16)?0:1,count);
+	up(&pd->lock);
 	return len;
 }
 
@@ -1036,15 +1047,17 @@
 		return -ENODEV;
 	}
 	memcpy(&pms_device, &pms_template, sizeof(pms_template));
+	init_MUTEX(&pms_device.lock);
 	pms_device.height=240;
 	pms_device.width=320;
 	pms_swsense(75);
 	pms_resolution(320,240);
-	return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER);
+	return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER, video_nr);
 }
 
 MODULE_PARM(io_port,"i");
 MODULE_PARM(mem_base,"i");
+MODULE_PARM(video_nr,"i");
 
 static void __exit shutdown_mediavision(void)
 {
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/saa5249.c linux/drivers/media/video/saa5249.c
--- v2.4.4/linux/drivers/media/video/saa5249.c	Fri Nov 17 17:56:51 2000
+++ linux/drivers/media/video/saa5249.c	Sat May 19 17:43:06 2001
@@ -205,7 +205,7 @@
 	 *	Register it
 	 */
 
-	if((err=video_register_device(vd, VFL_TYPE_VTX))<0)
+	if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0)
 	{
 		kfree(t);
 		kfree(vd);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/saa7110.c linux/drivers/media/video/saa7110.c
--- v2.4.4/linux/drivers/media/video/saa7110.c	Wed Dec 29 17:08:55 1999
+++ linux/drivers/media/video/saa7110.c	Sat May 19 17:43:06 2001
@@ -19,6 +19,7 @@
 */
 
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -398,7 +399,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-struct i2c_driver i2c_driver_saa7110 =
+static struct i2c_driver i2c_driver_saa7110 =
 {
 	"saa7110",			/* name */
 
@@ -412,18 +413,16 @@
 
 EXPORT_NO_SYMBOLS;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int saa7110_init(void)
-#endif
+static int saa7110_init(void)
 {
 	return i2c_register_driver(&i2c_driver_saa7110);
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void saa7110_exit(void)
 {
 	i2c_unregister_driver(&i2c_driver_saa7110);
 }
-#endif
+
+
+module_init(saa7110_init);
+module_exit(saa7110_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/saa7111.c linux/drivers/media/video/saa7111.c
--- v2.4.4/linux/drivers/media/video/saa7111.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/media/video/saa7111.c	Sat May 19 17:43:06 2001
@@ -1,46 +1,41 @@
 /* 
-   saa7111 - Philips SAA7111A video decoder driver version 0.0.3
+    saa7111 - Philips SAA7111A video decoder driver version 0.0.3
 
-   Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
 
-   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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+    Slight changes for video timing and attachment output by
+    Wolfgang Scherr <scherr@net4you.net>
+    
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
 
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/slab.h>
+#include <linux/malloc.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
-#include <linux/types.h>
-#include <linux/wrapper.h>
 
 #include <linux/videodev.h>
 #include <linux/version.h>
-#include <asm/uaccess.h>
-
 #include <linux/i2c-old.h>
+
 #include <linux/video_decoder.h>
 
 #define DEBUG(x)		/* Debug driver */
@@ -67,7 +62,8 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int saa7111_write(struct saa7111 *dev, unsigned char subaddr, unsigned char data)
+static int saa7111_write(struct saa7111 *dev, unsigned char subaddr,
+			 unsigned char data)
 {
 	int ack;
 
@@ -82,9 +78,10 @@
 	return ack;
 }
 
-static int saa7111_write_block(struct saa7111 *dev, unsigned const char *data, unsigned int len)
+static int saa7111_write_block(struct saa7111 *dev,
+	       unsigned const char *data, unsigned int len)
 {
-	int ack = 0;
+	int ack = -1;
 	unsigned subaddr;
 
 	while (len > 1) {
@@ -96,7 +93,10 @@
 		len -= 2;
 		while (len > 1 && *data == ++subaddr) {
 			data++;
-			ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
+			ack =
+			    i2c_sendbyte(dev->bus,
+					 (dev->reg[subaddr] =
+					  *data++), I2C_DELAY);
 			len -= 2;
 		}
 		i2c_stop(dev->bus);
@@ -128,20 +128,19 @@
 	int i;
 	struct saa7111 *decoder;
 
-	static const unsigned char init[] =
-	{
+	static const unsigned char init[] = {
 		0x00, 0x00,	/* 00 - ID byte */
 		0x01, 0x00,	/* 01 - reserved */
 
-	/*front end */
+		/*front end */
 		0x02, 0xd0,	/* 02 - FUSE=3, GUDL=2, MODE=0 */
 		0x03, 0x23,	/* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
 		0x04, 0x00,	/* 04 - GAI1=256 */
 		0x05, 0x00,	/* 05 - GAI2=256 */
 
-	/* decoder */
-		0x06, 0xf6,	/* 06 - HSB at  13(50Hz) /  17(60Hz) pixels after end of last line */
-		0x07, 0xdd,	/* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */
+		/* decoder */
+		0x06, 0xf3,	/* 06 - HSB at  13(50Hz) /  17(60Hz) pixels after end of last line */
+		0x07, 0x13,	/* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */
 		0x08, 0xc8,	/* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, HPLL=0, VNOI=0 */
 		0x09, 0x01,	/* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, UPTCV=0, APER=1 */
 		0x0a, 0x80,	/* 0a - BRIG=128 */
@@ -160,11 +159,14 @@
 		0x17, 0x00,	/* 17 - VBI */
 	};
 
+	MOD_INC_USE_COUNT;
+
 	device->data = decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
-	if (decoder == NULL) {
+	if (decoder == NULL)
+	{
+		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
-	MOD_INC_USE_COUNT;
 
 	memset(decoder, 0, sizeof(struct saa7111));
 	strcpy(device->name, "saa7111");
@@ -180,9 +182,11 @@
 
 	i = saa7111_write_block(decoder, init, sizeof(init));
 	if (i < 0) {
-		printk(KERN_ERR "%s_attach: init status %d\n", device->name, i);
+		printk(KERN_ERR "%s_attach: init status %d\n",
+		       device->name, i);
 	} else {
-		printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7111_read(decoder, 0x00));
+		printk(KERN_INFO "%s_attach: chip version %x\n",
+		       device->name, saa7111_read(decoder, 0x00) >> 4);
 	}
 	return 0;
 }
@@ -195,7 +199,8 @@
 	return 0;
 }
 
-static int saa7111_command(struct i2c_device *device, unsigned int cmd, void *arg)
+static int saa7111_command(struct i2c_device *device, unsigned int cmd,
+			   void *arg)
 {
 	struct saa7111 *decoder = device->data;
 
@@ -209,9 +214,12 @@
 			for (i = 0; i < 32; i += 16) {
 				int j;
 
-				printk("KERN_DEBUG %s: %03x", device->name, i);
+				printk("KERN_DEBUG %s: %03x", device->name,
+				       i);
 				for (j = 0; j < 16; ++j) {
-					printk(" %02x", saa7111_read(decoder, i + j));
+					printk(" %02x",
+					       saa7111_read(decoder,
+							    i + j));
 				}
 				printk("\n");
 			}
@@ -226,8 +234,7 @@
 			cap->flags
 			    = VIDEO_DECODER_PAL
 			    | VIDEO_DECODER_NTSC
-			    | VIDEO_DECODER_AUTO
-			    | VIDEO_DECODER_CCIR;
+			    | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
 			cap->inputs = 8;
 			cap->outputs = 1;
 		}
@@ -274,15 +281,21 @@
 			switch (*iarg) {
 
 			case VIDEO_MODE_NTSC:
-				saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x40);
+				saa7111_write(decoder, 0x08,
+					      (decoder->
+					       reg[0x08] & 0x3f) | 0x40);
 				break;
 
 			case VIDEO_MODE_PAL:
-				saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x00);
+				saa7111_write(decoder, 0x08,
+					      (decoder->
+					       reg[0x08] & 0x3f) | 0x00);
 				break;
 
 			case VIDEO_MODE_AUTO:
-				saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x80);
+				saa7111_write(decoder, 0x08,
+					      (decoder->
+					       reg[0x08] & 0x3f) | 0x80);
 				break;
 
 			default:
@@ -300,12 +313,20 @@
 			if (*iarg < 0 || *iarg > 7) {
 				return -EINVAL;
 			}
+
 			if (decoder->input != *iarg) {
 				decoder->input = *iarg;
 				/* select mode */
-				saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8) | decoder->input);
+				saa7111_write(decoder, 0x02,
+					      (decoder->
+					       reg[0x02] & 0xf8) |
+					      decoder->input);
 				/* bypass chrominance trap for modes 4..7 */
-				saa7111_write(decoder, 0x09, (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0));
+				saa7111_write(decoder, 0x09,
+					      (decoder->
+					       reg[0x09] & 0x7f) |
+					      ((decoder->input >
+						3) ? 0x80 : 0));
 			}
 		}
 		break;
@@ -330,19 +351,34 @@
 				decoder->enable = enable;
 
 // RJ: If output should be disabled (for playing videos), we also need a open PLL.
-				//     The input is set to 0 (where no input source is connected), although this
-				//     is not necessary.
-				//
-				//     If output should be enabled, we have to reverse the above.
+//     The input is set to 0 (where no input source is connected), although this
+//     is not necessary.
+//
+//     If output should be enabled, we have to reverse the above.
 
 				if (decoder->enable) {
-					saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8) | decoder->input);
-					saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0xfb));
-					saa7111_write(decoder, 0x11, (decoder->reg[0x11] & 0xf3) | 0x0c);
+					saa7111_write(decoder, 0x02,
+						      (decoder->
+						       reg[0x02] & 0xf8) |
+						      decoder->input);
+					saa7111_write(decoder, 0x08,
+						      (decoder->
+						       reg[0x08] & 0xfb));
+					saa7111_write(decoder, 0x11,
+						      (decoder->
+						       reg[0x11] & 0xf3) |
+						      0x0c);
 				} else {
-					saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8));
-					saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0xfb) | 0x04);
-					saa7111_write(decoder, 0x11, (decoder->reg[0x11] & 0xf3));
+					saa7111_write(decoder, 0x02,
+						      (decoder->
+						       reg[0x02] & 0xf8));
+					saa7111_write(decoder, 0x08,
+						      (decoder->
+						       reg[0x08] & 0xfb) |
+						      0x04);
+					saa7111_write(decoder, 0x11,
+						      (decoder->
+						       reg[0x11] & 0xf3));
 				}
 			}
 		}
@@ -355,22 +391,26 @@
 			if (decoder->bright != pic->brightness) {
 				/* We want 0 to 255 we get 0-65535 */
 				decoder->bright = pic->brightness;
-				saa7111_write(decoder, 0x0a, decoder->bright >> 8);
+				saa7111_write(decoder, 0x0a,
+					      decoder->bright >> 8);
 			}
 			if (decoder->contrast != pic->contrast) {
 				/* We want 0 to 127 we get 0-65535 */
 				decoder->contrast = pic->contrast;
-				saa7111_write(decoder, 0x0b, decoder->contrast >> 9);
+				saa7111_write(decoder, 0x0b,
+					      decoder->contrast >> 9);
 			}
 			if (decoder->sat != pic->colour) {
 				/* We want 0 to 127 we get 0-65535 */
 				decoder->sat = pic->colour;
-				saa7111_write(decoder, 0x0c, decoder->sat >> 9);
+				saa7111_write(decoder, 0x0c,
+					      decoder->sat >> 9);
 			}
 			if (decoder->hue != pic->hue) {
 				/* We want -128 to 127 we get 0-65535 */
 				decoder->hue = pic->hue;
-				saa7111_write(decoder, 0x0d, (decoder->hue - 32768) >> 8);
+				saa7111_write(decoder, 0x0d,
+					      (decoder->hue - 32768) >> 8);
 			}
 		}
 		break;
@@ -384,8 +424,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-struct i2c_driver i2c_driver_saa7111 =
-{
+static struct i2c_driver i2c_driver_saa7111 = {
 	"saa7111",		/* name */
 	I2C_DRIVERID_VIDEODECODER,	/* ID */
 	I2C_SAA7111, I2C_SAA7111 + 1,
@@ -397,22 +436,15 @@
 
 EXPORT_NO_SYMBOLS;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int saa7111_init(void)
-#endif
+static int saa7111_init(void)
 {
 	return i2c_register_driver(&i2c_driver_saa7111);
 }
 
-
-
-#ifdef MODULE
-
-void cleanup_module(void)
+static void saa7111_exit(void)
 {
 	i2c_unregister_driver(&i2c_driver_saa7111);
 }
 
-#endif
+module_init(saa7111_init);
+module_exit(saa7111_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/saa7185.c linux/drivers/media/video/saa7185.c
--- v2.4.4/linux/drivers/media/video/saa7185.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/media/video/saa7185.c	Sat May 19 17:43:06 2001
@@ -1,30 +1,34 @@
 /* 
-   saa7185 - Philips SAA7185B video encoder driver version 0.0.3
+    saa7185 - Philips SAA7185B video encoder driver version 0.0.3
 
-   Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
 
-   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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+    Slight changes for video timing and attachment output by
+    Wolfgang Scherr <scherr@net4you.net>
+    
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
 
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/slab.h>
+#include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/signal.h>
@@ -41,9 +45,10 @@
 #include <asm/uaccess.h>
 
 #include <linux/i2c-old.h>
+
 #include <linux/video_encoder.h>
 
-#define DEBUG(x)   x		/* Debug driver */
+#define DEBUG(x)		/* Debug driver */
 
 /* ----------------------------------------------------------------------- */
 
@@ -66,13 +71,31 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int saa7185_write(struct saa7185 *dev, unsigned char subaddr, unsigned char data)
+static int saa7185_read(struct saa7185 *dev)
 {
 	int ack;
 
 	LOCK_I2C_BUS(dev->bus);
 
 	i2c_start(dev->bus);
+	i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY);
+	ack = i2c_readbyte(dev->bus, 1);
+	i2c_stop(dev->bus);
+	UNLOCK_I2C_BUS(dev->bus);
+	return ack;
+}
+
+static int saa7185_write(struct saa7185 *dev, unsigned char subaddr,
+			 unsigned char data)
+{
+	int ack;
+
+	DEBUG(printk
+	      (KERN_DEBUG "SAA7185: %02x set to %02x\n", subaddr, data);
+	    )
+	    LOCK_I2C_BUS(dev->bus);
+
+	i2c_start(dev->bus);
 	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
 	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
 	ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
@@ -82,9 +105,10 @@
 	return ack;
 }
 
-static int saa7185_write_block(struct saa7185 *dev, unsigned const char *data, unsigned int len)
+static int saa7185_write_block(struct saa7185 *dev,
+			       unsigned const char *data, unsigned int len)
 {
-	int ack = 0;
+	int ack = -1;
 	unsigned subaddr;
 
 	while (len > 1) {
@@ -107,8 +131,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-static const unsigned char init_common[] =
-{
+static const unsigned char init_common[] = {
 	0x3a, 0x0f,		/* CBENB=0, V656=0, VY2C=1, YUV2C=1, MY2C=1, MUV2C=1 */
 
 	0x42, 0x6b,		/* OVLY0=107 */
@@ -155,7 +178,7 @@
 	0x6c, 0x20,		/* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0, CBLF=0, ORCV2=0, PRCV2=0 */
 	0x6d, 0x00,		/* SRCM1=0, CCEN=0 */
 
-	0x6e, 0x0e,		/* HTRIG=0x00e, approx. centered, at least for PAL */
+	0x6e, 0x0e,		/* HTRIG=0x005, approx. centered, at least for PAL */
 	0x6f, 0x00,		/* HTRIG upper bits */
 	0x70, 0x20,		/* PHRES=0, SBLN=1, VTRIG=0 */
 
@@ -182,8 +205,7 @@
 	0x7d, 0x20,		/* LAL=244, FAL=22 */
 };
 
-static const unsigned char init_pal[] =
-{
+static const unsigned char init_pal[] = {
 	0x61, 0x1e,		/* FISE=0, PAL=1, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */
 	0x62, 0xc8,		/* DECTYP=1, BSTA=72 */
 	0x63, 0xcb,		/* FSC0 */
@@ -192,8 +214,7 @@
 	0x66, 0x2a,		/* FSC3 */
 };
 
-static const unsigned char init_ntsc[] =
-{
+static const unsigned char init_ntsc[] = {
 	0x61, 0x1d,		/* FISE=1, PAL=0, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */
 	0x62, 0xe6,		/* DECTYP=1, BSTA=102 */
 	0x63, 0x1f,		/* FSC0 */
@@ -207,11 +228,14 @@
 	int i;
 	struct saa7185 *encoder;
 
+	MOD_INC_USE_COUNT;
+	
 	device->data = encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
 	if (encoder == NULL) {
+		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
-	MOD_INC_USE_COUNT;
+
 
 	memset(encoder, 0, sizeof(struct saa7185));
 	strcpy(device->name, "saa7185");
@@ -222,23 +246,33 @@
 
 	i = saa7185_write_block(encoder, init_common, sizeof(init_common));
 	if (i >= 0) {
-		i = saa7185_write_block(encoder, init_ntsc, sizeof(init_ntsc));
+		i = saa7185_write_block(encoder, init_ntsc,
+					sizeof(init_ntsc));
 	}
 	if (i < 0) {
-		printk(KERN_ERR "%s_attach: init error %d\n", device->name, i);
+		printk(KERN_ERR "%s_attach: init error %d\n", device->name,
+		       i);
+	} else {
+		printk(KERN_INFO "%s_attach: chip version %d\n",
+		       device->name, saa7185_read(encoder) >> 5);
 	}
+
 	return 0;
 }
 
 
 static int saa7185_detach(struct i2c_device *device)
 {
-	kfree(device->data);
+	struct saa7185 *encoder = device->data;
+	saa7185_write(encoder, 0x61, (encoder->reg[0x61]) | 0x40);	/* SW: output off is active */
+	//saa7185_write(encoder, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
+	kfree(encoder);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
-static int saa7185_command(struct i2c_device *device, unsigned int cmd, void *arg)
+static int saa7185_command(struct i2c_device *device, unsigned int cmd,
+			   void *arg)
 {
 	struct saa7185 *encoder = device->data;
 
@@ -251,8 +285,7 @@
 			cap->flags
 			    = VIDEO_ENCODER_PAL
 			    | VIDEO_ENCODER_NTSC
-			    | VIDEO_ENCODER_SECAM
-			    | VIDEO_ENCODER_CCIR;
+			    | VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR;
 			cap->inputs = 1;
 			cap->outputs = 1;
 		}
@@ -265,11 +298,13 @@
 			switch (*iarg) {
 
 			case VIDEO_MODE_NTSC:
-				saa7185_write_block(encoder, init_ntsc, sizeof(init_ntsc));
+				saa7185_write_block(encoder, init_ntsc,
+						    sizeof(init_ntsc));
 				break;
 
 			case VIDEO_MODE_PAL:
-				saa7185_write_block(encoder, init_pal, sizeof(init_pal));
+				saa7185_write_block(encoder, init_pal,
+						    sizeof(init_pal));
 				break;
 
 			case VIDEO_MODE_SECAM:
@@ -285,12 +320,6 @@
 		{
 			int *iarg = arg;
 
-#if 0
-			/* not much choice of inputs */
-			if (*iarg != 0) {
-				return -EINVAL;
-			}
-#else
 			/* RJ: *iarg = 0: input is from SA7111
 			   *iarg = 1: input is from ZR36060 */
 
@@ -298,19 +327,25 @@
 
 			case 0:
 				/* Switch RTCE to 1 */
-				saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
+				saa7185_write(encoder, 0x61,
+					      (encoder->
+					       reg[0x61] & 0xf7) | 0x08);
+				saa7185_write(encoder, 0x6e, 0x01);
 				break;
 
 			case 1:
 				/* Switch RTCE to 0 */
-				saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
+				saa7185_write(encoder, 0x61,
+					      (encoder->
+					       reg[0x61] & 0xf7) | 0x00);
+				/* SW: a slight sync problem... */
+				saa7185_write(encoder, 0x6e, 0x00);
 				break;
 
 			default:
 				return -EINVAL;
 
 			}
-#endif
 		}
 		break;
 
@@ -330,7 +365,11 @@
 			int *iarg = arg;
 
 			encoder->enable = !!*iarg;
-			saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xbf) | (encoder->enable ? 0x00 : 0x40));
+			saa7185_write(encoder, 0x61,
+				      (encoder->
+				       reg[0x61] & 0xbf) | (encoder->
+							    enable ? 0x00 :
+							    0x40));
 		}
 		break;
 
@@ -343,8 +382,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-struct i2c_driver i2c_driver_saa7185 =
-{
+static struct i2c_driver i2c_driver_saa7185 = {
 	"saa7185",		/* name */
 	I2C_DRIVERID_VIDEOENCODER,	/* ID */
 	I2C_SAA7185, I2C_SAA7185 + 1,
@@ -356,22 +394,15 @@
 
 EXPORT_NO_SYMBOLS;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int saa7185_init(void)
-#endif
+static int saa7185_init(void)
 {
 	return i2c_register_driver(&i2c_driver_saa7185);
 }
 
-
-
-#ifdef MODULE
-
-void cleanup_module(void)
+static void saa7185_exit(void)
 {
 	i2c_unregister_driver(&i2c_driver_saa7185);
 }
 
-#endif
+module_init(saa7185_init);
+module_exit(saa7185_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/stradis.c linux/drivers/media/video/stradis.c
--- v2.4.4/linux/drivers/media/video/stradis.c	Thu Apr 19 09:34:05 2001
+++ linux/drivers/media/video/stradis.c	Sat May 19 17:43:06 2001
@@ -63,6 +63,9 @@
 
 static int saa_num = 0;		/* number of SAA7146s in use */
 
+static int video_nr = -1;
+MODULE_PARM(video_nr,"i");
+
 #define nDebNormal	0x00480000
 #define nDebNoInc	0x00480000
 #define nDebVideo	0xd0480000
@@ -2073,7 +2076,7 @@
 		return result;
 	}
 	pci_set_master(dev);
-	if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0) {
+	if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) {
 		iounmap(saa->saa7146_mem);
 		return -1;
 	}
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/tda9875.c linux/drivers/media/video/tda9875.c
--- v2.4.4/linux/drivers/media/video/tda9875.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/media/video/tda9875.c	Sat May 19 17:43:06 2001
@@ -80,8 +80,8 @@
 #define TDA9875_DACOS       0x13  /*DAC i/o select (ADC) 0b0000100*/
 #define TDA9875_LOSR        0x16  /*Line output select regirter 0b0100 0001*/
 
-#define TDA9875_CH1V        0x0c  /*Chanel 1 volume (mute)*/
-#define TDA9875_CH2V        0x0d  /*Chanel 2 volume (mute)*/
+#define TDA9875_CH1V        0x0c  /*Channel 1 volume (mute)*/
+#define TDA9875_CH2V        0x0d  /*Channel 2 volume (mute)*/
 #define TDA9875_SC1         0x14  /*SCART 1 in (mono)*/
 #define TDA9875_SC2         0x15  /*SCART 2 in (mono)*/
 
@@ -182,8 +182,8 @@
 	tda9875_write(client, TDA9875_SC1, 0x00 );    /* SCART 1 (SC1)*/
 	tda9875_write(client, TDA9875_SC2, 0x01 );    /* SCART 2 (sc2)*/
         
-	tda9875_write(client, TDA9875_CH1V, 0x10 );  /* Chanel volume 1 mute*/
-	tda9875_write(client, TDA9875_CH2V, 0x10 );  /* Chanel volume 2 mute */
+	tda9875_write(client, TDA9875_CH1V, 0x10 );  /* Channel volume 1 mute*/
+	tda9875_write(client, TDA9875_CH2V, 0x10 );  /* Channel volume 2 mute */
 	tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/
 	tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/
 	tda9875_write(client, TDA9875_LOSR, 0x00 );  /* line out (in:mono)*/
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/tvaudio.c linux/drivers/media/video/tvaudio.c
--- v2.4.4/linux/drivers/media/video/tvaudio.c	Mon Feb 19 14:43:36 2001
+++ linux/drivers/media/video/tvaudio.c	Tue May  1 16:05:00 2001
@@ -124,7 +124,7 @@
 
 
 /* ---------------------------------------------------------------------- */
-/* i2c adresses                                                           */
+/* i2c addresses                                                           */
 
 static unsigned short normal_i2c[] = {
 	I2C_TDA8425   >> 1,
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/videodev.c linux/drivers/media/video/videodev.c
--- v2.4.4/linux/drivers/media/video/videodev.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/videodev.c	Sat May 19 18:13:15 2001
@@ -30,6 +30,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/semaphore.h>
 
 #include <linux/kmod.h>
 
@@ -394,7 +395,7 @@
 		if (vfd == d->vdev) {
 			remove_proc_entry(d->name, video_dev_proc_entry);
 			list_del (&d->proc_list);
-			kfree (d);
+			kfree(d);
 			break;
 		}
 	}
@@ -406,9 +407,10 @@
 
 /**
  *	video_register_device - register video4linux devices
- *	@vfd: video device structure we want to register
+ *	@vfd:  video device structure we want to register
  *	@type: type of device to register
- *	FIXME: needs a semaphore on 2.3.x
+ *	@nr:   which device number (0 == /dev/video0, 1 == /dev/video1, ...
+ *             -1 == first free)
  *	
  *	The registration code assigns minor numbers based on the type
  *	requested. -ENFILE is returned in all the device slots for this
@@ -427,14 +429,17 @@
  *
  *	%VFL_TYPE_RADIO - A radio card	
  */
- 
-int video_register_device(struct video_device *vfd, int type)
+
+static DECLARE_MUTEX(videodev_register_lock);
+
+int video_register_device(struct video_device *vfd, int type, int nr)
 {
 	int i=0;
 	int base;
 	int err;
 	int end;
 	char *name_base;
+	char name[16];
 	
 	switch(type)
 	{
@@ -461,49 +466,58 @@
 		default:
 			return -1;
 	}
-	
-	for(i=base;i<end;i++)
-	{
-		if(video_device[i]==NULL)
-		{
-			char name[16];
 
-			video_device[i]=vfd;
-			vfd->minor=i;
-			/* The init call may sleep so we book the slot out
-			   then call */
-			MOD_INC_USE_COUNT;
-			if(vfd->initialize)
-			{
-				err=vfd->initialize(vfd);
-				if(err<0)
-				{
-					video_device[i]=NULL;
-					MOD_DEC_USE_COUNT;
-					return err;
-				}
-			}
-			sprintf (name, "v4l/%s%d", name_base, i - base);
-			/*
-			 *	Start the device root only. Anything else
-			 *	has serious privacy issues.
-			 */
-			vfd->devfs_handle =
-			    devfs_register (NULL, name, DEVFS_FL_DEFAULT,
-					    VIDEO_MAJOR, vfd->minor,
-					    S_IFCHR | S_IRUSR | S_IWUSR,
-					    &video_fops, NULL);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-			sprintf (name, "%s%d", name_base, i - base);
-			videodev_proc_create_dev (vfd, name);
-#endif
-			
-
-			return 0;
+	/* pick a minor number */
+	down(&videodev_register_lock);
+	if (-1 == nr) {
+		/* use first free */
+		for(i=base;i<end;i++)
+			if (NULL == video_device[i])
+				break;
+		if (i == end) {
+			up(&videodev_register_lock);
+			return -ENFILE;
+		}
+	} else {
+		/* use the one the driver asked for */
+		i = base+nr;
+		if (NULL != video_device[i]) {
+			up(&videodev_register_lock);
+			return -ENFILE;
+		}
+	}
+	video_device[i]=vfd;
+	vfd->minor=i;
+	up(&videodev_register_lock);
+
+	/* The init call may sleep so we book the slot out
+	   then call */
+	MOD_INC_USE_COUNT;
+	if(vfd->initialize) {
+		err=vfd->initialize(vfd);
+		if(err<0) {
+			video_device[i]=NULL;
+			MOD_DEC_USE_COUNT;
+			return err;
 		}
 	}
-	return -ENFILE;
+	sprintf (name, "v4l/%s%d", name_base, i - base);
+	/*
+	 *	Start the device root only. Anything else
+	 *	has serious privacy issues.
+	 */
+	vfd->devfs_handle =
+		devfs_register (NULL, name, DEVFS_FL_DEFAULT,
+				VIDEO_MAJOR, vfd->minor,
+				S_IFCHR | S_IRUSR | S_IWUSR,
+				&video_fops,
+				NULL);
+	
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	sprintf (name, "%s%d", name_base, i - base);
+	videodev_proc_create_dev (vfd, name);
+#endif
+	return 0;
 }
 
 /**
@@ -546,7 +560,7 @@
  *	Initialise video for linux
  */
  
-int __init videodev_init(void)
+static int __init videodev_init(void)
 {
 	struct video_init *vfli = video_init_list;
 	
@@ -573,25 +587,28 @@
 	return 0;
 }
 
-#ifdef MODULE		
-int init_module(void)
-{
-	return videodev_init();
-}
-
-void cleanup_module(void)
+static void __exit videodev_exit(void)
 {
+#ifdef MODULE		
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
 	videodev_proc_destroy ();
 #endif
+#endif
 	
 	devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture");
 }
 
-#endif
+module_init(videodev_init)
+module_exit(videodev_exit)
 
 EXPORT_SYMBOL(video_register_device);
 EXPORT_SYMBOL(video_unregister_device);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("Device registrar for Video4Linux drivers");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/w9966.c linux/drivers/media/video/w9966.c
--- v2.4.4/linux/drivers/media/video/w9966.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/media/video/w9966.c	Thu May 24 15:14:08 2001
@@ -0,0 +1,996 @@
+/*
+	Winbond w9966cf Webcam parport driver.
+
+	Version 0.32
+
+	Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
+
+	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+	Supported devices:
+	*Lifeview FlyCam Supra (using the Philips saa7111a chip)
+
+	Does any other model using the w9966 interface chip exist ?
+
+	Todo:
+	
+	*Add a working EPP mode, since DMA ECP read isn't implemented
+	in the parport drivers. (That's why it's so sloow)
+
+	*Add support for other ccd-control chips than the saa7111
+	please send me feedback on what kind of chips you have.
+
+	*Add proper probing. I don't know what's wrong with the IEEE1284
+	parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
+	and nibble read seems to be broken for some peripherals.
+
+	*Add probing for onboard SRAM, port directions etc. (if possible)
+
+	*Add support for the hardware compressed modes (maybe using v4l2)
+
+	*Fix better support for the capture window (no skewed images, v4l
+	interface to capt. window)
+
+	*Probably some bugs that I don't know of
+
+	Please support me by sending feedback!
+	
+	Changes:
+	
+	Alan Cox:	Removed RGB mode for kernel merge, added THIS_MODULE
+			and owner support for newer module locks
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/videodev.h>
+#include <linux/parport.h>
+
+//#define DEBUG				// Undef me for production
+
+#ifdef DEBUG
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: "__FUNCTION__ "(): "x, ##a)
+#else
+#define DPRINTF(x...)
+#endif
+
+/*
+ *	Defines, simple typedefs etc.
+ */
+
+#define W9966_DRIVERNAME	"W9966CF Webcam"
+#define W9966_MAXCAMS		4	// Maximum number of cameras
+#define W9966_RBUFFER		2048	// Read buffer (must be an even number)
+#define W9966_SRAMSIZE		131072	// 128kb
+#define W9966_SRAMID		0x02	// check w9966cf.pdf
+
+// Empirically determined window limits
+#define W9966_WND_MIN_X		16
+#define W9966_WND_MIN_Y		14
+#define W9966_WND_MAX_X		705
+#define W9966_WND_MAX_Y		253
+#define W9966_WND_MAX_W		(W9966_WND_MAX_X - W9966_WND_MIN_X)
+#define W9966_WND_MAX_H		(W9966_WND_MAX_Y - W9966_WND_MIN_Y)
+
+// Keep track of our current state
+#define W9966_STATE_PDEV	0x01
+#define W9966_STATE_CLAIMED	0x02
+#define W9966_STATE_VDEV	0x04
+
+#define W9966_I2C_W_ID		0x48
+#define W9966_I2C_R_ID		0x49
+#define W9966_I2C_R_DATA	0x08
+#define W9966_I2C_R_CLOCK	0x04
+#define W9966_I2C_W_DATA	0x02
+#define W9966_I2C_W_CLOCK	0x01
+
+struct w9966_dev {
+	unsigned char dev_state;
+	unsigned char i2c_state;
+	unsigned short ppmode;
+	struct parport* pport;
+	struct pardevice* pdev;
+	struct video_device vdev;
+	unsigned short width;
+	unsigned short height;
+	unsigned char brightness;
+	signed char contrast;
+	signed char color;
+	signed char hue;
+};
+
+/*
+ *	Module specific properties
+ */
+
+MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
+MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
+
+#ifdef MODULE
+static const char* pardev[] = {[0 ... W9966_MAXCAMS] = ""};
+#else
+static const char* pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
+#endif
+MODULE_PARM(pardev, "1-" __MODULE_STRING(W9966_MAXCAMS) "s");
+MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
+\teach camera. 'aggressive' means brute-force search.\n\
+\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign
+\tcam 1 to parport3 and search every parport for cam 2 etc...");
+
+static int parmode = 0;
+MODULE_PARM(parmode, "i");
+MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+
+static int video_nr = -1;
+MODULE_PARM(video_nr, "i");
+
+/*
+ *	Private data
+ */
+
+static struct w9966_dev w9966_cams[W9966_MAXCAMS];
+
+/*
+ *	Private function declares
+ */
+
+static inline void w9966_setState(struct w9966_dev* cam, int mask, int val);
+static inline int  w9966_getState(struct w9966_dev* cam, int mask, int val);
+static inline void w9966_pdev_claim(struct w9966_dev *vdev);
+static inline void w9966_pdev_release(struct w9966_dev *vdev);
+
+static int w9966_rReg(struct w9966_dev* cam, int reg);
+static int w9966_wReg(struct w9966_dev* cam, int reg, int data);
+static int w9966_rReg_i2c(struct w9966_dev* cam, int reg);
+static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data);
+static int w9966_findlen(int near, int size, int maxlen);
+static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor);
+static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h);
+
+static int  w9966_init(struct w9966_dev* cam, struct parport* port);
+static void w9966_term(struct w9966_dev* cam);
+
+static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state);
+static inline int  w9966_i2c_setscl(struct w9966_dev* cam, int state);
+static inline int  w9966_i2c_getsda(struct w9966_dev* cam);
+static inline int  w9966_i2c_getscl(struct w9966_dev* cam);
+static int w9966_i2c_wbyte(struct w9966_dev* cam, int data);
+static int w9966_i2c_rbyte(struct w9966_dev* cam);
+
+static int  w9966_v4l_open(struct video_device *vdev, int mode);
+static void w9966_v4l_close(struct video_device *vdev);
+static int  w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg);
+static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count, int noblock);
+
+/*
+ *	Private function defines
+ */
+
+
+// Set camera phase flags, so we know what to uninit when terminating 
+static inline void w9966_setState(struct w9966_dev* cam, int mask, int val)
+{
+	cam->dev_state = (cam->dev_state & ~mask) ^ val;
+}
+
+// Get camera phase flags
+static inline int w9966_getState(struct w9966_dev* cam, int mask, int val)
+{
+	return ((cam->dev_state & mask) == val);
+}
+
+// Claim parport for ourself
+static inline void w9966_pdev_claim(struct w9966_dev* cam)
+{
+	if (w9966_getState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
+		return;
+	parport_claim_or_block(cam->pdev);
+	w9966_setState(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
+}
+
+// Release parport for others to use
+static inline void w9966_pdev_release(struct w9966_dev* cam)
+{
+	if (w9966_getState(cam, W9966_STATE_CLAIMED, 0))
+		return;
+	parport_release(cam->pdev);
+	w9966_setState(cam, W9966_STATE_CLAIMED, 0);
+}
+ 
+// Read register from W9966 interface-chip
+// Expects a claimed pdev
+// -1 on error, else register data (byte)
+static int w9966_rReg(struct w9966_dev* cam, int reg)
+{
+	// ECP, read, regtransfer, REG, REG, REG, REG, REG
+	const unsigned char addr = 0x80 | (reg & 0x1f);
+	unsigned char val;
+	
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+		return -1;
+	if (parport_write(cam->pport, &addr, 1) != 1)
+		return -1;
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+		return -1;
+	if (parport_read(cam->pport, &val, 1) != 1)
+		return -1;
+
+	return val;
+}
+
+// Write register to W9966 interface-chip
+// Expects a claimed pdev
+// -1 on error
+static int w9966_wReg(struct w9966_dev* cam, int reg, int data)
+{
+	// ECP, write, regtransfer, REG, REG, REG, REG, REG
+	const unsigned char addr = 0xc0 | (reg & 0x1f);
+	const unsigned char val = data;
+	
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+		return -1;
+	if (parport_write(cam->pport, &addr, 1) != 1)
+		return -1;
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+		return -1;
+	if (parport_write(cam->pport, &val, 1) != 1)
+		return -1;
+
+	return 0;
+}
+
+// Initialize camera device. Setup all internal flags, set a
+// default video mode, setup ccd-chip, register v4l device etc..
+// Also used for 'probing' of hardware.
+// -1 on error
+static int w9966_init(struct w9966_dev* cam, struct parport* port)
+{
+	if (cam->dev_state != 0)
+		return -1;
+	
+	cam->pport = port;
+	cam->brightness = 128;
+	cam->contrast = 64;
+	cam->color = 64;
+	cam->hue = 0;
+
+// Select requested transfer mode
+	switch(parmode)
+	{
+	default:	// Auto-detect (priority: hw-ecp, hw-epp, sw-ecp)
+	case 0:
+		if (port->modes & PARPORT_MODE_ECP)
+			cam->ppmode = IEEE1284_MODE_ECP;
+		else if (port->modes & PARPORT_MODE_EPP)
+			cam->ppmode = IEEE1284_MODE_EPP;
+		else
+			cam->ppmode = IEEE1284_MODE_ECP;
+		break;	
+	case 1:		// hw- or sw-ecp
+		cam->ppmode = IEEE1284_MODE_ECP;
+		break;
+	case 2:		// hw- or sw-epp
+		cam->ppmode = IEEE1284_MODE_EPP;
+	break;
+	}
+	
+// Tell the parport driver that we exists
+	cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
+	if (cam->pdev == NULL) {
+		DPRINTF("parport_register_device() failed\n");
+		return -1;
+	}
+	w9966_setState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
+
+	w9966_pdev_claim(cam);
+	
+// Setup a default capture mode
+	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
+		DPRINTF("w9966_setup() failed.\n");
+		return -1;
+	}
+
+	w9966_pdev_release(cam);
+
+// Fill in the video_device struct and register us to v4l
+	memset(&cam->vdev, 0, sizeof(struct video_device));
+	strcpy(cam->vdev.name, W9966_DRIVERNAME);
+	cam->vdev.type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
+	cam->vdev.hardware = VID_HARDWARE_W9966;
+	cam->vdev.open = &w9966_v4l_open;
+	cam->vdev.close = &w9966_v4l_close;
+	cam->vdev.read = &w9966_v4l_read;
+	cam->vdev.ioctl = &w9966_v4l_ioctl;
+	cam->vdev.priv = (void*)cam;
+	cam->vdev.owner = THIS_MODULE;
+
+	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1)		 
+		return -1;
+	
+	w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
+	
+	// All ok
+	printk(
+		"w9966cf: Found and initialized a webcam on %s.\n",
+		cam->pport->name
+	);
+	return 0;
+}
+
+
+// Terminate everything gracefully
+static void w9966_term(struct w9966_dev* cam)
+{
+// Unregister from v4l
+	if (w9966_getState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
+		video_unregister_device(&cam->vdev);
+		w9966_setState(cam, W9966_STATE_VDEV, 0);
+	}
+
+// Terminate from IEEE1284 mode and release pdev block
+	if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+		w9966_pdev_claim(cam);
+		parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
+		w9966_pdev_release(cam);
+	}
+
+// Unregister from parport
+	if (w9966_getState(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+		parport_unregister_device(cam->pdev);
+		w9966_setState(cam, W9966_STATE_PDEV, 0);
+	}
+}
+
+
+// Find a good length for capture window (used both for W and H)
+// A bit ugly but pretty functional. The capture length
+// have to match the downscale
+static int w9966_findlen(int near, int size, int maxlen)
+{
+	int bestlen = size;
+	int besterr = abs(near - bestlen);
+	int len;
+
+	for(len = size+1;len < maxlen;len++)
+	{
+		int err;
+		if ( ((64*size) %len) != 0)
+			continue;
+
+		err = abs(near - len);
+
+		// Only continue as long as we keep getting better values
+		if (err > besterr)
+			break;
+		
+		besterr = err;
+		bestlen = len;
+	}
+
+	return bestlen;
+}
+
+// Modify capture window (if necessary) 
+// and calculate downscaling
+// Return -1 on error
+static int w9966_calcscale(int size, int min, int max, int* beg, int* end, unsigned char* factor)
+{
+	int maxlen = max - min;
+	int len = *end - *beg + 1;
+	int newlen = w9966_findlen(len, size, maxlen);
+	int err = newlen - len; 
+
+	// Check for bad format
+	if (newlen > maxlen || newlen < size)
+		return -1;
+
+	// Set factor (6 bit fixed)
+	*factor = (64*size) / newlen;
+	if (*factor == 64)
+		*factor = 0x00;	// downscale is disabled
+	else
+		*factor |= 0x80; // set downscale-enable bit
+
+	// Modify old beginning and end
+	*beg -= err / 2;
+	*end += err - (err / 2);
+
+	// Move window if outside borders
+	if (*beg < min) {
+		*end += min - *beg;
+		*beg += min - *beg;
+	}
+	if (*end > max) {
+		*beg -= *end - max;
+		*end -= *end - max;
+	}
+
+	return 0;
+}
+
+// Setup the cameras capture window etc.
+// Expects a claimed pdev
+// return -1 on error
+static int w9966_setup(struct w9966_dev* cam, int x1, int y1, int x2, int y2, int w, int h)
+{
+	unsigned int i;
+	unsigned int enh_s, enh_e;
+	unsigned char scale_x, scale_y;
+	unsigned char regs[0x1c];
+	unsigned char saa7111_regs[] = {
+		0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
+		0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
+		0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
+	};
+	
+	
+	if (w*h*2 > W9966_SRAMSIZE)
+	{
+		DPRINTF("capture window exceeds SRAM size!.\n");
+		w = 200; h = 160;	// Pick default values
+	}
+
+	w &= ~0x1;
+	if (w < 2) w = 2;
+	if (h < 1) h = 1;
+	if (w > W9966_WND_MAX_W) w = W9966_WND_MAX_W;
+	if (h > W9966_WND_MAX_H) h = W9966_WND_MAX_H;
+
+	cam->width = w;
+	cam->height = h;
+
+	enh_s = 0;	
+	enh_e = w*h*2;
+	
+// Modify capture window if necessary and calculate downscaling
+	if (
+		w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
+		w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0
+	) return -1;
+
+	DPRINTF(
+		"%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
+		w, h, x1, x2, y1, y2, scale_x&~0x80, scale_y&~0x80
+	);
+	
+// Setup registers
+	regs[0x00] = 0x00;			// Set normal operation
+	regs[0x01] = 0x18;			// Capture mode
+	regs[0x02] = scale_y;			// V-scaling
+	regs[0x03] = scale_x;			// H-scaling
+	
+	// Capture window	
+	regs[0x04] = (x1 & 0x0ff);		// X-start (8 low bits)
+	regs[0x05] = (x1 & 0x300)>>8;		// X-start (2 high bits)
+	regs[0x06] = (y1 & 0x0ff);		// Y-start (8 low bits)
+	regs[0x07] = (y1 & 0x300)>>8;		// Y-start (2 high bits)
+	regs[0x08] = (x2 & 0x0ff);		// X-end (8 low bits)
+	regs[0x09] = (x2 & 0x300)>>8;		// X-end (2 high bits)
+	regs[0x0a] = (y2 & 0x0ff);		// Y-end (8 low bits)
+
+	regs[0x0c] = W9966_SRAMID;		// SRAM-banks (1x 128kb)
+	
+	// Enhancement layer
+	regs[0x0d] = (enh_s& 0x000ff);		// Enh. start (0-7)
+	regs[0x0e] = (enh_s& 0x0ff00)>>8;	// Enh. start (8-15)
+	regs[0x0f] = (enh_s& 0x70000)>>16;	// Enh. start (16-17/18??)
+	regs[0x10] = (enh_e& 0x000ff);		// Enh. end (0-7)
+	regs[0x11] = (enh_e& 0x0ff00)>>8;	// Enh. end (8-15)
+	regs[0x12] = (enh_e& 0x70000)>>16;	// Enh. end (16-17/18??)
+
+	// Misc
+	regs[0x13] = 0x40;			// VEE control (raw 4:2:2)
+	regs[0x17] = 0x00;			// ???
+	regs[0x18] = cam->i2c_state = 0x00;	// Serial bus
+	regs[0x19] = 0xff;			// I/O port direction control
+	regs[0x1a] = 0xff;			// I/O port data register
+	regs[0x1b] = 0x10;			// ???
+	
+	// SAA7111 chip settings
+	saa7111_regs[0x0a] = cam->brightness;
+	saa7111_regs[0x0b] = cam->contrast;
+	saa7111_regs[0x0c] = cam->color;
+	saa7111_regs[0x0d] = cam->hue;
+
+// Reset (ECP-fifo & serial-bus)
+	if (w9966_wReg(cam, 0x00, 0x03) == -1)
+		return -1;
+
+// Write regs to w9966cf chip
+	for (i = 0; i < 0x1c; i++)
+		if (w9966_wReg(cam, i, regs[i]) == -1)
+			return -1;
+
+// Write regs to saa7111 chip
+	for (i = 0; i < 0x20; i++)
+		if (w9966_wReg_i2c(cam, i, saa7111_regs[i]) == -1)
+			return -1;
+
+	return 0;
+}
+
+/*
+ *	Ugly and primitive i2c protocol functions
+ */
+
+// Sets the data line on the i2c bus.
+// Expects a claimed pdev.
+static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state)
+{
+	if (state)
+		cam->i2c_state |= W9966_I2C_W_DATA;
+	else
+		cam->i2c_state &= ~W9966_I2C_W_DATA;
+	
+	w9966_wReg(cam, 0x18, cam->i2c_state);
+	udelay(5);
+}
+
+// Sets the clock line on the i2c bus.
+// Expects a claimed pdev. -1 on error
+static inline int w9966_i2c_setscl(struct w9966_dev* cam, int state)
+{
+	int timeout;
+	if (state)
+		cam->i2c_state |= W9966_I2C_W_CLOCK;
+	else
+		cam->i2c_state &= ~W9966_I2C_W_CLOCK;
+
+	w9966_wReg(cam, 0x18, cam->i2c_state);
+	udelay(5);
+	
+	// we go to high, we also expect the peripheral to ack.
+	if (state) {
+		timeout = jiffies + 100;
+		while (!w9966_i2c_getscl(cam)) {
+			if (jiffies > timeout)
+				return -1;
+		}
+	}
+	return 0;
+}
+
+// Get peripheral data line
+// Expects a claimed pdev.
+static inline int w9966_i2c_getsda(struct w9966_dev* cam)
+{
+	const unsigned char state = w9966_rReg(cam, 0x18);
+	return ((state & W9966_I2C_R_DATA) > 0);
+}
+
+// Get peripheral clock line
+// Expects a claimed pdev.
+static inline int w9966_i2c_getscl(struct w9966_dev* cam)
+{
+	const unsigned char state = w9966_rReg(cam, 0x18);
+	return ((state & W9966_I2C_R_CLOCK) > 0);
+}
+
+// Write a byte with ack to the i2c bus.
+// Expects a claimed pdev. -1 on error
+static int w9966_i2c_wbyte(struct w9966_dev* cam, int data)
+{
+	int i;
+	for (i = 7; i >= 0; i--)
+	{
+		w9966_i2c_setsda(cam, (data >> i) & 0x01);
+
+		if (w9966_i2c_setscl(cam, 1) == -1)
+			return -1;			
+		w9966_i2c_setscl(cam, 0);
+	}
+
+	w9966_i2c_setsda(cam, 1);
+	
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setscl(cam, 0);
+	
+	return 0;
+}
+
+// Read a data byte with ack from the i2c-bus
+// Expects a claimed pdev. -1 on error
+static int w9966_i2c_rbyte(struct w9966_dev* cam)
+{
+	unsigned char data = 0x00;
+	int i;	
+	
+	w9966_i2c_setsda(cam, 1);
+
+	for (i = 0; i < 8; i++)
+	{
+		if (w9966_i2c_setscl(cam, 1) == -1)
+			return -1;
+		data = data << 1;
+		if (w9966_i2c_getsda(cam))
+			data |= 0x01;
+		
+		w9966_i2c_setscl(cam, 0);
+	}
+	return data;
+}
+
+// Read a register from the i2c device.
+// Expects claimed pdev. -1 on error
+static int w9966_rReg_i2c(struct w9966_dev* cam, int reg)
+{
+	int data;
+
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (
+		w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+		w9966_i2c_wbyte(cam, reg) == -1
+	)
+		return -1;
+
+	w9966_i2c_setsda(cam, 1);
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (
+		w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1 ||
+		(data = w9966_i2c_rbyte(cam)) == -1
+	)
+		return -1;
+
+	w9966_i2c_setsda(cam, 0);
+	
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setsda(cam, 1);
+	
+	return data;
+}
+
+// Write a register to the i2c device.
+// Expects claimed pdev. -1 on error
+static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
+{
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (
+		w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+		w9966_i2c_wbyte(cam, reg) == -1 ||
+		w9966_i2c_wbyte(cam, data) == -1
+	)
+		return -1;
+
+	w9966_i2c_setsda(cam, 0);
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+		
+	w9966_i2c_setsda(cam, 1);
+
+	return 0;
+}
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int w9966_v4l_open(struct video_device *vdev, int flags)
+{
+	return 0;
+}
+
+static void w9966_v4l_close(struct video_device *vdev)
+{
+}
+
+static int w9966_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+	struct w9966_dev *cam = (struct w9966_dev*)vdev->priv;
+	
+	switch(cmd)
+	{
+	case VIDIOCGCAP:
+	{
+		struct video_capability vcap = {
+			W9966_DRIVERNAME,	// name
+			VID_TYPE_CAPTURE | VID_TYPE_SCALES,	// type
+			1, 0,			// vid, aud channels
+			W9966_WND_MAX_W,	// max w
+			W9966_WND_MAX_H,	// max h
+			2, 1			// min w, min h
+		};
+
+		if(copy_to_user(arg, &vcap, sizeof(vcap)) != 0)
+			return -EFAULT;
+
+		return 0;
+	}
+	case VIDIOCGCHAN:
+	{
+		struct video_channel vch;
+		if(copy_from_user(&vch, arg, sizeof(vch)) != 0)
+			return -EFAULT;
+
+		if(vch.channel != 0)	// We only support one channel (#0)
+			return -EINVAL;
+
+		strcpy(vch.name, "CCD-input");
+		vch.flags = 0;		// We have no tuner or audio
+		vch.tuners = 0;
+		vch.type = VIDEO_TYPE_CAMERA;
+		vch.norm = 0;		// ???
+		
+		if(copy_to_user(arg, &vch, sizeof(vch)) != 0)
+			return -EFAULT;
+		
+		return 0;
+	}
+	case VIDIOCSCHAN:
+	{
+		struct video_channel vch;
+		if(copy_from_user(&vch, arg, sizeof(vch) ) != 0)
+			return -EFAULT;
+		
+		if(vch.channel != 0)
+			return -EINVAL;
+		
+		return 0;
+	}
+	case VIDIOCGTUNER:
+	{
+		struct video_tuner vtune;
+		if(copy_from_user(&vtune, arg, sizeof(vtune)) != 0)
+			return -EFAULT;
+		
+		if(vtune.tuner != 0);
+			return -EINVAL;
+		
+		strcpy(vtune.name, "no tuner");
+		vtune.rangelow = 0;
+		vtune.rangehigh = 0;
+		vtune.flags = VIDEO_TUNER_NORM;
+		vtune.mode = VIDEO_MODE_AUTO;
+		vtune.signal = 0xffff;
+		
+		if(copy_to_user(arg, &vtune, sizeof(vtune)) != 0)
+			return -EFAULT;
+		
+		return 0;
+	}
+	case VIDIOCSTUNER:
+	{
+		struct video_tuner vtune;
+		if (copy_from_user(&vtune, arg, sizeof(vtune)) != 0)
+			return -EFAULT;
+		
+		if (vtune.tuner != 0)
+			return -EINVAL;
+		
+		if (vtune.mode != VIDEO_MODE_AUTO)
+			return -EINVAL;
+		
+		return 0;
+	}
+	case VIDIOCGPICT:
+	{
+		struct video_picture vpic = {
+			cam->brightness << 8,	// brightness
+			(cam->hue + 128) << 8,	// hue
+			cam->color << 9,	// color
+			cam->contrast << 9,	// contrast
+			0x8000,			// whiteness
+			16, VIDEO_PALETTE_YUV422// bpp, palette format
+		};
+
+		if(copy_to_user(arg, &vpic, sizeof(vpic)) != 0)
+			return -EFAULT;
+
+		return 0;
+	}
+	case VIDIOCSPICT:
+	{
+		struct video_picture vpic;
+		if(copy_from_user(&vpic, arg, sizeof(vpic)) != 0)
+			return -EFAULT;
+		
+		if (vpic.depth != 16 || vpic.palette != VIDEO_PALETTE_YUV422)
+			return -EINVAL;
+			
+		cam->brightness = vpic.brightness >> 8;
+		cam->hue = (vpic.hue >> 8) - 128;
+		cam->color = vpic.colour >> 9;
+		cam->contrast = vpic.contrast >> 9;
+
+		w9966_pdev_claim(cam);
+		
+		if (
+			w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 ||
+			w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 ||
+			w9966_wReg_i2c(cam, 0x0c, cam->color) == -1 ||
+			w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1
+		) {
+			w9966_pdev_release(cam);
+			return -EFAULT;
+		}
+		
+		w9966_pdev_release(cam);
+		return 0;
+	}
+	case VIDIOCSWIN:
+	{
+		int ret;
+		struct video_window vwin;
+		
+		if (copy_from_user(&vwin, arg, sizeof(vwin)) != 0)
+			return -EFAULT;		
+		if (vwin.flags != 0)
+			return -EINVAL;
+		if (vwin.clipcount != 0)
+			return -EINVAL;
+		if (vwin.width < 2 || vwin.width > W9966_WND_MAX_W)
+			return -EINVAL;		
+		if (vwin.height < 1 || vwin.height > W9966_WND_MAX_H)
+			return -EINVAL;
+
+		// Update camera regs
+		w9966_pdev_claim(cam);
+		ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin.width, vwin.height);
+		w9966_pdev_release(cam);
+		
+		if (ret != 0) {
+			DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n");
+			return -EFAULT;
+		}
+		
+		return 0;
+	}
+	case VIDIOCGWIN:
+	{
+		struct video_window vwin;
+		memset(&vwin, 0, sizeof(vwin));
+		
+		vwin.width = cam->width;
+		vwin.height = cam->height;
+		
+		if(copy_to_user(arg, &vwin, sizeof(vwin)) != 0)
+			return -EFAULT;
+		
+		return 0;
+	}
+	// Unimplemented
+	case VIDIOCCAPTURE:	
+	case VIDIOCGFBUF:
+	case VIDIOCSFBUF:
+	case VIDIOCKEY:
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+		return -EINVAL;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+// Capture data
+static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count,  int noblock)
+{
+	struct w9966_dev *cam = (struct w9966_dev *)vdev->priv;
+	unsigned char addr = 0xa0;	// ECP, read, CCD-transfer, 00000
+	unsigned char* dest = (unsigned char*)buf;
+	unsigned long dleft = count;
+	
+	// Why would anyone want more than this??
+	if (count > cam->width * cam->height * 2)
+		return -EINVAL;
+	
+	w9966_pdev_claim(cam);
+	w9966_wReg(cam, 0x00, 0x02);	// Reset ECP-FIFO buffer
+	w9966_wReg(cam, 0x00, 0x00);	// Return to normal operation
+	w9966_wReg(cam, 0x01, 0x98);	// Enable capture
+
+	// write special capture-addr and negotiate into data transfer	
+	if (
+		(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0	)||
+		(parport_write(cam->pport, &addr, 1) != 1						)||
+		(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0	)
+	) {
+		w9966_pdev_release(cam);
+		return -EFAULT;
+	}
+	
+	while(dleft > 0)
+	{
+		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
+		unsigned char tbuf[W9966_RBUFFER];
+	
+		if (parport_read(cam->pport, tbuf, tsize) < tsize) {
+			w9966_pdev_release(cam);
+			return -EFAULT;
+		}
+		if (copy_to_user(dest, tbuf, tsize) != 0) {
+			w9966_pdev_release(cam);
+			return -EFAULT;
+		}
+		dest += tsize;
+		dleft -= tsize;
+	}
+	
+	w9966_wReg(cam, 0x01, 0x18);	// Disable capture
+	w9966_pdev_release(cam);
+
+	return count;
+}
+
+
+// Called once for every parport on init
+static void w9966_attach(struct parport *port)
+{
+	int i;
+	
+	for (i = 0; i < W9966_MAXCAMS; i++)
+	{
+		if (w9966_cams[i].dev_state != 0)	// Cam is already assigned
+			continue;
+		if (
+			strcmp(pardev[i], "aggressive") == 0 ||
+			strcmp(pardev[i], port->name) == 0
+		) {
+			if (w9966_init(&w9966_cams[i], port) != 0)
+			w9966_term(&w9966_cams[i]);
+			break;	// return
+		}
+	}
+}
+
+// Called once for every parport on termination
+static void w9966_detach(struct parport *port)
+{
+	int i;
+	for (i = 0; i < W9966_MAXCAMS; i++)
+	if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
+		w9966_term(&w9966_cams[i]);
+}
+
+
+static struct parport_driver w9966_ppd = {
+	W9966_DRIVERNAME,
+	w9966_attach,
+	w9966_detach,
+	NULL
+};
+
+// Module entry point
+static int __init w9966_mod_init(void)
+{
+	int i;
+	for (i = 0; i < W9966_MAXCAMS; i++)
+		w9966_cams[i].dev_state = 0;
+
+	return parport_register_driver(&w9966_ppd);
+}
+
+// Module cleanup
+static void __exit w9966_mod_term(void)
+{
+	parport_unregister_driver(&w9966_ppd);
+}
+
+module_init(w9966_mod_init);
+module_exit(w9966_mod_term);
diff -u --recursive --new-file v2.4.4/linux/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c
--- v2.4.4/linux/drivers/media/video/zr36120.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/video/zr36120.c	Mon May 21 17:06:00 2001
@@ -57,11 +57,15 @@
 
 static unsigned int triton1=0;			/* triton1 chipset? */
 static unsigned int cardtype[ZORAN_MAX]={ [ 0 ... ZORAN_MAX-1 ] = CARDTYPE };
+static int video_nr = -1;
+static int vbi_nr = -1;
 
 MODULE_AUTHOR("Pauline Middelink <middelin@polyware.nl>");
 MODULE_DESCRIPTION("Zoran ZR36120 based framegrabber");
 MODULE_PARM(triton1,"i");
 MODULE_PARM(cardtype,"1-" __MODULE_STRING(ZORAN_MAX) "i");
+MODULE_PARM(video_nr,"i");
+MODULE_PARM(vbi_nr,"i");
 
 static int zoran_cards;
 static struct zoran zorans[ZORAN_MAX];
@@ -1194,8 +1198,10 @@
 		vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
 		if (vcp==NULL)
 			return -ENOMEM;
-		if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount))
+		if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) {
+			vfree(vcp);
 			return -EFAULT;
+		}
 
 		on = ztv->running;
 		if (on)
@@ -1990,13 +1996,13 @@
 	ztv->video_dev = zr36120_template;
 	strcpy(ztv->video_dev.name, ztv->i2c.name);
 	ztv->video_dev.priv = ztv;
-	if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER) < 0)
+	if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0)
 		return -1;
 
 	ztv->vbi_dev = vbi_template;
 	strcpy(ztv->vbi_dev.name, ztv->i2c.name);
 	ztv->vbi_dev.priv = ztv;
-	if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI) < 0) {
+	if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) {
 		video_unregister_device(&ztv->video_dev);
 		return -1;
 	}
diff -u --recursive --new-file v2.4.4/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c
--- v2.4.4/linux/drivers/mtd/ftl.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/mtd/ftl.c	Sat Apr 28 11:27:54 2001
@@ -915,9 +915,6 @@
 
 static release_t ftl_close(struct inode *inode, struct file *file)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-    struct super_block *sb = get_super(inode->i_rdev);
-#endif
     int minor = MINOR(inode->i_rdev);
     partition_t *part = myparts[minor >> 4];
     int i;
@@ -925,11 +922,7 @@
     DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor);
 
     /* Flush all writes */
-    fsync_dev(inode->i_rdev);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-    if (sb) invalidate_inodes(sb);
-#endif
-    invalidate_buffers(inode->i_rdev);
+    invalidate_device(inode->i_rdev, 1);
 
     /* Wait for any pending erase operations to complete */
     if (part->mtd->sync)
diff -u --recursive --new-file v2.4.4/linux/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c
--- v2.4.4/linux/drivers/mtd/mtdblock.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/mtd/mtdblock.c	Sat Apr 28 11:27:54 2001
@@ -355,19 +355,12 @@
 {
 	int dev;
 	struct mtdblk_dev *mtdblk;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-	struct super_block * sb = get_super(inode->i_rdev);
-#endif
    	DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
 
 	if (inode == NULL)
 		release_return(-ENODEV);
    
-	fsync_dev(inode->i_rdev);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-	if (sb) invalidate_inodes(sb);
-#endif
-	invalidate_buffers(inode->i_rdev);
+	invalidate_device(inode->i_rdev, 1);
 
 	dev = MINOR(inode->i_rdev);
 	mtdblk = mtdblks[dev];
diff -u --recursive --new-file v2.4.4/linux/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c
--- v2.4.4/linux/drivers/mtd/mtdchar.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/mtd/mtdchar.c	Mon May 21 17:06:29 2001
@@ -310,8 +310,10 @@
 		if (!databuf)
 			return -ENOMEM;
 		
-		if (copy_from_user(databuf, buf.ptr, buf.length))
+		if (copy_from_user(databuf, buf.ptr, buf.length)) {
+			kfree(databuf);
 			return -EFAULT;
+		}
 
 		ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
 
diff -u --recursive --new-file v2.4.4/linux/drivers/mtd/nftl.c linux/drivers/mtd/nftl.c
--- v2.4.4/linux/drivers/mtd/nftl.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/mtd/nftl.c	Sat Apr 28 11:27:54 2001
@@ -997,17 +997,13 @@
 
 static int nftl_release(struct inode *inode, struct file *fp)
 {
-	struct super_block *sb = get_super(inode->i_rdev);
 	struct NFTLrecord *thisNFTL;
 
 	thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];
 
 	DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n");
 
-	fsync_dev(inode->i_rdev);
-	if (sb)
-		invalidate_inodes(sb);
-	invalidate_buffers(inode->i_rdev);
+	invalidate_device(inode->i_rdev, 1);
 
 	if (thisNFTL->mtd->sync)
 		thisNFTL->mtd->sync(thisNFTL->mtd);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/8139too.c linux/drivers/net/8139too.c
--- v2.4.4/linux/drivers/net/8139too.c	Thu Apr 19 09:32:48 2001
+++ linux/drivers/net/8139too.c	Mon May  7 14:13:19 2001
@@ -149,7 +149,7 @@
 #include <asm/io.h>
 
 
-#define RTL8139_VERSION "0.9.16"
+#define RTL8139_VERSION "0.9.17"
 #define MODNAME "8139too"
 #define RTL8139_DRIVER_NAME   MODNAME " Fast Ethernet driver " RTL8139_VERSION
 #define PFX MODNAME ": "
@@ -728,7 +728,7 @@
 	struct rtl8139_private *tp;
 	u8 tmp8;
 	int rc;
-	unsigned int i, have_pci_pm = 1;
+	unsigned int i;
 	u32 pio_start, pio_end, pio_flags, pio_len;
 	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
 	u32 tmp;
@@ -770,10 +770,6 @@
 	DPRINTK("PIO region size == 0x%02X\n", pio_len);
 	DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
 
-	/* ugly hueristic, but it's a chicken-and-egg problem */
-	if (pio_len < RTL8139B_IO_SIZE)
-		have_pci_pm = 0;
-	
 #ifdef USE_IO_OPS
 	/* make sure PCI base addr 0 is PIO */
 	if (!(pio_flags & IORESOURCE_IO)) {
@@ -824,30 +820,7 @@
 #endif /* USE_IO_OPS */
 
 	/* Bring old chips out of low-power mode. */
-	if (have_pci_pm) {
-		u8 new_tmp8 = tmp8 = RTL_R8 (Config1);
-		if ((rtl_chip_info[tp->chipset].flags & HasLWake) &&
-		    (tmp8 & LWAKE))
-			new_tmp8 &= ~LWAKE;
-		new_tmp8 |= Cfg1_PM_Enable;
-		if (new_tmp8 != tmp8) {
-			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tmp8);
-			RTL_W8 (Cfg9346, Cfg9346_Lock);
-		}
-		if (rtl_chip_info[tp->chipset].flags & HasLWake) {
-			tmp8 = RTL_R8 (Config4);
-			if (tmp8 & LWPTN)
-				RTL_W8 (Config4, tmp8 & ~LWPTN);
-		}
-	} else {
-		RTL_W8 (HltClk, 'R');
-		tmp8 = RTL_R8 (Config1);
-		tmp8 &= ~(SLEEP | PWRDN);
-		RTL_W8 (Config1, tmp8);
-	}
-
-	rtl8139_chip_reset (ioaddr);
+	RTL_W8 (HltClk, 'R');
 
 	/* check for missing/broken hardware */
 	if (RTL_R32 (TxConfig) == 0xFFFFFFFF) {
@@ -877,6 +850,32 @@
 		tp->chipset,
 		rtl_chip_info[tp->chipset].name);
 
+	if (tp->chipset >= CH_8139B) {
+		u8 new_tmp8 = tmp8 = RTL_R8 (Config1);
+		DPRINTK("PCI PM wakeup\n");
+		if ((rtl_chip_info[tp->chipset].flags & HasLWake) &&
+		    (tmp8 & LWAKE))
+			new_tmp8 &= ~LWAKE;
+		new_tmp8 |= Cfg1_PM_Enable;
+		if (new_tmp8 != tmp8) {
+			RTL_W8 (Cfg9346, Cfg9346_Unlock);
+			RTL_W8 (Config1, tmp8);
+			RTL_W8 (Cfg9346, Cfg9346_Lock);
+		}
+		if (rtl_chip_info[tp->chipset].flags & HasLWake) {
+			tmp8 = RTL_R8 (Config4);
+			if (tmp8 & LWPTN)
+				RTL_W8 (Config4, tmp8 & ~LWPTN);
+		}
+	} else {
+		DPRINTK("Old chip wakeup\n");
+		tmp8 = RTL_R8 (Config1);
+		tmp8 &= ~(SLEEP | PWRDN);
+		RTL_W8 (Config1, tmp8);
+	}
+
+	rtl8139_chip_reset (ioaddr);
+
 	DPRINTK ("EXIT, returning 0\n");
 	*dev_out = dev;
 	return 0;
@@ -1358,11 +1357,16 @@
 		else if ((mii_reg5 & 0x0100) == 0x0100
 				 || (mii_reg5 & 0x00C0) == 0x0040)
 			tp->full_duplex = 1;
-		printk(KERN_INFO"%s: Setting %s%s-duplex based on"
+		if (mii_reg5) {
+			printk(KERN_INFO"%s: Setting %s%s-duplex based on"
 			   " auto-negotiated partner ability %4.4x.\n", dev->name,
 			   mii_reg5 == 0 ? "" :
 			   (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
 			   tp->full_duplex ? "full" : "half", mii_reg5);
+		} else {
+			printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
+			       dev->name);
+		}
 	}
 
 	if (tp->chipset >= CH_8139B) {
@@ -1542,11 +1546,18 @@
 		    || (mii_reg5 & 0x01C0) == 0x0040;
 		if (tp->full_duplex != duplex) {
 			tp->full_duplex = duplex;
-			printk (KERN_INFO
-				"%s: Setting %s-duplex based on MII #%d link"
-				" partner ability of %4.4x.\n", dev->name,
-				tp->full_duplex ? "full" : "half",
-				tp->phys[0], mii_reg5);
+
+			if (mii_reg5) {
+				printk (KERN_INFO
+					"%s: Setting %s-duplex based on MII #%d link"
+					" partner ability of %4.4x.\n",
+					dev->name,
+					tp->full_duplex ? "full" : "half",
+					tp->phys[0], mii_reg5);
+			} else {
+				printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
+				       dev->name);
+			}
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
 			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.4.4/linux/drivers/net/8390.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/8390.c	Wed May 16 10:25:38 2001
@@ -453,6 +453,8 @@
 	{
 		if (!netif_running(dev)) {
 			printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+			/* rmk - acknowledge the interrupts */
+			outb_p(interrupts, e8390_base + EN0_ISR);
 			interrupts = 0;
 			break;
 		}
diff -u --recursive --new-file v2.4.4/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.4.4/linux/drivers/net/Config.in	Sun Apr 22 15:43:21 2001
+++ linux/drivers/net/Config.in	Sat May 19 17:55:11 2001
@@ -35,6 +35,9 @@
    fi
    if [ "$CONFIG_PPC" = "y" ]; then
       tristate '  MACE (Power Mac ethernet) support' CONFIG_MACE
+      if [ "$CONFIG_MACE" != "n" ]; then
+        bool '    Use AAUI port instead of TP by default' CONFIG_MACE_AAUI_PORT
+      fi
       tristate '  BMAC (G3 ethernet) support' CONFIG_BMAC
       tristate '  GMAC (G4/iBook ethernet) support' CONFIG_GMAC
       tristate '  Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
@@ -143,10 +146,11 @@
          tristate '    Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
          tristate '    Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
       fi
-      dep_tristate '    DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102 $CONFIG_PCI $CONFIG_EXPERIMENTAL
+      dep_tristate '    Davicom DM910x/DM980x support' CONFIG_DM9102 $CONFIG_PCI
       dep_tristate '    EtherExpressPro/100 support' CONFIG_EEPRO100 $CONFIG_PCI
       dep_mbool '      Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM $CONFIG_EEPRO100 $CONFIG_EXPERIMENTAL
       dep_tristate '    Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
+      dep_tristate '    Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
       dep_tristate '    National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
       dep_tristate '    PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
       dep_tristate '    Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
@@ -261,6 +265,9 @@
       dep_bool '     Aironet 4500/4800 I365 broken support (EXPERIMENTAL)' CONFIG_AIRONET4500_I365 $CONFIG_EXPERIMENTAL
    fi
    dep_tristate '   Aironet 4500/4800 PROC interface ' CONFIG_AIRONET4500_PROC $CONFIG_AIRONET4500 m
+
+# New directory for Wireless LAN devices - cards above will move there
+   source drivers/net/wireless/Config.in
 fi
 
 endmenu
diff -u --recursive --new-file v2.4.4/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.4.4/linux/drivers/net/Makefile	Thu Apr 19 22:46:05 2001
+++ linux/drivers/net/Makefile	Wed May 16 10:25:38 2001
@@ -8,7 +8,7 @@
 obj-n           :=
 obj-            :=
 
-mod-subdirs     := appletalk arcnet fc irda tokenring pcmcia wan
+mod-subdirs     := appletalk arcnet fc irda tokenring pcmcia wireless wan
 
 O_TARGET := net.o
 
@@ -30,6 +30,7 @@
 endif
 
 subdir-$(CONFIG_NET_PCMCIA) += pcmcia
+subdir-$(CONFIG_NET_RADIO) += wireless
 subdir-$(CONFIG_TULIP) += tulip
 subdir-$(CONFIG_IRDA) += irda
 subdir-$(CONFIG_TR) += tokenring
@@ -75,6 +76,7 @@
 obj-$(CONFIG_ACENIC) += acenic.o
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
+obj-$(CONFIG_FEALNX) += fealnx.o
 
 ifeq ($(CONFIG_SK98LIN),y)
 obj-y += sk98lin/sk98lin.o
diff -u --recursive --new-file v2.4.4/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- v2.4.4/linux/drivers/net/acenic.h	Thu Apr 12 12:11:39 2001
+++ linux/drivers/net/acenic.h	Sun May 20 12:11:38 2001
@@ -1,6 +1,7 @@
 #ifndef _ACENIC_H_
 #define _ACENIC_H_
 
+#include <linux/config.h>
 
 /*
  * Generate TX index update each time, when TX ring is closed.
diff -u --recursive --new-file v2.4.4/linux/drivers/net/acenic_firmware.h linux/drivers/net/acenic_firmware.h
--- v2.4.4/linux/drivers/net/acenic_firmware.h	Tue Mar  6 19:28:33 2001
+++ linux/drivers/net/acenic_firmware.h	Tue May  1 22:03:44 2001
@@ -17,7 +17,7 @@
 #define tigonFwSbssLen 0x38
 #define tigonFwBssAddr 0x00015dd0
 #define tigonFwBssLen 0x2080
-#ifndef CONFIG_ACENIC_OMIT_TIGON_I
+#ifdef CONFIG_ACENIC_OMIT_TIGON_I
 #define tigonFwText 0
 #define tigonFwData 0
 #define tigonFwRodata 0
diff -u --recursive --new-file v2.4.4/linux/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c
--- v2.4.4/linux/drivers/net/appletalk/cops.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/appletalk/cops.c	Wed May 16 10:31:27 2001
@@ -1,7 +1,7 @@
 /*      cops.c: LocalTalk driver for Linux.
  *
  *	Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  *
  *	With more than a little help from;
  *	- Alan Cox <Alan.Cox@linux.org> 
@@ -34,7 +34,7 @@
  */
 
 static const char *version =
-"cops.c:v0.04 6/7/98 Jay Schulist <jschlst@turbolinux.com>\n";
+"cops.c:v0.04 6/7/98 Jay Schulist <jschlst@samba.org>\n";
 /*
  *  Sources:
  *      COPS Localtalk SDK. This provides almost all of the information
diff -u --recursive --new-file v2.4.4/linux/drivers/net/appletalk/cops.h linux/drivers/net/appletalk/cops.h
--- v2.4.4/linux/drivers/net/appletalk/cops.h	Fri Mar  3 12:54:44 2000
+++ linux/drivers/net/appletalk/cops.h	Wed May 16 10:31:27 2001
@@ -1,7 +1,7 @@
 /*      cops.h: LocalTalk driver for Linux.
  *
  *      Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  */
 
 #ifndef __LINUX_COPSLTALK_H
diff -u --recursive --new-file v2.4.4/linux/drivers/net/appletalk/cops_ffdrv.h linux/drivers/net/appletalk/cops_ffdrv.h
--- v2.4.4/linux/drivers/net/appletalk/cops_ffdrv.h	Mon Dec 11 13:00:20 2000
+++ linux/drivers/net/appletalk/cops_ffdrv.h	Wed May 16 10:31:27 2001
@@ -21,7 +21,7 @@
 /*      cops_ffdrv.h: LocalTalk driver firmware dump for Linux.
  *
  *      Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  */
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/net/appletalk/cops_ltdrv.h linux/drivers/net/appletalk/cops_ltdrv.h
--- v2.4.4/linux/drivers/net/appletalk/cops_ltdrv.h	Mon Dec 11 13:00:20 2000
+++ linux/drivers/net/appletalk/cops_ltdrv.h	Wed May 16 10:31:27 2001
@@ -20,7 +20,7 @@
 /*      cops_ltdrv.h: LocalTalk driver firmware dump for Linux.
  *
  *      Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  */
  
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/net/appletalk/ipddp.c linux/drivers/net/appletalk/ipddp.c
--- v2.4.4/linux/drivers/net/appletalk/ipddp.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/net/appletalk/ipddp.c	Wed May 16 10:31:27 2001
@@ -4,7 +4,7 @@
  *
  *	Authors:
  *      - DDP-IP Encap by: Bradford W. Johnson <johns393@maroon.tc.umn.edu>
- *	- DDP-IP Decap by: Jay Schulist <jschlst@turbolinux.com>
+ *	- DDP-IP Decap by: Jay Schulist <jschlst@samba.org>
  *
  *	Derived from:
  *	- Almost all code already existed in net/appletalk/ddp.c I just
@@ -14,7 +14,7 @@
  *        Written 1993-94 by Donald Becker.
  *	- dummy.c: A dummy net driver. By Nick Holloway.
  *	- MacGate: A user space Daemon for Appletalk-IP Decap for
- *	  Linux by Jay Schulist <jschlst@turbolinux.com>
+ *	  Linux by Jay Schulist <jschlst@samba.org>
  *
  *      Copyright 1993 United States Government as represented by the
  *      Director, National Security Agency.
@@ -69,7 +69,7 @@
 		printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n", 
 			dev->name);
 	if(ipddp_mode == IPDDP_DECAP)
-		printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@turbolinux.com>\n", 
+		printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@samba.org>\n", 
 			dev->name);
 
 	/* Fill in the device structure with ethernet-generic values. */
diff -u --recursive --new-file v2.4.4/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.4.4/linux/drivers/net/bmac.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/bmac.c	Wed May 16 09:58:36 2001
@@ -76,9 +76,6 @@
 	struct net_device_stats stats;
 	struct timer_list tx_timeout;
 	int timeout_active;
-	int reset_and_enabled;
-	int rx_allocated;
-	int tx_allocated;
 	unsigned short hash_use_count[64];
 	unsigned short hash_table_mask[4];
 	struct net_device *next_bmac;
@@ -126,6 +123,7 @@
 };
 
 static struct net_device *bmac_devs;
+static unsigned char *bmac_emergency_rxbuf;
 
 #ifdef CONFIG_PMAC_PBOOK
 static int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
@@ -151,9 +149,9 @@
 static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *bmac_stats(struct net_device *dev);
 static void bmac_set_multicast(struct net_device *dev);
-static int bmac_reset_and_enable(struct net_device *dev, int enable);
+static void bmac_reset_and_enable(struct net_device *dev);
 static void bmac_start_chip(struct net_device *dev);
-static int bmac_init_chip(struct net_device *dev);
+static void bmac_init_chip(struct net_device *dev);
 static void bmac_init_registers(struct net_device *dev);
 static void bmac_reset_chip(struct net_device *dev);
 static int bmac_set_address(struct net_device *dev, void *addr);
@@ -185,17 +183,6 @@
 }
 
 static void
-dbdma_stop(volatile struct dbdma_regs *dmap)
-{
-	dbdma_st32((volatile unsigned long *)&dmap->control,
-		   DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
-	eieio();
-
-	while (dbdma_ld32((volatile unsigned long *)&dmap->status) & (ACTIVE|FLUSH))
-		eieio();
-}
-
-static void
 dbdma_continue(volatile struct dbdma_regs *dmap)
 {
 	dbdma_st32((volatile unsigned long *)&dmap->control,
@@ -467,12 +454,11 @@
 	}
 }
 
-static int
+static void
 bmac_init_chip(struct net_device *dev)
 {
 	bmac_init_phy(dev);
 	bmac_init_registers(dev);
-	return 1;
 }
 
 #ifdef CONFIG_PMAC_PBOOK
@@ -503,7 +489,7 @@
 		break;
 	case PBOOK_WAKE:
 		/* see if this is enough */
-		bmac_reset_and_enable(bmac_devs, 1);
+		bmac_reset_and_enable(bmac_devs);
 		enable_irq(bmac_devs->irq);
 		enable_irq(bp->tx_dma_intr);
 		enable_irq(bp->rx_dma_intr);
@@ -569,9 +555,12 @@
 }
 
 static void
-bmac_construct_rxbuff(unsigned char *addr, volatile struct dbdma_cmd *cp)
+bmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
 {
-	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN, virt_to_bus(addr), 0);
+	unsigned char *addr = skb? skb->data: bmac_emergency_rxbuf;
+
+	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN,
+		     virt_to_bus(addr), 0);
 }
 
 /* Bit-reverse one byte of an ethernet hardware address. */
@@ -586,7 +575,7 @@
 }
 
 
-static int
+static void
 bmac_init_tx_ring(struct bmac_data *bp)
 {
 	volatile struct dbdma_regs *td = bp->tx_dma;
@@ -605,9 +594,6 @@
 	dbdma_reset(td);
 	out_le32(&td->wait_sel, 0x00200020);
 	out_le32(&td->cmdptr, virt_to_bus(bp->tx_cmds));
-
-	return 1;
-
 }
 
 static int
@@ -615,22 +601,20 @@
 {
 	volatile struct dbdma_regs *rd = bp->rx_dma;
 	int i;
+	struct sk_buff *skb;
 
 	/* initialize list of sk_buffs for receiving and set up recv dma */
-	if (!bp->rx_allocated) {
-		for (i = 0; i < N_RX_RING; i++) {
-			bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
-			if (bp->rx_bufs[i] == NULL)
-				return 0;
-			skb_reserve(bp->rx_bufs[i], 2);
+	memset((char *)bp->rx_cmds, 0,
+	       (N_RX_RING + 1) * sizeof(struct dbdma_cmd));
+	for (i = 0; i < N_RX_RING; i++) {
+		if ((skb = bp->rx_bufs[i]) == NULL) {
+			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+			if (skb != NULL)
+				skb_reserve(skb, 2);
 		}
-		bp->rx_allocated = 1;
+		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
 	}
 
-	memset((char *)bp->rx_cmds, 0, (N_RX_RING+1) * sizeof(struct dbdma_cmd));
-	for (i = 0; i < N_RX_RING; i++)
-		bmac_construct_rxbuff(bp->rx_bufs[i]->data, &bp->rx_cmds[i]);
-
 	bp->rx_empty = 0;
 	bp->rx_fill = i;
 
@@ -706,27 +690,36 @@
 		cp = &bp->rx_cmds[i];
 		stat = ld_le16(&cp->xfer_status);
 		residual = ld_le16(&cp->res_count);
-		if ((stat & ACTIVE) == 0) break;
+		if ((stat & ACTIVE) == 0)
+			break;
 		nb = RX_BUFLEN - residual - 2;
 		if (nb < (ETHERMINPACKET - ETHERCRC)) {
 			skb = NULL;
 			bp->stats.rx_length_errors++;
 			bp->stats.rx_errors++;
-		} else skb =  bp->rx_bufs[i];
+		} else {
+			skb = bp->rx_bufs[i];
+			bp->rx_bufs[i] = NULL;
+		}
 		if (skb != NULL) {
 			nb -= ETHERCRC;
 			skb_put(skb, nb);
 			skb->dev = dev;
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
-			skb_reserve(bp->rx_bufs[i], 2);
-			bmac_construct_rxbuff(bp->rx_bufs[i]->data, &bp->rx_cmds[i]);
+			dev->last_rx = jiffies;
 			++bp->stats.rx_packets;
 			bp->stats.rx_bytes += nb;
 		} else {
 			++bp->stats.rx_dropped;
 		}
+		dev->last_rx = jiffies;
+		if ((skb = bp->rx_bufs[i]) == NULL) {
+			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+			if (skb != NULL)
+				skb_reserve(bp->rx_bufs[i], 2);
+		}
+		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
 		st_le16(&cp->res_count, 0);
 		st_le16(&cp->xfer_status, 0);
 		last = i;
@@ -772,7 +765,13 @@
 		if (txintcount < 10) {
 			XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat));
 		}
-		if (!(stat & ACTIVE)) break;
+		if (!(stat & ACTIVE)) {
+			/*
+			 * status field might not have been filled by DBDMA
+			 */
+			if (cp == bus_to_virt(in_le32(&bp->tx_dma->cmdptr)))
+				break;
+		}
 
 		if (bp->tx_bufs[bp->tx_empty]) {
 			++bp->stats.tx_packets;
@@ -1215,7 +1214,7 @@
 		}
 }
 
-static int bmac_reset_and_enable(struct net_device *dev, int enable)
+static void bmac_reset_and_enable(struct net_device *dev)
 {
 	struct bmac_data *bp = dev->priv;
 	unsigned long flags;
@@ -1223,22 +1222,19 @@
 	unsigned char *data;
 
 	save_flags(flags); cli();
-	bp->reset_and_enabled = 0;
 	bmac_reset_chip(dev);
-	if (enable) {
-		if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp))
-			return 0;
-		if (!bmac_init_chip(dev))
-			return 0;
-		bmac_start_chip(dev);
-		bmwrite(dev, INTDISABLE, EnableNormal);
-		bp->reset_and_enabled = 1;
-
-		/*
-		 * It seems that the bmac can't receive until it's transmitted
-		 * a packet.  So we give it a dummy packet to transmit.
-		 */
-		skb = dev_alloc_skb(ETHERMINPACKET);
+	bmac_init_tx_ring(bp);
+	bmac_init_rx_ring(bp);
+	bmac_init_chip(dev);
+	bmac_start_chip(dev);
+	bmwrite(dev, INTDISABLE, EnableNormal);
+
+	/*
+	 * It seems that the bmac can't receive until it's transmitted
+	 * a packet.  So we give it a dummy packet to transmit.
+	 */
+	skb = dev_alloc_skb(ETHERMINPACKET);
+	if (skb != NULL) {
 		data = skb_put(skb, ETHERMINPACKET);
 		memset(data, 0, ETHERMINPACKET);
 		memcpy(data, dev->dev_addr, 6);
@@ -1246,13 +1242,14 @@
 		bmac_transmit_packet(skb, dev);
 	}
 	restore_flags(flags);
-	return 1;
 }
 
 static int __init bmac_probe(void)
 {
 	struct device_node *bmac;
 
+	MOD_INC_USE_COUNT;
+
 	for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next)
 		bmac_probe1(bmac, 0);
 	for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0;
@@ -1265,7 +1262,10 @@
 		pmu_register_sleep_notifier(&bmac_sleep_notifier);
 #endif
 	}
-	return 0;
+
+	MOD_DEC_USE_COUNT;
+
+	return bmac_devs? 0: -ENODEV;
 }
 
 static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
@@ -1290,6 +1290,14 @@
 		}
 	}
 
+	if (bmac_emergency_rxbuf == NULL) {
+		bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL);
+		if (bmac_emergency_rxbuf == NULL) {
+			printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n");
+			return;
+		}
+	}
+
 	dev = init_etherdev(NULL, PRIV_BYTES);
 	if (!dev) {
 		printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n",
@@ -1390,9 +1398,7 @@
 {
 	/* XXDEBUG(("bmac: enter open\n")); */
 	/* reset the chip */
-	if (!bmac_reset_and_enable(dev, 1))
-		return -ENOMEM;
-
+	bmac_reset_and_enable(dev);
 	dev->flags |= IFF_RUNNING;
 	return 0;
 }
@@ -1428,7 +1434,6 @@
 			bp->rx_bufs[i] = NULL;
 		}
 	}
-	bp->rx_allocated = 0;
 	XXDEBUG(("bmac: free tx bufs\n"));
 	for (i = 0; i<N_TX_RING; i++) {
 		if (bp->tx_bufs[i] != NULL) {
@@ -1436,7 +1441,6 @@
 			bp->tx_bufs[i] = NULL;
 		}
 	}
-	bp->reset_and_enabled = 0;
 	XXDEBUG(("bmac: all bufs freed\n"));
 
 	return 0;
@@ -1607,6 +1611,11 @@
 {
 	struct bmac_data *bp;
 	struct net_device *dev;
+
+	if (bmac_emergency_rxbuf != NULL) {
+		kfree(bmac_emergency_rxbuf);
+		bmac_emergency_rxbuf = NULL;
+	}
 
 	if (bmac_devs == 0)
 		return;
diff -u --recursive --new-file v2.4.4/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- v2.4.4/linux/drivers/net/dmfe.c	Wed Apr 25 16:14:08 2001
+++ linux/drivers/net/dmfe.c	Sat May 19 18:05:23 2001
@@ -1,82 +1,56 @@
 /*
-   dmfe.c: Version 1.30 06/11/2000
+    dmfe.c: Version 1.36p1 2001-05-12 for Linux kernel 2.4.x
 
-   A Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux. 
-   Copyright (C) 1997  Sten Wang
-   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
+    A Davicom DM9102/DM9102A/DM9102A+DM9801/DM9102A+DM9802 NIC fast
+    ethernet driver for Linux.
+    Copyright (C) 1997  Sten Wang
 
-   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 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.
+    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.
 
+    DAVICOM Web-Site: www.davicom.com.tw
 
-   Compiler command:
-   "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall 
-   -Wstrict-prototypes -O6 -c dmfe.c"
-   OR
-   "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net -Wall 
-   -Wstrict-prototypes -O6 -c dmfe.c"
+    Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw
+    Maintainer: Tobias Ringstrom <tori@unhappy.mine.nu>
 
-   The following steps teach you how to active DM9102 board:
-   1. Used the upper compiler command to compile dmfe.c
-   2. insert dmfe module into kernel
-   "insmod dmfe"        ;;Auto Detection Mode
-   "insmod dmfe mode=0" ;;Force 10M Half Duplex
-   "insmod dmfe mode=1" ;;Force 100M Half Duplex
-   "insmod dmfe mode=4" ;;Force 10M Full Duplex
-   "insmod dmfe mode=5" ;;Force 100M Full Duplex
-   3. config a dm9102 network interface
-   "ifconfig eth0 172.22.3.18"
-   4. active the IP routing table
-   "route add -net 172.22.3.0 eth0"
-   5. Well done. Your DM9102 adapter actived now.
+    (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
 
-   Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw
+    Marcelo Tosatti <marcelo@conectiva.com.br> :
+    Made it compile in 2.3 (device to net_device)
 
-   Date:   10/28,1998
+    Alan Cox <alan@redhat.com> :
+    Cleaned up for kernel merge.
+    Removed the back compatibility support
+    Reformatted, fixing spelling etc as I went
+    Removed IRQ 0-15 assumption
 
-   (C)Copyright 1997-1998 DAVICOM Semiconductor, Inc. All Rights Reserved.
+    Jeff Garzik <jgarzik@mandrakesoft.com> :
+    Updated to use new PCI driver API.
+    Resource usage cleanups.
+    Report driver version to user.
 
-   Marcelo Tosatti <marcelo@conectiva.com.br> : 
-   Made it compile in 2.3 (device to net_device)
-   
-   Alan Cox <alan@redhat.com> :
-   Cleaned up for kernel merge.
-   Removed the back compatibility support
-   Reformatted, fixing spelling etc as I went
-   Removed IRQ 0-15 assumption
+    Tobias Ringstrom <tori@unhappy.mine.nu> :
+    Cleaned up and added SMP safety.  Thanks go to Jeff Garzik,
+	Andrew Morton and Frank Davis for the SMP safety fixes.
 
-   Jeff Garzik <jgarzik@mandrakesoft.com> :
-   Updated to use new PCI driver API.
-   Resource usage cleanups.
-   Report driver version to user.
+    TODO
 
-   Tobias Ringstr÷m <zajbot@goteborg.utfors.se> :
-   Added additional proper locking
-   Rewrote the transmit code to actually use the ring buffer,
-   and to generate a lot fewer interrupts.
+    Implement pci_driver::suspend() and pci_driver::resume()
+    power management methods.
 
-   Frank Davis <fdavis112@juno.com>
-   Added SMP-safe locking mechanisms in addition to Andrew Morton's work
+    Check and fix on 64bit and big endian boxes.
 
-   TODO
+    Test and make sure PCI latency is now correct for all cases.
+*/
 
-   Implement pci_driver::suspend() and pci_driver::resume()
-   power management methods.
-
-   Check and fix on 64bit and big endian boxes.
-
-   Test and make sure PCI latency is now correct for all cases.
-
- */
-
-#define DMFE_VERSION "1.30p3 (April 17, 2001)"
+#define DMFE_VERSION "1.36p1 (May 12, 2001)"
 
 #include <linux/module.h>
 
@@ -87,7 +61,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/slab.h>
+#include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -103,54 +77,58 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
-static char version[] __initdata =
-KERN_INFO "Davicom DM91xx net driver, version " DMFE_VERSION "\n";
-
-
 
 /* Board/System/Debug information/definition ---------------- */
-#define PCI_DM9132_ID   0x91321282	/* Davicom DM9132 ID */
-#define PCI_DM9102_ID   0x91021282	/* Davicom DM9102 ID */
-#define PCI_DM9100_ID   0x91001282	/* Davicom DM9100 ID */
+#define PCI_DM9132_ID   0x91321282      /* Davicom DM9132 ID */
+#define PCI_DM9102_ID   0x91021282      /* Davicom DM9102 ID */
+#define PCI_DM9100_ID   0x91001282      /* Davicom DM9100 ID */
+#define PCI_DM9009_ID   0x90091282      /* Davicom DM9009 ID */
 
 #define DMFE_SUCC       0
 #define DM9102_IO_SIZE  0x80
 #define DM9102A_IO_SIZE 0x100
-#define TX_FREE_DESC_CNT 0xc	/* Tx packet count */
-#define TX_MAX_SEND_CNT 0x1	/* Maximum tx packet per time */
-#define TX_DESC_CNT     0x10	/* Allocated Tx descriptors */
-#define RX_DESC_CNT     0x10	/* Allocated Rx descriptors */
-#define TX_IRQ_THR      12
-#define DESC_ALL_CNT    TX_DESC_CNT+RX_DESC_CNT
+#define TX_MAX_SEND_CNT 0x1             /* Maximum tx packet per time */
+#define TX_DESC_CNT     0x10            /* Allocated Tx descriptors */
+#define RX_DESC_CNT     0x20            /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2)	/* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3)	/* TX wakeup count */
+#define DESC_ALL_CNT    (TX_DESC_CNT + RX_DESC_CNT)
 #define TX_BUF_ALLOC    0x600
 #define RX_ALLOC_SIZE   0x620
 #define DM910X_RESET    1
-#define CR6_DEFAULT     0x00280000	/* SF, HD */
-#define CR7_DEFAULT     0x1a2cd
-#define CR15_DEFAULT    0x06	/* TxJabber RxWatchdog */
-#define TDES0_ERR_MASK  0x4302	/* TXJT, LC, EC, FUE */
+#define CR0_DEFAULT     0x00E00000      /* TX & RX burst mode */
+#define CR6_DEFAULT     0x00080000      /* HD */
+#define CR7_DEFAULT     0x180c1
+#define CR15_DEFAULT    0x06            /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK  0x4302          /* TXJT, LC, EC, FUE */
 #define MAX_PACKET_SIZE 1514
 #define DMFE_MAX_MULTICAST 14
-#define RX_MAX_TRAFFIC  0x14000
+#define RX_COPY_SIZE	100
 #define MAX_CHECK_PACKET 0x8000
+#define DM9801_NOISE_FLOOR 8
+#define DM9802_NOISE_FLOOR 5
 
 #define DMFE_10MHF      0
 #define DMFE_100MHF     1
 #define DMFE_10MFD      4
 #define DMFE_100MFD     5
 #define DMFE_AUTO       8
+#define DMFE_1M_HPNA    0x10
+
+#define DMFE_TXTH_72	0x400000	/* TX TH 72 byte */
+#define DMFE_TXTH_96	0x404000	/* TX TH 96 byte */
+#define DMFE_TXTH_128	0x0000		/* TX TH 128 byte */
+#define DMFE_TXTH_256	0x4000		/* TX TH 256 byte */
+#define DMFE_TXTH_512	0x8000		/* TX TH 512 byte */
+#define DMFE_TXTH_1K	0xC000		/* TX TH 1K  byte */
+
+#define DMFE_TIMER_WUT  (jiffies + HZ * 1)/* timer wakeup time : 1 second */
+#define DMFE_TX_TIMEOUT (HZ * 1.5)	/* tx packet time-out time 1.5 s" */
+#define DMFE_TX_KICK 	(HZ * 0.5)	/* tx packet Kick-out time 0.5 s" */
 
-#define DMFE_TIMER_WUT  (HZ)	/* timer wakeup time : 1 second */
-#define DMFE_TX_TIMEOUT ((HZ*3)/2)	/* tx packet time-out time 1.5 s" */
+#define DMFE_DBUG(dbug_now, msg, vaule) if (dmfe_debug || dbug_now) printk(KERN_ERR "<DMFE>: %s %x\n", msg, vaule)
 
-#define DMFE_DBUG(dbug_now, msg, value)	\
-	if (dmfe_debug || dbug_now)	\
-		printk("DBUG: %s %x\n", msg, value)
-
-#define SHOW_MEDIA_TYPE(mode) \
- 	printk(KERN_WARNING "dmfe: Change Speed to %sMhz %s duplex\n",	\
-	       mode & 1 ? "100" : "10",					\
-	       mode & 4 ? "full":"half");
+#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR "<DMFE>: Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
 
 
 /* CR9 definition: SROM/MII */
@@ -164,20 +142,17 @@
 #define PHY_DATA_0      0x00000
 #define MDCLKH          0x10000
 
-#define SROM_CLK_WRITE(data, ioaddr) \
-	outl(data | CR9_SROM_READ | CR9_SRCS , ioaddr);			\
-	udelay(5);							\
-	outl(data | CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, ioaddr);	\
-	udelay(5);							\
-	outl(data | CR9_SROM_READ | CR9_SRCS , ioaddr);			\
-	udelay(5);
+#define PHY_POWER_DOWN	0x800
 
-#define __CHK_IO_SIZE(pci_id, dev_rev) \
-	( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \
-		DM9102A_IO_SIZE : DM9102_IO_SIZE
-#define CHK_IO_SIZE(pci_dev, dev_rev) \
-	__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
+#define SROM_V41_CODE   0x14
 
+#define SROM_CLK_WRITE(data, ioaddr) outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK,ioaddr);udelay(5);outl(data|CR9_SROM_READ|CR9_SRCS,ioaddr);udelay(5);
+
+#define __CHK_IO_SIZE(pci_id, dev_rev) ( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? DM9102A_IO_SIZE: DM9102_IO_SIZE
+#define CHK_IO_SIZE(pci_dev, dev_rev) __CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev)
+
+/* Sten Check */
+#define DEVICE net_device
 
 /* Structure/enum declaration ------------------------------- */
 struct tx_desc {
@@ -197,19 +172,26 @@
 };
 
 struct dmfe_board_info {
-	u32 chip_id;		/* Chip vendor/Device ID */
-	u32 chip_revision;	/* Chip revision */
-	struct net_device *next_dev;	/* next device */
-	spinlock_t lock; /* Spinlock */
-	struct pci_dev *net_dev;	/* PCI device */
+	u32 chip_id;			/* Chip vendor/Device ID */
+	u32 chip_revision;		/* Chip revision */
+	struct DEVICE *next_dev;	/* next device */
+	struct pci_dev * net_dev;	/* PCI device */
+	spinlock_t lock;
 
-	unsigned long ioaddr;		/* I/O base address */
+	u32 ioaddr;			/* I/O base address */
 	u32 cr0_data;
 	u32 cr5_data;
 	u32 cr6_data;
 	u32 cr7_data;
 	u32 cr15_data;
-	
+
+	/* pointer for memory physical address */
+	dma_addr_t buf_pool_dma_ptr;	/* Tx buffer pool memory */
+	dma_addr_t buf_pool_dma_start;	/* Tx buffer pool align dword */
+	dma_addr_t desc_pool_dma_ptr;	/* descriptor pool memory */
+	dma_addr_t first_tx_desc_dma;
+	dma_addr_t first_rx_desc_dma;
+
 	/* descriptor pointer */
 	unsigned char *buf_pool_ptr;	/* Tx buffer pool memory */
 	unsigned char *buf_pool_start;	/* Tx buffer pool align dword */
@@ -220,52 +202,82 @@
 	struct rx_desc *first_rx_desc;
 	struct rx_desc *rx_insert_ptr;
 	struct rx_desc *rx_ready_ptr;	/* packet come pointer */
-	int tx_int_pkt_num;	/* number of packets to transmit until
-				 * a transmit interrupt is requested */
-	u32 tx_live_cnt;	/* number of used/live tx slots */
-	u32 rx_avail_cnt;	/* available rx descriptor count */
-	u32 interval_rx_cnt;	/* rx packet count a callback time */
-
-	u16 phy_id2;		/* Phyxcer ID2 */
-
-	u8 media_mode;		/* user specify media mode */
-	u8 op_mode;		/* real work media mode */
+	u32 tx_packet_cnt;		/* transmitted packet count */
+	u32 tx_queue_cnt;		/* wait to send packet count */
+	u32 rx_avail_cnt;		/* available rx descriptor count */
+	u32 interval_rx_cnt;		/* rx packet count a callback time */
+
+	u16 HPNA_command;		/* For HPNA register 16 */
+	u16 HPNA_timer;			/* For HPNA remote device check */
+	u16 dbug_cnt;
+	u16 NIC_capability;		/* NIC media capability */
+	u16 PHY_reg4;			/* Saved Phyxcer register 4 value */
+
+	u8 HPNA_present;		/* 0:none, 1:DM9801, 2:DM9802 */
+	u8 chip_type;			/* Keep DM9102A chip type */
+	u8 media_mode;			/* user specify media mode */
+	u8 op_mode;			/* real work media mode */
 	u8 phy_addr;
-	u8 link_failed;		/* Ever link failed */
-	u8 wait_reset;		/* Hardware failed, need to reset */
-	u8 in_reset_state;	/* Now driver in reset routine */
-	u8 rx_error_cnt;	/* recieved abnormal case count */
-	u8 dm910x_chk_mode;	/* Operating mode check */
+	u8 link_failed;			/* Ever link failed */
+	u8 wait_reset;			/* Hardware failed, need to reset */
+	u8 dm910x_chk_mode;		/* Operating mode check */
+	u8 first_in_callback;		/* Flag to record state */
 	struct timer_list timer;
-	struct net_device_stats stats;	/* statistic counter */
+
+	/* System defined statistic counter */
+	struct net_device_stats stats;
+
+	/* Driver defined statistic counter */
+	unsigned long tx_fifo_underrun;
+	unsigned long tx_loss_carrier;
+	unsigned long tx_no_carrier;
+	unsigned long tx_late_collision;
+	unsigned long tx_excessive_collision;
+	unsigned long tx_jabber_timeout;
+	unsigned long reset_count;
+	unsigned long reset_cr8;
+	unsigned long reset_fatal;
+	unsigned long reset_TXtimeout;
+
+	/* NIC SROM data */
 	unsigned char srom[128];
 };
 
 enum dmfe_offsets {
-	DCR0 = 0, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20, DCR5 = 0x28,
-	DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48, DCR10 = 0x50, DCR11 = 0x58,
-	DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70, DCR15 = 0x78
+	DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+	DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+	DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
+	DCR15 = 0x78
 };
 
 enum dmfe_CR6_bits {
-	CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80, CR6_FDM = 0x200,
-	CR6_TXSC = 0x2000, CR6_STI = 0x100000, CR6_SFT = 0x200000, CR6_RXA = 0x40000000,
-	CR6_NO_PURGE = 0x20000000
+	CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+	CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+	CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
 };
 
 /* Global variable declaration ----------------------------- */
-static int dmfe_debug;
-static unsigned char dmfe_media_mode = 8;
-static u32 dmfe_cr6_user_set;
+static int __devinitdata printed_version;
+static char version[] __devinitdata =
+	KERN_INFO "Davicom DM9xxx net driver, version " DMFE_VERSION "\n";
+
+static int dmfe_debug = 0;
+static unsigned char dmfe_media_mode = DMFE_AUTO;
+static u32 dmfe_cr6_user_set = 0;
 
 /* For module input parameter */
-static int debug;
-static u32 cr6set;
+static int debug = 0;
+static u32 cr6set = 0;
 static unsigned char mode = 8;
 static u8 chkmode = 1;
+static u8 HPNA_mode = 0;	/* Default: Low Power/High Speed */
+static u8 HPNA_rx_cmd = 0;	/* Default: Disable Rx remote command */
+static u8 HPNA_tx_cmd = 0;	/* Default: Don't issue remote command */
+static u8 HPNA_NoiseFloor = 0;	/* Default: HPNA NoiseFloor */
+static u8 SF_mode = 0;		/* Special Function: 1:VLAN, 2:RX Flow Control
+				   4: TX pause packet */
 
-static unsigned long CrcTable[256] =
-{
+unsigned long CrcTable[256] = {
 	0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
 	0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
 	0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
@@ -333,83 +345,73 @@
 };
 
 /* function declaration ------------------------------------- */
-static int dmfe_open(struct net_device *);
-static int dmfe_start_xmit(struct sk_buff *, struct net_device *);
-static int dmfe_stop(struct net_device *);
-static struct net_device_stats *dmfe_get_stats(struct net_device *);
-static void dmfe_set_filter_mode(struct net_device *);
-static int dmfe_do_ioctl(struct net_device *, struct ifreq *, int);
-static u16 read_srom_word(long, int);
-static void dmfe_interrupt(int, void *, struct pt_regs *);
+static int dmfe_open(struct DEVICE *);
+static int dmfe_start_xmit(struct sk_buff *, struct DEVICE *);
+static int dmfe_stop(struct DEVICE *);
+static struct net_device_stats * dmfe_get_stats(struct DEVICE *);
+static void dmfe_set_filter_mode(struct DEVICE *);
+static int dmfe_do_ioctl(struct DEVICE *, struct ifreq *, int);
+static u16 read_srom_word(long ,int);
+static void dmfe_interrupt(int , void *, struct pt_regs *);
 static void dmfe_descriptor_init(struct dmfe_board_info *, u32);
 static void allocated_rx_buffer(struct dmfe_board_info *);
 static void update_cr6(u32, u32);
-static void send_filter_frame(struct net_device *, int);
-static void dm9132_id_table(struct net_device *, int);
+static void send_filter_frame(struct DEVICE * ,int);
+static void dm9132_id_table(struct DEVICE * ,int);
 static u16 phy_read(u32, u8, u8, u32);
 static void phy_write(u32, u8, u8, u16, u32);
 static void phy_write_1bit(u32, u32);
 static u16 phy_read_1bit(u32);
-static void dmfe_sense_speed(struct dmfe_board_info *);
+static u8 dmfe_sense_speed(struct dmfe_board_info *);
 static void dmfe_process_mode(struct dmfe_board_info *);
 static void dmfe_timer(unsigned long);
-static void dmfe_rx_packet(struct net_device *, struct dmfe_board_info *);
+static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *);
+static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *);
 static void dmfe_reused_skb(struct dmfe_board_info *, struct sk_buff *);
-static void dmfe_dynamic_reset(struct net_device *);
+static void dmfe_dynamic_reset(struct DEVICE *);
 static void dmfe_free_rxbuffer(struct dmfe_board_info *);
-static void dmfe_init_dm910x(struct net_device *);
+static void dmfe_init_dm910x(struct DEVICE *);
 static unsigned long cal_CRC(unsigned char *, unsigned int, u8);
+static void dmfe_parse_srom(struct dmfe_board_info *);
+static void dmfe_program_DM9801(struct dmfe_board_info *, int);
+static void dmfe_program_DM9802(struct dmfe_board_info *);
+static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * );
+static void dmfe_set_phyxcer(struct dmfe_board_info *);
 
-/* DM910X network board routine ---------------------------- */
+/* DM910X network baord routine ---------------------------- */
 
 /*
- *	Search DM910X board, allocate space and register it
+ *	Search DM910X board ,allocate space and register it
  */
- 
 
-static int __init dmfe_init_one (struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
+static int __devinit dmfe_init_one (struct pci_dev *pdev,
+				    const struct pci_device_id *ent)
 {
 	unsigned long pci_iobase;
 	u8 pci_irqline;
-	struct dmfe_board_info *db;	/* Point a board information structure */
+	struct dmfe_board_info *db;	/* board information structure */
 	int i;
 	struct net_device *dev;
-	u32 dev_rev;
-	u16 pci_command;
+	u32 dev_rev, pci_pmr;
 
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-	static int printed_version;
 	if (!printed_version++)
 		printk(version);
-#endif
 
-	DMFE_DBUG(0, "dmfe_probe()", 0);
+	DMFE_DBUG(0, "dmfe_init_one()", 0);
 
 	/* Enable Master/IO access, Disable memory access */
 	i = pci_enable_device(pdev);
-	if (i) return i;
-
+	if (i)
+		return i;
 	pci_set_master(pdev);
-	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-	pci_command &= ~PCI_COMMAND_MEMORY;
-	pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 
 	pci_iobase = pci_resource_start(pdev, 0);
 	pci_irqline = pdev->irq;
 
-	/* Interrupt check */
-	if (pci_irqline == 0) {
-		printk(KERN_ERR "dmfe(%s): Interrupt wrong : IRQ=%d\n",
-		       pdev->slot_name, pci_irqline);
-		goto err_out;
-	}
-
 	/* iobase check */
-	if (pci_iobase == 0 || pci_resource_len(pdev, 0) == 0) {
-		printk(KERN_ERR "dmfe(%s): I/O base is zero\n", pdev->slot_name);
-		goto err_out;
+	if (pci_iobase == 0) {
+		printk(KERN_ERR "<DMFE>: I/O base is zero\n");
+		return -ENODEV;
 	}
 
 #if 0	/* pci_{enable_device,set_master} sets minimum latency for us now */
@@ -427,15 +429,36 @@
 	/* Init network device */
 	dev = alloc_etherdev(sizeof(*db));
 	if (dev == NULL)
-		goto err_out;
+		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
 
-	if (pci_request_regions(pdev, "dmfe"))
-		goto err_out_netdev;
+	/* IO range check */
+	if (pci_resource_len (pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) {
+		printk(KERN_ERR "<DMFE>: Allocated I/O size too small\n");
+		goto err_out;
+	}
 
+	if (!request_region(pci_iobase,
+			    pci_resource_len (pdev, 0),
+			    dev->name)) {
+		printk(KERN_ERR "<DMFE>: I/O conflict : IO=%lx Range=%x\n",
+		       pci_iobase, CHK_IO_SIZE(pdev, dev_rev));
+		goto err_out;
+	}
+
+	/* Init system & device */
 	db = dev->priv;
-	pci_set_drvdata(pdev, dev);
-	spin_lock_init(&db->lock);
+
+	/* Allocated Tx/Rx descriptor memory */
+	db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
+	db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
+
+	db->first_tx_desc = (struct tx_desc *)db->desc_pool_ptr;
+	db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+	db->buf_pool_start = db->buf_pool_ptr;
+	db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+	pdev->driver_data = dev;
 
 	db->chip_id = ent->driver_data;
 	db->ioaddr = pci_iobase;
@@ -445,12 +468,21 @@
 
 	dev->base_addr = pci_iobase;
 	dev->irq = pci_irqline;
+	pci_set_drvdata(pdev, dev);
 	dev->open = &dmfe_open;
 	dev->hard_start_xmit = &dmfe_start_xmit;
 	dev->stop = &dmfe_stop;
 	dev->get_stats = &dmfe_get_stats;
 	dev->set_multicast_list = &dmfe_set_filter_mode;
 	dev->do_ioctl = &dmfe_do_ioctl;
+	spin_lock_init(&db->lock);
+
+	pci_read_config_dword(pdev, 0x50, &pci_pmr);
+	pci_pmr &= 0x70000;
+	if ( (pci_pmr == 0x10000) && (dev_rev == 0x02000031) )
+		db->chip_type = 1;	/* DM9102A E3 */
+	else
+		db->chip_type = 0;
 
 	/* read 64 word srom data */
 	for (i = 0; i < 64; i++)
@@ -460,9 +492,8 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = db->srom[20 + i];
 
-	i = register_netdev(dev);
-	if (i)
-		goto err_out_res;
+	i = register_netdev (dev);
+	if (i) goto err_out;
 
 	printk(KERN_INFO "%s: Davicom DM%04lx at 0x%lx,",
 	       dev->name,
@@ -474,11 +505,9 @@
 
 	return 0;
 
-err_out_res:
-	pci_release_regions(pdev);
-err_out_netdev:
-	kfree(dev);
 err_out:
+	pci_set_drvdata(pdev, NULL);
+	kfree(dev);
 	return -ENODEV;
 }
 
@@ -486,17 +515,22 @@
 static void __exit dmfe_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct dmfe_board_info *db;
+	struct dmfe_board_info *db = dev->priv;
 
 	DMFE_DBUG(0, "dmfe_remove_one()", 0);
-	
-	db = dev->priv;
-
-	unregister_netdev(dev);
-	pci_release_regions(pdev);
-	kfree(dev);	/* free board information */
 
-	pci_set_drvdata(pdev, NULL);
+ 	if (dev) {
+		pci_free_consistent(db->net_dev, sizeof(struct tx_desc) *
+					DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
+ 					db->desc_pool_dma_ptr);
+		pci_free_consistent(db->net_dev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+					db->buf_pool_ptr, db->buf_pool_dma_ptr);
+		unregister_netdev(dev);
+		release_region(dev->base_addr,
+				CHK_IO_SIZE(pdev, db->chip_revision));
+		kfree(dev);	/* free board information */
+		pci_set_drvdata(pdev, NULL);
+	}
 
 	DMFE_DBUG(0, "dmfe_remove_one() exit", 0);
 }
@@ -506,107 +540,103 @@
  *	Open the interface.
  *	The interface is opened whenever "ifconfig" actives it.
  */
- 
-static int dmfe_open(struct net_device *dev)
+
+static int dmfe_open(struct DEVICE *dev)
 {
 	int ret;
 	struct dmfe_board_info *db = dev->priv;
 
 	DMFE_DBUG(0, "dmfe_open", 0);
 
-	ret = request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev);
+	ret =  request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev);
 	if (ret)
 		return ret;
 
-	/* Allocated Tx/Rx descriptor memory */
-	db->desc_pool_ptr = kmalloc(sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, GFP_KERNEL | GFP_DMA);
-	if (db->desc_pool_ptr == NULL)
-		return -ENOMEM;
-	if ((u32) db->desc_pool_ptr & 0x1f)
-		db->first_tx_desc = (struct tx_desc *) (((u32) db->desc_pool_ptr & ~0x1f) + 0x20);
-	else
-		db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
-
-	/* Allocated Tx buffer memory */
-	db->buf_pool_ptr = kmalloc(TX_BUF_ALLOC * TX_DESC_CNT + 4, GFP_KERNEL | GFP_DMA);
-	if (db->buf_pool_ptr == NULL) {
-		kfree(db->desc_pool_ptr);
-		return -ENOMEM;
-	}
-	if ((u32) db->buf_pool_ptr & 0x3)
-		db->buf_pool_start = (char *) (((u32) db->buf_pool_ptr & ~0x3) + 0x4);
-	else
-		db->buf_pool_start = db->buf_pool_ptr;
-
 	/* system variable init */
 	db->cr6_data = CR6_DEFAULT | dmfe_cr6_user_set;
-	db->tx_int_pkt_num = TX_IRQ_THR;
-	db->tx_live_cnt = 0;
+	db->tx_packet_cnt = 0;
+	db->tx_queue_cnt = 0;
 	db->rx_avail_cnt = 0;
-	db->link_failed = 0;
+	db->link_failed = 1;
 	db->wait_reset = 0;
-	db->in_reset_state = 0;
-	db->rx_error_cnt = 0;
 
-	if (!chkmode || (db->chip_id == PCI_DM9132_ID) || (db->chip_revision >= 0x02000030)) {
-		//db->cr6_data &= ~CR6_SFT;         /* Used Tx threshold */
-		//db->cr6_data |= CR6_NO_PURGE;     /* No purge if rx unavailable */
-		db->cr0_data = 0xc00000;	/* TX/RX desc burst mode */
-		db->dm910x_chk_mode = 4;	/* Enter the normal mode */
-	} else {
+	db->first_in_callback = 0;
+	db->NIC_capability = 0xf;	/* All capability*/
+	db->PHY_reg4 = 0x1e0;
+
+	/* CR6 operation mode decision */
+	if ( !chkmode || (db->chip_id == PCI_DM9132_ID) ||
+		(db->chip_revision >= 0x02000030) ) {
+    		db->cr6_data |= DMFE_TXTH_256;
+		db->cr0_data = CR0_DEFAULT;
+		db->dm910x_chk_mode=4;		/* Enter the normal mode */
+ 	} else {
+		db->cr6_data |= CR6_SFT;	/* Store & Forward mode */
 		db->cr0_data = 0;
 		db->dm910x_chk_mode = 1;	/* Enter the check mode */
 	}
 
-	/* Initialize DM910X board */
+	/* Initilize DM910X board */
 	dmfe_init_dm910x(dev);
 
+	/* Active System Interface */
+	netif_wake_queue(dev);
+
 	/* set and active a timer process */
 	init_timer(&db->timer);
-	db->timer.expires = jiffies + DMFE_TIMER_WUT;
-	db->timer.data = (unsigned long) dev;
+	db->timer.expires = DMFE_TIMER_WUT + HZ * 2;
+	db->timer.data = (unsigned long)dev;
 	db->timer.function = &dmfe_timer;
 	add_timer(&db->timer);
-	
-	netif_wake_queue(dev);
 
 	return 0;
 }
 
-/* Initialize DM910X board
-   Reset DM910X board
-   Initialize TX/Rx descriptor chain structure
-   Send the set-up frame
-   Enable Tx/Rx machine
+
+/*	Initilize DM910X board
+ *	Reset DM910X board
+ *	Initilize TX/Rx descriptor chain structure
+ *	Send the set-up frame
+ *	Enable Tx/Rx machine
  */
-static void dmfe_init_dm910x(struct net_device *dev)
+
+static void dmfe_init_dm910x(struct DEVICE *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
 	u32 ioaddr = db->ioaddr;
-	
+
 	DMFE_DBUG(0, "dmfe_init_dm910x()", 0);
 
-	/* Reset DM910x board : need 32 PCI clock to complete */
+	/* Reset DM910x MAC controller */
 	outl(DM910X_RESET, ioaddr + DCR0);	/* RESET MAC */
-	udelay(5);
+	udelay(100);
 	outl(db->cr0_data, ioaddr + DCR0);
-
-	outl(0x180, ioaddr + DCR12);	/* Let bit 7 output port */
-	outl(0x80, ioaddr + DCR12);	/* RESET DM9102 phyxcer */
-	outl(0x0, ioaddr + DCR12);	/* Clear RESET signal */
+	udelay(5);
 
 	/* Phy addr : DM910(A)2/DM9132/9801, phy address = 1 */
 	db->phy_addr = 1;
 
-	/* Media Mode Check */
+	/* Parser SROM and media mode */
+	dmfe_parse_srom(db);
 	db->media_mode = dmfe_media_mode;
-	if (db->media_mode & DMFE_AUTO)
-		dmfe_sense_speed(db);
-	else
-		db->op_mode = db->media_mode;
-	dmfe_process_mode(db);
 
-	/* Initialize Transmit/Receive decriptor and CR3/4 */
+	/* RESET Phyxcer Chip by GPR port bit 7 */
+	outl(0x180, ioaddr + DCR12);		/* Let bit 7 output port */
+	if (db->chip_id == PCI_DM9009_ID) {
+		outl(0x80, ioaddr + DCR12);	/* Issue RESET signal */
+		mdelay(300);			/* Delay 300 ms */
+	}
+	outl(0x0, ioaddr + DCR12);	/* Clear RESET signal */
+
+	/* Process Phyxcer Media Mode */
+	if ( !(db->media_mode & 0x10) )	/* Force 1M mode */
+		dmfe_set_phyxcer(db);
+
+	/* Media Mode Process */
+	if ( !(db->media_mode & DMFE_AUTO) )
+		db->op_mode = db->media_mode; 	/* Force Mode */
+
+	/* Initiliaze Transmit/Receive decriptor and CR3/4 */
 	dmfe_descriptor_init(db, ioaddr);
 
 	/* Init CR6 to program DM910x operation */
@@ -618,182 +648,184 @@
 	else
 		send_filter_frame(dev, dev->mc_count);	/* DM9102/DM9102A */
 
-	/* Init CR5/CR7, interrupt active bit */
-	outl(0xffffffff, ioaddr + DCR5);	/* clear all CR5 status */
+	/* Init CR7, interrupt active bit */
 	db->cr7_data = CR7_DEFAULT;
 	outl(db->cr7_data, ioaddr + DCR7);
 
 	/* Init CR15, Tx jabber and Rx watchdog timer */
-	db->cr15_data = CR15_DEFAULT;
 	outl(db->cr15_data, ioaddr + DCR15);
 
 	/* Enable DM910X Tx/Rx function */
-	db->cr6_data |= CR6_RXSC | CR6_TXSC;
+	db->cr6_data |= CR6_RXSC | CR6_TXSC | 0x40000;
 	update_cr6(db->cr6_data, ioaddr);
-
 }
 
 
 /*
-   Hardware start transmission.
-   Send a packet to media from the upper layer.
+ *	Hardware start transmission.
+ *	Send a packet to media from the upper layer.
  */
-static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
 	struct tx_desc *txptr;
 	unsigned long flags;
 
 	DMFE_DBUG(0, "dmfe_start_xmit", 0);
+
+	/* Resource flag check */
+	netif_stop_queue(dev);
+
+	/* Too large packet check */
+	if (skb->len > MAX_PACKET_SIZE) {
+		printk(KERN_ERR "<DMFE>: big packet = %d\n", (u16)skb->len);
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
 	spin_lock_irqsave(&db->lock, flags);
-	
-	/* transmit this packet */
-	txptr = db->tx_insert_ptr;
-	memcpy((char *) txptr->tx_buf_ptr, (char *) skb->data, skb->len);
-	if (--db->tx_int_pkt_num < 0)
-	{
-		txptr->tdes1 = 0xe1000000 | skb->len;
-		db->tx_int_pkt_num = TX_IRQ_THR;
+
+	/* No Tx resource check, it never happen nromally */
+	if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
+		spin_unlock_irqrestore(&db->lock, flags);
+		printk(KERN_ERR "<DMFE>: No Tx resource %d\n", db->tx_queue_cnt);
+		return 1;
 	}
-	else
-		txptr->tdes1 = 0x61000000 | skb->len;
 
-	/* Transmit Packet Process */
-	txptr->tdes0 = 0x80000000;	/* set owner bit to DM910X */
-	outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling command */
-	dev->trans_start = jiffies;     /* saved the time stamp */
+	/* Disable NIC interrupt */
+	outl(0, dev->base_addr + DCR7);
 
-	/* Point to next transmit free descriptor */
-	txptr = (struct tx_desc *)txptr->next_tx_desc;
+	/* transmit this packet */
+	txptr = db->tx_insert_ptr;
+	memcpy( (char *) txptr->tx_buf_ptr, (char *) skb->data, skb->len);
+	txptr->tdes1 = cpu_to_le32(0xe1000000 | skb->len);
 
-	if (txptr->tdes0 & 0x80000000)
-		netif_stop_queue(dev);
+	/* Point to next transmit free descriptor */
+	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
 
-	db->tx_insert_ptr = txptr;
-	db->tx_live_cnt++;
+	/* Transmit Packet Process */
+	if ( (!db->tx_queue_cnt) && (db->tx_packet_cnt < TX_MAX_SEND_CNT) ) {
+		txptr->tdes0 = cpu_to_le32(0x80000000);	/* Set owner bit */
+		db->tx_packet_cnt++;			/* Ready to send */
+		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling */
+		dev->trans_start = jiffies;		/* saved time stamp */
+	} else {
+		db->tx_queue_cnt++;			/* queue TX packet */
+		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling */
+	}
 
-	spin_unlock_irqrestore(&db->lock, flags);
+	/* Tx resource check */
+	if ( db->tx_queue_cnt < TX_FREE_DESC_CNT )
+		netif_wake_queue(dev);
 
 	/* free this SKB */
 	dev_kfree_skb(skb);
 
+	/* Restore CR7 to enable interrupt */
+	spin_unlock_irqrestore(&db->lock, flags);
+	outl(db->cr7_data, dev->base_addr + DCR7);
+
 	return 0;
 }
 
+
 /*
  *	Stop the interface.
  *	The interface is stopped when it is brought.
  */
 
-static int dmfe_stop(struct net_device *dev)
+static int dmfe_stop(struct DEVICE *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
 	u32 ioaddr = dev->base_addr;
 
 	DMFE_DBUG(0, "dmfe_stop", 0);
 
+	/* disable system */
 	netif_stop_queue(dev);
 
+	/* deleted timer */
+	del_timer_sync(&db->timer);
+
 	/* Reset & stop DM910X board */
 	outl(DM910X_RESET, ioaddr + DCR0);
 	udelay(5);
+	phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
 
-	/* deleted timer */
-	del_timer_sync(&db->timer);
-	
 	/* free interrupt */
 	free_irq(dev->irq, dev);
 
 	/* free allocated rx buffer */
 	dmfe_free_rxbuffer(db);
 
-	/* free all descriptor memory and buffer memory */
-	kfree(db->desc_pool_ptr);
-	kfree(db->buf_pool_ptr);
+#if 0
+	/* show statistic counter */
+	printk("<DMFE>: FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n",
+		db->tx_fifo_underrun, db->tx_excessive_collision,
+		db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier,
+		db->tx_jabber_timeout, db->reset_count, db->reset_cr8,
+		db->reset_fatal, db->reset_TXtimeout);
+#endif
 
 	return 0;
 }
 
+
 /*
-   DM9102 interrupt handler
-   receive the packet to upper layer, free the transmitted packet
+ *	DM9102 insterrupt handler
+ *	receive the packet to upper layer, free the transmitted packet
  */
 
 static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct net_device *dev = dev_id;
-	struct tx_desc *txptr;
-	struct dmfe_board_info *db;
-	u32 ioaddr;
+	struct DEVICE *dev = dev_id;
+	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
+	u32 ioaddr = dev->base_addr;
 	unsigned long flags;
 
+	DMFE_DBUG(0, "dmfe_interrupt()", 0);
+
 	if (!dev) {
-		DMFE_DBUG(1, "dmfe_interrupt() without device arg", 0);
+		DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0);
 		return;
 	}
-	/* A real interrupt coming */
-	db = (struct dmfe_board_info *) dev->priv;
-	ioaddr = dev->base_addr;
-
-	DMFE_DBUG(0, "dmfe_interrupt()", 0);
 
 	spin_lock_irqsave(&db->lock, flags);
 
-	/* Disable all interrupt in CR7 to solve the interrupt edge problem */
-	outl(0, ioaddr + DCR7);
-
 	/* Got DM910X status */
 	db->cr5_data = inl(ioaddr + DCR5);
 	outl(db->cr5_data, ioaddr + DCR5);
-	/* printk("CR5=%x\n", db->cr5_data); */
+	if ( !(db->cr5_data & 0xc1) ) {
+		spin_unlock_irqrestore(&db->lock, flags);
+		return;
+	}
+
+	/* Disable all interrupt in CR7 to solve the interrupt edge problem */
+	outl(0, ioaddr + DCR7);
 
 	/* Check system status */
 	if (db->cr5_data & 0x2000) {
-		/* A system bus error occurred */
-		DMFE_DBUG(1, "A system bus error occurred. CR5=", db->cr5_data);
-		netif_stop_queue(dev);
-		db->wait_reset = 1;		/* Need to RESET */
-		outl(0, ioaddr + DCR7);		/* disable all interrupt */
+		/* system bus error happen */
+		DMFE_DBUG(1, "System bus error happen. CR5=", db->cr5_data);
+		db->reset_fatal++;
+		db->wait_reset = 1;	/* Need to RESET */
 		spin_unlock_irqrestore(&db->lock, flags);
 		return;
 	}
 
-	/* Free the transmitted descriptor */
-	txptr = db->tx_remove_ptr;
-	while (db->tx_live_cnt > 0 && (txptr->tdes0 & 0x80000000) == 0)
-	{
-		/* printk("tdes0=%x\n", txptr->tdes0); */
-		db->stats.tx_packets++;
-		
-		if ((txptr->tdes0 & TDES0_ERR_MASK) && (txptr->tdes0 != 0x7fffffff)) {
-			/* printk("tdes0=%x\n", txptr->tdes0); */
-			db->stats.tx_errors++;
-		}
-		/* Transmit statistic counter */
-		if (txptr->tdes0 != 0x7fffffff) {
- 			/* printk("tdes0=%x\n", txptr->tdes0); */
- 			db->stats.collisions += (txptr->tdes0 >> 3) & 0xf;
-			db->stats.tx_bytes += txptr->tdes1 & 0x7ff;
-			if (txptr->tdes0 & TDES0_ERR_MASK)
-				db->stats.tx_errors++;
-		}
-		txptr = (struct tx_desc *) txptr->next_tx_desc;
-		db->tx_live_cnt--;
-	}
-	/* Update TX remove pointer to next */
-	db->tx_remove_ptr = (struct tx_desc *) txptr;
-
-	if ((db->tx_insert_ptr->tdes0 & 0x80000000) == 0)
-		netif_wake_queue(dev);
-
-	/* Received the coming packet */
-	if (db->rx_avail_cnt)
+	 /* Received the coming packet */
+	if ( (db->cr5_data & 0x40) && db->rx_avail_cnt )
 		dmfe_rx_packet(dev, db);
 
 	/* reallocated rx descriptor buffer */
-	if (db->rx_avail_cnt < RX_DESC_CNT)
+	if (db->rx_avail_cnt<RX_DESC_CNT)
 		allocated_rx_buffer(db);
 
+	/* Free the transmitted descriptor */
+	if ( db->cr5_data & 0x01)
+		dmfe_free_tx_pkt(dev, db);
+
 	/* Mode Check */
 	if (db->dm910x_chk_mode & 0x2) {
 		db->dm910x_chk_mode = 0x4;
@@ -802,19 +834,85 @@
 	}
 
 	/* Restore CR7 to enable interrupt mask */
-	if (db->interval_rx_cnt > RX_MAX_TRAFFIC)
-		db->cr7_data = 0x1a28d;
-	else
-		db->cr7_data = 0x1a2cd;
 	outl(db->cr7_data, ioaddr + DCR7);
 
 	spin_unlock_irqrestore(&db->lock, flags);
 }
 
+
 /*
-   Receive the come packet and pass to upper layer
+ *	Free TX resource after TX complete
  */
-static void dmfe_rx_packet(struct net_device *dev, struct dmfe_board_info *db)
+
+static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
+{
+	struct tx_desc *txptr;
+	u32 ioaddr = dev->base_addr;
+
+	txptr = db->tx_remove_ptr;
+	while(db->tx_packet_cnt) {
+		/* printk("<DMFE>: tdes0=%x\n", txptr->tdes0); */
+		if (txptr->tdes0 & 0x80000000)
+			break;
+
+		/* A packet sent completed */
+		db->tx_packet_cnt--;
+		db->stats.tx_packets++;
+
+		/* Transmit statistic counter */
+		if ( txptr->tdes0 != 0x7fffffff ) {
+			/* printk("<DMFE>: tdes0=%x\n", txptr->tdes0); */
+			db->stats.collisions += (txptr->tdes0 >> 3) & 0xf;
+			db->stats.tx_bytes += txptr->tdes1 & 0x7ff;
+			if (txptr->tdes0 & TDES0_ERR_MASK) {
+				db->stats.tx_errors++;
+
+				if (txptr->tdes0 & 0x0002) {	/* UnderRun */
+					db->tx_fifo_underrun++;
+					if ( !(db->cr6_data & CR6_SFT) ) {
+						db->cr6_data = db->cr6_data | CR6_SFT;
+						update_cr6(db->cr6_data, db->ioaddr);
+					}
+				}
+				if (txptr->tdes0 & 0x0100)
+					db->tx_excessive_collision++;
+				if (txptr->tdes0 & 0x0200)
+					db->tx_late_collision++;
+				if (txptr->tdes0 & 0x0400)
+					db->tx_no_carrier++;
+				if (txptr->tdes0 & 0x0800)
+					db->tx_loss_carrier++;
+				if (txptr->tdes0 & 0x4000)
+					db->tx_jabber_timeout++;
+			}
+		}
+
+    		txptr = (struct tx_desc *) txptr->next_tx_desc;
+	}/* End of while */
+
+	/* Update TX remove pointer to next */
+	db->tx_remove_ptr = (struct tx_desc *) txptr;
+
+	/* Send the Tx packet in queue */
+	if ( (db->tx_packet_cnt < TX_MAX_SEND_CNT) && db->tx_queue_cnt ) {
+		txptr->tdes0 = cpu_to_le32(0x80000000);	/* Set owner bit */
+		db->tx_packet_cnt++;			/* Ready to send */
+		db->tx_queue_cnt--;
+		outl(0x1, ioaddr + DCR1);		/* Issue Tx polling */
+		dev->trans_start = jiffies;		/* saved time stamp */
+	}
+
+	/* Resource available check */
+	if ( db->tx_queue_cnt < TX_WAKE_DESC_CNT )
+		netif_wake_queue(dev);	/* Active upper layer, send again */
+}
+
+
+/*
+ *	Receive the come packet and pass to upper layer
+ */
+
+static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
 {
 	struct rx_desc *rxptr;
 	struct sk_buff *skb;
@@ -822,26 +920,26 @@
 
 	rxptr = db->rx_ready_ptr;
 
-	while (db->rx_avail_cnt) {
+	while(db->rx_avail_cnt) {
 		if (rxptr->rdes0 & 0x80000000)	/* packet owner check */
 			break;
 
 		db->rx_avail_cnt--;
 		db->interval_rx_cnt++;
 
-		if ((rxptr->rdes0 & 0x300) != 0x300) {
+		if ( (rxptr->rdes0 & 0x300) != 0x300) {
 			/* A packet without First/Last flag */
 			/* reused this SKB */
 			DMFE_DBUG(0, "Reused SK buffer, rdes0", rxptr->rdes0);
 			dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
-			/* db->rx_error_cnt++; */
 		} else {
 			/* A packet with First/Last flag */
-			rxlen = ((rxptr->rdes0 >> 16) & 0x3fff) - 4;	/* skip CRC */
+			rxlen = ( (rxptr->rdes0 >> 16) & 0x3fff) - 4;
 
-			if (rxptr->rdes0 & 0x8000) {	/* error summary bit check */
+			/* error summary bit check */
+			if (rxptr->rdes0 & 0x8000) {
 				/* This is a error packet */
-				/* printk("rdes0 error : %x \n", rxptr->rdes0); */
+				//printk("<DMFE>: rdes0: %lx\n", rxptr->rdes0);
 				db->stats.rx_errors++;
 				if (rxptr->rdes0 & 1)
 					db->stats.rx_fifo_errors++;
@@ -850,21 +948,36 @@
 				if (rxptr->rdes0 & 0x80)
 					db->stats.rx_length_errors++;
 			}
-			if (!(rxptr->rdes0 & 0x8000) ||
-			    ((db->cr6_data & CR6_PM) && (rxlen > 6))) {
+
+			if ( !(rxptr->rdes0 & 0x8000) ||
+				((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
 				skb = (struct sk_buff *) rxptr->rx_skb_ptr;
 
 				/* Received Packet CRC check need or not */
-				if ((db->dm910x_chk_mode & 1) && (cal_CRC(skb->tail, rxlen, 1) != (*(unsigned long *) (skb->tail + rxlen)))) {
+				if ( (db->dm910x_chk_mode & 1) &&
+					(cal_CRC(skb->tail, rxlen, 1) !=
+					(*(unsigned long *) (skb->tail+rxlen) )
+					) ) {
 					/* Found a error received packet */
 					dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
 					db->dm910x_chk_mode = 3;
 				} else {
-					/* A good packet coming, send to upper layer */
-					skb->dev = dev;
-					skb_put(skb, rxlen);
+					/* Good packet, send to upper layer */
+					/* Shorst packet used new SKB */
+					if ( (rxlen < RX_COPY_SIZE) &&
+						( (skb = dev_alloc_skb(rxlen + 2) )
+						!= NULL) ) {
+						/* size less than COPY_SIZE, allocated a rxlen SKB */
+						skb->dev = dev;
+						skb_reserve(skb, 2); /* 16byte align */
+						memcpy(skb_put(skb, rxlen), ((struct sk_buff *) rxptr->rx_skb_ptr)->tail, rxlen);
+						dmfe_reused_skb(db, (struct sk_buff *) rxptr->rx_skb_ptr);
+					} else {
+						skb->dev = dev;
+						skb_put(skb, rxlen);
+					}
 					skb->protocol = eth_type_trans(skb, dev);
-					netif_rx(skb);	/* Send to upper layer */
+					netif_rx(skb);
 					dev->last_rx = jiffies;
 					db->stats.rx_packets++;
 					db->stats.rx_bytes += rxlen;
@@ -880,24 +993,27 @@
 	}
 
 	db->rx_ready_ptr = rxptr;
-
 }
 
+
 /*
-   Get statistics from driver.
+ *	Get statistics from driver.
  */
-static struct net_device_stats *dmfe_get_stats(struct net_device *dev)
+
+static struct net_device_stats * dmfe_get_stats(struct DEVICE *dev)
 {
-	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
+	struct dmfe_board_info *db = (struct dmfe_board_info *)dev->priv;
 
 	DMFE_DBUG(0, "dmfe_get_stats", 0);
 	return &db->stats;
 }
 
+
 /*
-   Set DM910X multicast address
+ * Set DM910X multicast address
  */
-static void dmfe_set_filter_mode(struct net_device *dev)
+
+static void dmfe_set_filter_mode(struct DEVICE * dev)
 {
 	struct dmfe_board_info *db = dev->priv;
 	unsigned long flags;
@@ -912,6 +1028,7 @@
 		spin_unlock_irqrestore(&db->lock, flags);
 		return;
 	}
+
 	if (dev->flags & IFF_ALLMULTI || dev->mc_count > DMFE_MAX_MULTICAST) {
 		DMFE_DBUG(0, "Pass all multicast address", dev->mc_count);
 		db->cr6_data &= ~(CR6_PM | CR6_PBF);
@@ -919,83 +1036,97 @@
 		spin_unlock_irqrestore(&db->lock, flags);
 		return;
 	}
+
 	DMFE_DBUG(0, "Set multicast address", dev->mc_count);
 	if (db->chip_id == PCI_DM9132_ID)
 		dm9132_id_table(dev, dev->mc_count);	/* DM9132 */
 	else
-		send_filter_frame(dev, dev->mc_count);	/* DM9102/DM9102A */
+		send_filter_frame(dev, dev->mc_count); 	/* DM9102/DM9102A */
 	spin_unlock_irqrestore(&db->lock, flags);
 }
 
-/*
-   Process the upper socket ioctl command
- */
 
-/* 
- * The following function just returns 0. Shouldn't it do more? 
+/*
+ *	Process the upper socket ioctl command
  */
 
-static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int dmfe_do_ioctl(struct DEVICE *dev, struct ifreq *ifr, int cmd)
 {
 	DMFE_DBUG(0, "dmfe_do_ioctl()", 0);
 	return 0;
 }
 
+
 /*
-   A periodic timer routine
-   Dynamic media sense, allocated Rx buffer...
+ *	A periodic timer routine
+ *	Dynamic media sense, allocated Rx buffer...
  */
+
 static void dmfe_timer(unsigned long data)
 {
 	u32 tmp_cr8;
 	unsigned char tmp_cr12;
-	struct net_device *dev = (struct net_device *) data;
+	struct DEVICE *dev = (struct DEVICE *) data;
 	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
-	unsigned long flags;
+ 	unsigned long flags;
 
 	DMFE_DBUG(0, "dmfe_timer()", 0);
 	spin_lock_irqsave(&db->lock, flags);
 
-	/* Do reset now */
-	if (db->in_reset_state) {
-		spin_unlock_irqrestore(&db->lock, flags);
-		return;
+	/* Media mode process when Link OK before enter this route */
+	if (db->first_in_callback == 0) {
+		db->first_in_callback = 1;
+		if (db->chip_type && (db->chip_id==PCI_DM9102_ID)) {
+			db->cr6_data &= ~0x40000;
+			update_cr6(db->cr6_data, db->ioaddr);
+			phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+			db->cr6_data |= 0x40000;
+			update_cr6(db->cr6_data, db->ioaddr);
+			db->timer.expires = DMFE_TIMER_WUT + HZ * 2;
+			add_timer(&db->timer);
+			spin_unlock_irqrestore(&db->lock, flags);
+			return;
+		}
 	}
 
+
 	/* Operating Mode Check */
-	if ((db->dm910x_chk_mode & 0x1) && (db->stats.rx_packets > MAX_CHECK_PACKET)) {
+	if ( (db->dm910x_chk_mode & 0x1) &&
+		(db->stats.rx_packets > MAX_CHECK_PACKET) )
 		db->dm910x_chk_mode = 0x4;
-	}
+
 	/* Dynamic reset DM910X : system error or transmit time-out */
 	tmp_cr8 = inl(db->ioaddr + DCR8);
-	if ((db->interval_rx_cnt == 0) && (tmp_cr8)) {
+	if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
+		db->reset_cr8++;
 		db->wait_reset = 1;
-		/* printk("CR8 %x, Interval Rx %x\n", tmp_cr8, db->interval_rx_cnt); */
 	}
-	/* Receiving Traffic check */
-	if (db->interval_rx_cnt > RX_MAX_TRAFFIC)
-		db->cr7_data = 0x1a28d;
-	else
-		db->cr7_data = 0x1a2cd;
-	outl(db->cr7_data, db->ioaddr + DCR7);
-
 	db->interval_rx_cnt = 0;
 
-	if (db->wait_reset ||
-	    (db->tx_live_cnt > 0 &&
-	     ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) ||
-	    (db->rx_error_cnt > 3)) {
-		/*
-		   printk("wait_reset %x, tx cnt %x, rx err %x, time %x\n", db->wait_reset, db->tx_packet_cnt, db->rx_error_cnt, jiffies-dev->trans_start);
-		 */
-		DMFE_DBUG(0, "Warn!! Warn!! Tx/Rx monitor step1", 0);
+	/* TX polling kick monitor */
+	if ( db->tx_packet_cnt &&
+		((jiffies - dev->trans_start) > DMFE_TX_KICK) ) {
+		outl(0x1, dev->base_addr + DCR1);   /* Tx polling again */
+
+		/* TX Timeout */
+		if ( (jiffies - dev->trans_start) > DMFE_TX_TIMEOUT ) {
+			db->reset_TXtimeout++;
+			db->wait_reset = 1;
+			printk(KERN_WARNING "%s: Tx timeout - resetting\n",
+			       dev->name);
+		}
+	}
+
+	if (db->wait_reset) {
+		DMFE_DBUG(0, "Dynamic Reset device", db->tx_packet_cnt);
+		db->reset_count++;
 		dmfe_dynamic_reset(dev);
-		db->timer.expires = jiffies + DMFE_TIMER_WUT;
+		db->first_in_callback = 0;
+		db->timer.expires = DMFE_TIMER_WUT;
 		add_timer(&db->timer);
 		spin_unlock_irqrestore(&db->lock, flags);
 		return;
 	}
-	db->rx_error_cnt = 0;	/* Clear previos counter */
 
 	/* Link status check, Dynamic media type change */
 	if (db->chip_id == PCI_DM9132_ID)
@@ -1003,138 +1134,150 @@
 	else
 		tmp_cr12 = inb(db->ioaddr + DCR12);	/* DM9102/DM9102A */
 
-	if (((db->chip_id == PCI_DM9102_ID) && (db->chip_revision == 0x02000030)) ||
-	    ((db->chip_id == PCI_DM9132_ID) && (db->chip_revision == 0x02000010))) {
+	if ( ((db->chip_id == PCI_DM9102_ID) &&
+		(db->chip_revision == 0x02000030)) ||
+		((db->chip_id == PCI_DM9132_ID) &&
+		(db->chip_revision == 0x02000010)) ) {
 		/* DM9102A Chip */
 		if (tmp_cr12 & 2)
 			tmp_cr12 = 0x0;		/* Link failed */
 		else
-			tmp_cr12 = 0x3;		/* Link OK */
+			tmp_cr12 = 0x3;	/* Link OK */
 	}
-	if (!(tmp_cr12 & 0x3) && !db->link_failed) {
+
+	if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
 		/* Link Failed */
 		DMFE_DBUG(0, "Link Failed", tmp_cr12);
 		db->link_failed = 1;
-		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);	/* reset Phy */
-
-		/* 10/100M link failed, used 1M Home-Net */
-		db->cr6_data |= 0x00040000;	/* CR6 bit18 = 1, select Home-Net */
-		db->cr6_data &= ~0x00000200;	/* CR6 bit9 =0, half duplex mode */
-		update_cr6(db->cr6_data, db->ioaddr);
-
-		/* For DM9801 : PHY ID1 0181h, PHY ID2 B900h */
-		db->phy_id2 = phy_read(db->ioaddr, db->phy_addr, 3, db->chip_id);
-		if (db->phy_id2 == 0xb900)
-			phy_write(db->ioaddr, db->phy_addr, 25, 0x7e08, db->chip_id);
-	} else if ((tmp_cr12 & 0x3) && db->link_failed) {
-		DMFE_DBUG(0, "Link link OK", tmp_cr12);
-		db->link_failed = 0;
 
-		/* CR6 bit18=0, select 10/100M */
-		db->cr6_data &= ~0x00040000;
-		update_cr6(db->cr6_data, db->ioaddr);
+		/* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */
+		/* AUTO or force 1M Homerun/Longrun don't need */
+		if ( !(db->media_mode & 0x38) )
+			phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);
+
+		/* AUTO mode, if INT phyxcer link failed, select EXT device */
+		if (db->media_mode & DMFE_AUTO) {
+			/* 10/100M link failed, used 1M Home-Net */
+			db->cr6_data|=0x00040000;	/* bit18=1, MII */
+			db->cr6_data&=~0x00000200;	/* bit9=0, HD mode */
+			update_cr6(db->cr6_data, db->ioaddr);
+		}
+	} else
+		if ((tmp_cr12 & 0x3) && db->link_failed) {
+			DMFE_DBUG(0, "Link link OK", tmp_cr12);
+			db->link_failed = 0;
+
+			/* Auto Sense Speed */
+			if ( (db->media_mode & DMFE_AUTO) &&
+				dmfe_sense_speed(db) )
+				db->link_failed = 1;
+			dmfe_process_mode(db);
+			/* SHOW_MEDIA_TYPE(db->op_mode); */
+		}
 
-		/* Auto Sense Speed */
-		if (db->media_mode & DMFE_AUTO)
-			dmfe_sense_speed(db);
-		dmfe_process_mode(db);
-		update_cr6(db->cr6_data, db->ioaddr);
-		/* SHOW_MEDIA_TYPE(db->op_mode); */
+	/* HPNA remote command check */
+	if (db->HPNA_command & 0xf00) {
+		db->HPNA_timer--;
+		if (!db->HPNA_timer)
+			dmfe_HPNA_remote_cmd_chk(db);
 	}
-	/* reallocated rx descriptor buffer */
-	if (db->rx_avail_cnt < RX_DESC_CNT)
-		allocated_rx_buffer(db);
 
 	/* Timer active again */
-	db->timer.expires = jiffies + DMFE_TIMER_WUT;
+	db->timer.expires = DMFE_TIMER_WUT;
 	add_timer(&db->timer);
 	spin_unlock_irqrestore(&db->lock, flags);
 }
 
+
 /*
-   Dynamic reset the DM910X board
-   Stop DM910X board
-   Free Tx/Rx allocated memory
-   Reset DM910X board
-   Re-initialize DM910X board
+ *	Dynamic reset the DM910X board
+ *	Stop DM910X board
+ *	Free Tx/Rx allocated memory
+ *	Reset DM910X board
+ *	Re-initilize DM910X board
  */
-static void dmfe_dynamic_reset(struct net_device *dev)
+
+static void dmfe_dynamic_reset(struct DEVICE *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
 
 	DMFE_DBUG(0, "dmfe_dynamic_reset()", 0);
 
-	/* Enter dynamic reset route */
-	db->in_reset_state = 1;
+	/* Sopt MAC controller */
+	db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);	/* Disable Tx/Rx */
+	update_cr6(db->cr6_data, dev->base_addr);
+	outl(0, dev->base_addr + DCR7);		/* Disable Interrupt */
+	outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);
 
 	/* Disable upper layer interface */
 	netif_stop_queue(dev);
-	
-	db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);		/* Disable Tx/Rx */
-	update_cr6(db->cr6_data, dev->base_addr);
 
 	/* Free Rx Allocate buffer */
 	dmfe_free_rxbuffer(db);
 
 	/* system variable init */
-	db->tx_int_pkt_num = TX_IRQ_THR;
-	db->tx_live_cnt = 0;
+	db->tx_packet_cnt = 0;
+	db->tx_queue_cnt = 0;
 	db->rx_avail_cnt = 0;
-	db->link_failed = 0;
+	db->link_failed = 1;
 	db->wait_reset = 0;
-	db->rx_error_cnt = 0;
 
-	/* Re-initialize DM910X board */
+	/* Re-initilize DM910X board */
 	dmfe_init_dm910x(dev);
 
-	/* Leave dynamic reser route */
-	db->in_reset_state = 0;
-
 	/* Restart upper layer interface */
 	netif_wake_queue(dev);
 }
 
+
 /*
-   free all allocated rx buffer 
+ *	free all allocated rx buffer
  */
-static void dmfe_free_rxbuffer(struct dmfe_board_info *db)
+
+static void dmfe_free_rxbuffer(struct dmfe_board_info * db)
 {
 	DMFE_DBUG(0, "dmfe_free_rxbuffer()", 0);
 
 	/* free allocated rx buffer */
 	while (db->rx_avail_cnt) {
-		dev_kfree_skb((void *) (db->rx_ready_ptr->rx_skb_ptr));
+		dev_kfree_skb( (void *) (db->rx_ready_ptr->rx_skb_ptr) );
 		db->rx_ready_ptr = (struct rx_desc *) db->rx_ready_ptr->next_rx_desc;
 		db->rx_avail_cnt--;
 	}
 }
 
+
 /*
-   Reused the SK buffer
+ *	Reused the SK buffer
  */
-static void dmfe_reused_skb(struct dmfe_board_info *db, struct sk_buff *skb)
+
+static void dmfe_reused_skb(struct dmfe_board_info *db, struct sk_buff * skb)
 {
 	struct rx_desc *rxptr = db->rx_insert_ptr;
 
 	if (!(rxptr->rdes0 & 0x80000000)) {
 		rxptr->rx_skb_ptr = (u32) skb;
-		rxptr->rdes2 = virt_to_bus(skb->tail);
-		rxptr->rdes0 = 0x80000000;
+		rxptr->rdes2 = cpu_to_le32( pci_map_single(db->net_dev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+		rxptr->rdes0 = cpu_to_le32(0x80000000);
 		db->rx_avail_cnt++;
 		db->rx_insert_ptr = (struct rx_desc *) rxptr->next_rx_desc;
 	} else
 		DMFE_DBUG(0, "SK Buffer reused method error", db->rx_avail_cnt);
 }
 
+
 /*
-   Initialize transmit/Receive descriptor 
-   Using Chain structure, and allocated Tx/Rx buffer
+ *	Initialize transmit/Receive descriptor
+ *	Using Chain structure, and allocated Tx/Rx buffer
  */
+
 static void dmfe_descriptor_init(struct dmfe_board_info *db, u32 ioaddr)
 {
 	struct tx_desc *tmp_tx;
 	struct rx_desc *tmp_rx;
 	unsigned char *tmp_buf;
+	dma_addr_t tmp_tx_dma, tmp_rx_dma;
+	dma_addr_t tmp_buf_dma;
 	int i;
 
 	DMFE_DBUG(0, "dmfe_descriptor_init()", 0);
@@ -1142,67 +1285,77 @@
 	/* tx descriptor start pointer */
 	db->tx_insert_ptr = db->first_tx_desc;
 	db->tx_remove_ptr = db->first_tx_desc;
-	outl(virt_to_bus(db->first_tx_desc), ioaddr + DCR4);	/* Init CR4 */
+	outl(db->first_tx_desc_dma, ioaddr + DCR4);     /* TX DESC address */
 
 	/* rx descriptor start pointer */
-	db->first_rx_desc = (struct rx_desc *)
-	    ((u32) db->first_tx_desc + sizeof(struct rx_desc) * TX_DESC_CNT);
+	db->first_rx_desc = (struct rx_desc *) ( (u32) db->first_tx_desc + sizeof(struct rx_desc) * TX_DESC_CNT );
+	db->first_rx_desc_dma = ( db->first_tx_desc_dma + sizeof(struct rx_desc) * TX_DESC_CNT);
 	db->rx_insert_ptr = db->first_rx_desc;
 	db->rx_ready_ptr = db->first_rx_desc;
-	outl(virt_to_bus(db->first_rx_desc), ioaddr + DCR3);	/* Init CR3 */
+	outl(db->first_rx_desc_dma, ioaddr + DCR3);	/* RX DESC address */
 
 	/* Init Transmit chain */
 	tmp_buf = db->buf_pool_start;
+	tmp_buf_dma = db->buf_pool_dma_start;
+	tmp_tx_dma = db->first_tx_desc_dma;
 	for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {
 		tmp_tx->tx_buf_ptr = (u32) tmp_buf;
-		tmp_tx->tdes0 = 0;
-		tmp_tx->tdes1 = 0x81000000;	/* IC, chain */
-		tmp_tx->tdes2 = (u32) virt_to_bus(tmp_buf);
-		tmp_tx->tdes3 = (u32) virt_to_bus(tmp_tx) + sizeof(struct tx_desc);
+		tmp_tx->tdes0 = cpu_to_le32(0);
+		tmp_tx->tdes1 = cpu_to_le32(0x81000000);	/* IC, chain */
+		tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
+		tmp_tx_dma += sizeof(struct tx_desc);
+		tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
 		tmp_tx->next_tx_desc = (u32) ((u32) tmp_tx + sizeof(struct tx_desc));
 		tmp_buf = (unsigned char *) ((u32) tmp_buf + TX_BUF_ALLOC);
+		tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
 	}
-	(--tmp_tx)->tdes3 = (u32) virt_to_bus(db->first_tx_desc);
+	(--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
 	tmp_tx->next_tx_desc = (u32) db->first_tx_desc;
 
-	/* Init Receive descriptor chain */
+	 /* Init Receive descriptor chain */
+	tmp_rx_dma=db->first_rx_desc_dma;
 	for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {
-		tmp_rx->rdes0 = 0;
-		tmp_rx->rdes1 = 0x01000600;
-		tmp_rx->rdes3 = (u32) virt_to_bus(tmp_rx) + sizeof(struct rx_desc);
+		tmp_rx->rdes0 = cpu_to_le32(0);
+		tmp_rx->rdes1 = cpu_to_le32(0x01000600);
+		tmp_rx_dma += sizeof(struct rx_desc);
+		tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
 		tmp_rx->next_rx_desc = (u32) ((u32) tmp_rx + sizeof(struct rx_desc));
 	}
-	(--tmp_rx)->rdes3 = (u32) virt_to_bus(db->first_rx_desc);
+	(--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
 	tmp_rx->next_rx_desc = (u32) db->first_rx_desc;
 
 	/* pre-allocated Rx buffer */
 	allocated_rx_buffer(db);
 }
 
+
 /*
-   Update CR6 value
-   Firstly stop DM910X , then written value and start
+ *	Update CR6 vaule
+ *	Firstly stop DM910X , then written value and start
  */
+
 static void update_cr6(u32 cr6_data, u32 ioaddr)
 {
 	u32 cr6_tmp;
 
-	cr6_tmp = cr6_data & ~0x2002;	/* stop Tx/Rx */
+	cr6_tmp = cr6_data & ~0x2002;           /* stop Tx/Rx */
 	outl(cr6_tmp, ioaddr + DCR6);
 	udelay(5);
 	outl(cr6_data, ioaddr + DCR6);
-	cr6_tmp = inl(ioaddr + DCR6);
-	/* printk("CR6 update %x ", cr6_tmp); */
+	udelay(5);
 }
 
-/* Send a setup frame for DM9132
-   This setup frame initialize DM910X address filter mode
- */
-static void dm9132_id_table(struct net_device *dev, int mc_cnt)
+
+/*
+ *	Send a setup frame for DM9132
+ *	This setup frame initilize DM910X addres filter mode
+*/
+
+static void dm9132_id_table(struct DEVICE *dev, int mc_cnt)
 {
 	struct dev_mc_list *mcptr;
-	u16 *addrptr;
-	u32 ioaddr = dev->base_addr + 0xc0;	/* ID Table */
+	u16 * addrptr;
+	u32 ioaddr = dev->base_addr+0xc0;		/* ID Table */
 	u32 hash_val;
 	u16 i, hash_table[4];
 
@@ -1226,26 +1379,28 @@
 
 	/* the multicast address in Hash Table : 64 bits */
 	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
-		hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+		hash_val = cal_CRC( (char *) mcptr->dmi_addr, 6, 0) & 0x3f;
 		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
 	}
 
 	/* Write the hash table to MAC MD table */
-	for (i = 0; i < 4; i++, ioaddr += 4) {
+	for (i = 0; i < 4; i++, ioaddr += 4)
 		outw(hash_table[i], ioaddr);
-	}
 }
 
-/* Send a setup frame for DM9102/DM9102A
-   This setup frame initialize DM910X address filter mode
+
+/*
+ *	Send a setup frame for DM9102/DM9102A
+ *	This setup frame initilize DM910X addres filter mode
  */
-static void send_filter_frame(struct net_device *dev, int mc_cnt)
+
+static void send_filter_frame(struct DEVICE *dev, int mc_cnt)
 {
 	struct dmfe_board_info *db = dev->priv;
 	struct dev_mc_list *mcptr;
 	struct tx_desc *txptr;
-	u16 *addrptr;
-	u32 *suptr;
+	u16 * addrptr;
+	u32 * suptr;
 	int i;
 
 	DMFE_DBUG(0, "send_filter_frame()", 0);
@@ -1253,12 +1408,6 @@
 	txptr = db->tx_insert_ptr;
 	suptr = (u32 *) txptr->tx_buf_ptr;
 
-	if (txptr->tdes0 & 0x80000000) {
-		printk(KERN_WARNING "%s: Too busy to send filter frame\n",
-		       dev->name);
-		return;
-	}
-
 	/* Node address */
 	addrptr = (u16 *) dev->dev_addr;
 	*suptr++ = addrptr[0];
@@ -1278,26 +1427,35 @@
 		*suptr++ = addrptr[2];
 	}
 
-	for (i=0; i < 14; i++) 
+	for (; i<14; i++) {
 		*suptr++ = 0xffff;
 		*suptr++ = 0xffff;
 		*suptr++ = 0xffff;
-	
+	}
+
 	/* prepare the setup frame */
 	db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
-	db->tx_live_cnt++;
-	txptr->tdes1 = 0x890000c0;
-	/* Send the setup packet */
-	txptr->tdes0 = 0x80000000;
-	update_cr6(db->cr6_data | 0x2000, dev->base_addr);
-	outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling command */
-	update_cr6(db->cr6_data, dev->base_addr);
+	txptr->tdes1 = cpu_to_le32(0x890000c0);
+
+	/* Resource Check and Send the setup packet */
+	if (!db->tx_packet_cnt) {
+		/* Resource Empty */
+		db->tx_packet_cnt++;
+		txptr->tdes0 = cpu_to_le32(0x80000000);
+		update_cr6(db->cr6_data | 0x2000, dev->base_addr);
+		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling */
+		update_cr6(db->cr6_data, dev->base_addr);
+		dev->trans_start = jiffies;
+	} else
+		db->tx_queue_cnt++;	/* Put in TX queue */
 }
 
+
 /*
  *	Allocate rx buffer,
- *	Allocate as many Rx buffers as possible.
+ *	As possible as allocated maxiumn Rx buffer
  */
+
 static void allocated_rx_buffer(struct dmfe_board_info *db)
 {
 	struct rx_desc *rxptr;
@@ -1305,12 +1463,12 @@
 
 	rxptr = db->rx_insert_ptr;
 
-	while (db->rx_avail_cnt < RX_DESC_CNT) {
-		if ((skb = alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC)) == NULL)
+	while(db->rx_avail_cnt < RX_DESC_CNT) {
+		if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )
 			break;
 		rxptr->rx_skb_ptr = (u32) skb;
-		rxptr->rdes2 = virt_to_bus(skb->tail);
-		rxptr->rdes0 = 0x80000000;
+		rxptr->rdes2 = cpu_to_le32( pci_map_single(db->net_dev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );
+		rxptr->rdes0 = cpu_to_le32(0x80000000);
 		rxptr = (struct rx_desc *) rxptr->next_rx_desc;
 		db->rx_avail_cnt++;
 	}
@@ -1318,9 +1476,11 @@
 	db->rx_insert_ptr = rxptr;
 }
 
+
 /*
-   Read one word data from the serial ROM
+ *	Read one word data from the serial ROM
  */
+
 static u16 read_srom_word(long ioaddr, int offset)
 {
 	int i;
@@ -1355,113 +1515,150 @@
 	return srom_data;
 }
 
+
 /*
  *	Auto sense the media mode
  */
- 
-static void dmfe_sense_speed(struct dmfe_board_info *db)
+
+static u8 dmfe_sense_speed(struct dmfe_board_info * db)
 {
-	int i;
-	u16 phy_mode = 0;
+	u8 ErrFlag = 0;
+	u16 phy_mode;
 
-	for (i = 1000; i; i--) {
-		udelay(5);
-		phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
-		if ((phy_mode & 0x24) == 0x24)
-			break;
-	}
+	/* CR6 bit18=0, select 10/100M */
+	update_cr6( (db->cr6_data & ~0x40000), db->ioaddr);
+
+	phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
+	phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
 
-	if (i) {
+	if ( (phy_mode & 0x24) == 0x24 ) {
 		if (db->chip_id == PCI_DM9132_ID)	/* DM9132 */
 			phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;
-		else		/* DM9102/DM9102A */
+		else 				/* DM9102/DM9102A */
 			phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;
-		/* printk("Phy_mode %x ",phy_mode); */
+		/* printk("<DMFE>: Phy_mode %x ",phy_mode); */
 		switch (phy_mode) {
-		case 0x1000:
-			db->op_mode = DMFE_10MHF;
-			break;
-		case 0x2000:
-			db->op_mode = DMFE_10MFD;
-			break;
-		case 0x4000:
-			db->op_mode = DMFE_100MHF;
-			break;
-		case 0x8000:
-			db->op_mode = DMFE_100MFD;
-			break;
-		default:
-			db->op_mode = DMFE_10MHF;
-			DMFE_DBUG(0, "Media Type error, phy reg17", phy_mode);
+		case 0x1000: db->op_mode = DMFE_10MHF; break;
+		case 0x2000: db->op_mode = DMFE_10MFD; break;
+		case 0x4000: db->op_mode = DMFE_100MHF; break;
+		case 0x8000: db->op_mode = DMFE_100MFD; break;
+		default: db->op_mode = DMFE_10MHF;
+			ErrFlag = 1;
 			break;
 		}
 	} else {
 		db->op_mode = DMFE_10MHF;
 		DMFE_DBUG(0, "Link Failed :", phy_mode);
+		ErrFlag = 1;
+	}
+
+	return ErrFlag;
+}
+
+
+/*
+ *	Set 10/100 phyxcer capability
+ *	AUTO mode : phyxcer register4 is NIC capability
+ *	Force mode: phyxcer register4 is the force media
+ */
+
+static void dmfe_set_phyxcer(struct dmfe_board_info *db)
+{
+	u16 phy_reg;
+
+	/* Select 10/100M phyxcer */
+	db->cr6_data &= ~0x40000;
+	update_cr6(db->cr6_data, db->ioaddr);
+
+	/* DM9009 Chip: Phyxcer reg18 bit12=0 */
+	if (db->chip_id == PCI_DM9009_ID) {
+		phy_reg = phy_read(db->ioaddr, db->phy_addr, 18, db->chip_id) & ~0x1000;
+		phy_write(db->ioaddr, db->phy_addr, 18, phy_reg, db->chip_id);
+	}
+
+	/* Phyxcer capability setting */
+	phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+	if (db->media_mode & DMFE_AUTO) {
+		/* AUTO Mode */
+		phy_reg |= db->PHY_reg4;
+	} else {
+		/* Force Mode */
+		switch(db->media_mode) {
+		case DMFE_10MHF: phy_reg |= 0x20; break;
+		case DMFE_10MFD: phy_reg |= 0x40; break;
+		case DMFE_100MHF: phy_reg |= 0x80; break;
+		case DMFE_100MFD: phy_reg |= 0x100; break;
+		}
+		if (db->chip_id == PCI_DM9009_ID) phy_reg &= 0x61;
 	}
+
+  	/* Write new capability to Phyxcer Reg4 */
+	if ( !(phy_reg & 0x01e0)) {
+		phy_reg|=db->PHY_reg4;
+		db->media_mode|=DMFE_AUTO;
+	}
+	phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ 	/* Restart Auto-Negotiation */
+	if ( db->chip_type && (db->chip_id == PCI_DM9102_ID) )
+		phy_write(db->ioaddr, db->phy_addr, 0, 0x1800, db->chip_id);
+	if ( !db->chip_type )
+		phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
 }
 
+
 /*
-   Process op-mode
-   AUTO mode : PHY controller in Auto-negotiation Mode
-   Force mode: PHY controller in force mode with HUB
-   N-way force capability with SWITCH
+ *	Process op-mode
+ *	AUTO mode : PHY controller in Auto-negotiation Mode
+ *	Force mode: PHY controller in force mode with HUB
+ *			N-way force capability with SWITCH
  */
+
 static void dmfe_process_mode(struct dmfe_board_info *db)
 {
 	u16 phy_reg;
 
 	/* Full Duplex Mode Check */
-	db->cr6_data &= ~CR6_FDM;	/* Clear Full Duplex Bit */
 	if (db->op_mode & 0x4)
-		db->cr6_data |= CR6_FDM;
+		db->cr6_data |= CR6_FDM;	/* Set Full Duplex Bit */
+	else
+		db->cr6_data &= ~CR6_FDM;	/* Clear Full Duplex Bit */
 
-	if (!(db->media_mode & DMFE_AUTO)) {	/* Force Mode Check */
-		/* User force the media type */
-		phy_reg = phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id);
-		/* printk("Nway phy_reg5 %x ",phy_reg); */
-		if (phy_reg & 0x1) {
-			/* parter own the N-Way capability */
-			phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x1e0;
-			switch (db->op_mode) {
-			case DMFE_10MHF:
-				phy_reg |= 0x20;
-				break;
-			case DMFE_10MFD:
-				phy_reg |= 0x40;
-				break;
-			case DMFE_100MHF:
-				phy_reg |= 0x80;
-				break;
-			case DMFE_100MFD:
-				phy_reg |= 0x100;
-				break;
-			}
-			phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
-		} else {
-			/* parter without the N-Way capability */
-			switch (db->op_mode) {
-			case DMFE_10MHF:
-				phy_reg = 0x0;
-				break;
-			case DMFE_10MFD:
-				phy_reg = 0x100;
-				break;
-			case DMFE_100MHF:
-				phy_reg = 0x2000;
-				break;
-			case DMFE_100MFD:
-				phy_reg = 0x2100;
-				break;
+	/* Transciver Selection */
+	if (db->op_mode & 0x10)		/* 1M HomePNA */
+		db->cr6_data |= 0x40000;/* External MII select */
+	else
+		db->cr6_data &= ~0x40000;/* Internal 10/100 transciver */
+
+	update_cr6(db->cr6_data, db->ioaddr);
+
+	/* 10/100M phyxcer force mode need */
+	if ( !(db->media_mode & 0x18)) {
+		/* Forece Mode */
+		phy_reg = phy_read(db->ioaddr, db->phy_addr, 6, db->chip_id);
+		if ( !(phy_reg & 0x1) ) {
+			/* parter without N-Way capability */
+			phy_reg = 0x0;
+			switch(db->op_mode) {
+			case DMFE_10MHF: phy_reg = 0x0; break;
+			case DMFE_10MFD: phy_reg = 0x100; break;
+			case DMFE_100MHF: phy_reg = 0x2000; break;
+			case DMFE_100MFD: phy_reg = 0x2100; break;
 			}
 			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
+       			if ( db->chip_type && (db->chip_id == PCI_DM9102_ID) )
+				mdelay(20);
+			phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
 		}
 	}
 }
 
+
 /*
-   Write a word to Phy register
+ *	Write a word to Phy register
  */
+
 static void phy_write(u32 iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
 {
 	u16 i;
@@ -1486,11 +1683,11 @@
 		phy_write_1bit(ioaddr, PHY_DATA_0);
 		phy_write_1bit(ioaddr, PHY_DATA_1);
 
-		/* Send Phy address */
+		/* Send Phy addres */
 		for (i = 0x10; i > 0; i = i >> 1)
 			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
 
-		/* Send register address */
+		/* Send register addres */
 		for (i = 0x10; i > 0; i = i >> 1)
 			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
 
@@ -1499,14 +1696,16 @@
 		phy_write_1bit(ioaddr, PHY_DATA_0);
 
 		/* Write a word data to PHY controller */
-		for (i = 0x8000; i > 0; i >>= 1)
+		for ( i = 0x8000; i > 0; i >>= 1)
 			phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0);
 	}
 }
 
+
 /*
-   Read a word data from phy register
+ *	Read a word data from phy register
  */
+
 static u16 phy_read(u32 iobase, u8 phy_addr, u8 offset, u32 chip_id)
 {
 	int i;
@@ -1519,8 +1718,8 @@
 		phy_data = inw(ioaddr);
 	} else {
 		/* DM9102/DM9102A Chip */
-
 		ioaddr = iobase + DCR9;
+
 		/* Send 33 synchronization clock to Phy controller */
 		for (i = 0; i < 35; i++)
 			phy_write_1bit(ioaddr, PHY_DATA_1);
@@ -1533,11 +1732,11 @@
 		phy_write_1bit(ioaddr, PHY_DATA_1);
 		phy_write_1bit(ioaddr, PHY_DATA_0);
 
-		/* Send Phy address */
+		/* Send Phy addres */
 		for (i = 0x10; i > 0; i = i >> 1)
 			phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0);
 
-		/* Send register address */
+		/* Send register addres */
 		for (i = 0x10; i > 0; i = i >> 1)
 			phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : PHY_DATA_0);
 
@@ -1554,41 +1753,47 @@
 	return phy_data;
 }
 
+
 /*
-   Write one bit data to Phy Controller
+ *	Write one bit data to Phy Controller
  */
+
 static void phy_write_1bit(u32 ioaddr, u32 phy_data)
 {
-	outl(phy_data, ioaddr);	/* MII Clock Low */
+	outl(phy_data, ioaddr);			/* MII Clock Low */
 	udelay(1);
 	outl(phy_data | MDCLKH, ioaddr);	/* MII Clock High */
 	udelay(1);
-	outl(phy_data, ioaddr);	/* MII Clock Low */
+	outl(phy_data, ioaddr);			/* MII Clock Low */
 	udelay(1);
 }
 
+
 /*
-   Read one bit phy data from PHY controller
+ *	Read one bit phy data from PHY controller
  */
+
 static u16 phy_read_1bit(u32 ioaddr)
 {
 	u16 phy_data;
 
 	outl(0x50000, ioaddr);
 	udelay(1);
-	phy_data = (inl(ioaddr) >> 19) & 0x1;
+	phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
 	outl(0x40000, ioaddr);
 	udelay(1);
 
 	return phy_data;
 }
 
+
 /*
-   Calculate the CRC valude of the Rx packet
-   flag = 1 : return the reverse CRC (for the received packet CRC)
-   0 : return the normal CRC (for Hash Table index)
+ *	Calculate the CRC valude of the Rx packet
+ *	flag = 	1 : return the reverse CRC (for the received packet CRC)
+ *		0 : return the normal CRC (for Hash Table index)
  */
-unsigned long cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
+
+unsigned long cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
 {
 	unsigned long Crc = 0xffffffff;
 
@@ -1603,10 +1808,190 @@
 }
 
 
-static struct pci_device_id dmfe_pci_tbl[] __initdata = {
+/*
+ *	Parser SROM and media mode
+ */
+
+static void dmfe_parse_srom(struct dmfe_board_info * db)
+{
+	char * srom = db->srom;
+	int dmfe_mode, tmp_reg;
+
+	DMFE_DBUG(0, "dmfe_parse_srom() ", 0);
+
+	/* Init CR15 */
+	db->cr15_data = CR15_DEFAULT;
+
+	/* Check SROM Version */
+	if ( ( (int) srom[18] & 0xff) == SROM_V41_CODE) {
+		/* SROM V4.01 */
+		/* Get NIC support media mode */
+		db->NIC_capability = *(u16 *) (&srom[34]);
+		db->PHY_reg4 = 0;
+		for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) {
+			switch( db->NIC_capability & tmp_reg ) {
+			case 0x1: db->PHY_reg4 |= 0x0020; break;
+			case 0x2: db->PHY_reg4 |= 0x0040; break;
+			case 0x4: db->PHY_reg4 |= 0x0080; break;
+			case 0x8: db->PHY_reg4 |= 0x0100; break;
+			}
+		}
+
+		/* Media Mode Force or not check */
+		dmfe_mode = *( (int *) &srom[34]) & *( (int *) &srom[36] );
+		switch(dmfe_mode) {
+		case 0x4: dmfe_media_mode = DMFE_100MHF; break;	/* 100MHF */
+		case 0x2: dmfe_media_mode = DMFE_10MFD; break;	/* 10MFD */
+		case 0x8: dmfe_media_mode = DMFE_100MFD; break;	/* 100MFD */
+		case 0x100:
+		case 0x200: dmfe_media_mode = DMFE_1M_HPNA; break;/* HomePNA */
+		}
+
+		/* Special Function setting */
+		/* VLAN function */
+		if ( (SF_mode & 0x1) || (srom[43] & 0x80) )
+			db->cr15_data |= 0x40;
+
+		/* Flow Control */
+		if ( (SF_mode & 0x2) || (srom[40] & 0x1) )
+			db->cr15_data |= 0x400;
+
+		/* TX pause packet */
+		if ( (SF_mode & 0x4) || (srom[40] & 0xe) )
+			db->cr15_data |= 0x9800;
+	}
+
+	/* Parse HPNA parameter */
+	db->HPNA_command = 1;
+
+	/* Accept remote command or not */
+	if (HPNA_rx_cmd == 0)
+		db->HPNA_command |= 0x8000;
+
+	 /* Issue remote command & operation mode */
+	if (HPNA_tx_cmd == 1)
+		switch(HPNA_mode) {	/* Issue Remote Command */
+		case 0: db->HPNA_command |= 0x0904; break;
+		case 1: db->HPNA_command |= 0x0a00; break;
+		case 2: db->HPNA_command |= 0x0506; break;
+		case 3: db->HPNA_command |= 0x0602; break;
+		}
+	else
+		switch(HPNA_mode) {	/* Don't Issue */
+		case 0: db->HPNA_command |= 0x0004; break;
+		case 1: db->HPNA_command |= 0x0000; break;
+		case 2: db->HPNA_command |= 0x0006; break;
+		case 3: db->HPNA_command |= 0x0002; break;
+		}
+
+	/* Check DM9801 or DM9802 present or not */
+	db->HPNA_present = 0;
+	update_cr6(db->cr6_data|0x40000, db->ioaddr);
+	tmp_reg = phy_read(db->ioaddr, db->phy_addr, 3, db->chip_id);
+	if ( ( tmp_reg & 0xfff0 ) == 0xb900 ) {
+		/* DM9801 or DM9802 present */
+		db->HPNA_timer = 8;
+		if ( phy_read(db->ioaddr, db->phy_addr, 31, db->chip_id) == 0x4404) {
+			/* DM9801 HomeRun */
+			db->HPNA_present = 1;
+			dmfe_program_DM9801(db, tmp_reg);
+		} else {
+			/* DM9802 LongRun */
+			db->HPNA_present = 2;
+			dmfe_program_DM9802(db);
+		}
+	}
+
+}
+
+
+/*
+ *	Init HomeRun DM9801
+ */
+
+static void dmfe_program_DM9801(struct dmfe_board_info * db, int HPNA_rev)
+{
+	uint reg17, reg25;
+
+	if ( !HPNA_NoiseFloor ) HPNA_NoiseFloor = DM9801_NOISE_FLOOR;
+	switch(HPNA_rev) {
+	case 0xb900: /* DM9801 E3 */
+		db->HPNA_command |= 0x1000;
+		reg25 = phy_read(db->ioaddr, db->phy_addr, 24, db->chip_id);
+		reg25 = ( (reg25 + HPNA_NoiseFloor) & 0xff) | 0xf000;
+		reg17 = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id);
+		break;
+	case 0xb901: /* DM9801 E4 */
+		reg25 = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);
+		reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor;
+		reg17 = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id);
+		reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor + 3;
+		break;
+	case 0xb902: /* DM9801 E5 */
+	case 0xb903: /* DM9801 E6 */
+	default:
+		db->HPNA_command |= 0x1000;
+		reg25 = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);
+		reg25 = (reg25 & 0xff00) + HPNA_NoiseFloor - 5;
+		reg17 = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id);
+		reg17 = (reg17 & 0xfff0) + HPNA_NoiseFloor;
+		break;
+	}
+	phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+	phy_write(db->ioaddr, db->phy_addr, 17, reg17, db->chip_id);
+	phy_write(db->ioaddr, db->phy_addr, 25, reg25, db->chip_id);
+}
+
+
+/*
+ *	Init HomeRun DM9802
+ */
+
+static void dmfe_program_DM9802(struct dmfe_board_info * db)
+{
+	uint phy_reg;
+
+	if ( !HPNA_NoiseFloor ) HPNA_NoiseFloor = DM9802_NOISE_FLOOR;
+	phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+	phy_reg = phy_read(db->ioaddr, db->phy_addr, 25, db->chip_id);
+	phy_reg = ( phy_reg & 0xff00) + HPNA_NoiseFloor;
+	phy_write(db->ioaddr, db->phy_addr, 25, phy_reg, db->chip_id);
+}
+
+
+/*
+ *	Check remote HPNA power and speed status. If not correct,
+ *	issue command again.
+*/
+
+static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db)
+{
+	uint phy_reg;
+
+	/* Got remote device status */
+	phy_reg = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0x60;
+	switch(phy_reg) {
+	case 0x00: phy_reg = 0x0a00;break; /* LP/LS */
+	case 0x20: phy_reg = 0x0900;break; /* LP/HS */
+	case 0x40: phy_reg = 0x0600;break; /* HP/LS */
+	case 0x60: phy_reg = 0x0500;break; /* HP/HS */
+	}
+
+	/* Check remote device status match our setting ot not */
+	if ( phy_reg != (db->HPNA_command & 0x0f00) ) {
+		phy_write(db->ioaddr, db->phy_addr, 16, db->HPNA_command, db->chip_id);
+		db->HPNA_timer=8;
+	} else
+		db->HPNA_timer=600;	/* Match, every 10 minutes, check */
+}
+
+
+
+static struct pci_device_id dmfe_pci_tbl[] __devinitdata = {
 	{ 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID },
 	{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID },
 	{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID },
+	{ 0x1282, 0x9009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9009_ID },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, dmfe_pci_tbl);
@@ -1624,20 +2009,23 @@
 MODULE_PARM(mode, "i");
 MODULE_PARM(cr6set, "i");
 MODULE_PARM(chkmode, "i");
+MODULE_PARM(HPNA_mode, "i");
+MODULE_PARM(HPNA_rx_cmd, "i");
+MODULE_PARM(HPNA_tx_cmd, "i");
+MODULE_PARM(HPNA_NoiseFloor, "i");
+MODULE_PARM(SF_mode, "i");
 
-/*	Description: 
+/*	Description:
  *	when user used insmod to add module, system invoked init_module()
- *	to initialize and register.
+ *	to initilize and register.
  */
- 
+
 static int __init dmfe_init_module(void)
 {
 	int rc;
-	
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
+
 	printk(version);
-#endif
+	printed_version = 1;
 
 	DMFE_DBUG(0, "init_module() ", debug);
 
@@ -1646,18 +2034,27 @@
 	if (cr6set)
 		dmfe_cr6_user_set = cr6set;
 
-	switch (mode) {
-	case 0:
-	case 1:
-	case 4:
-	case 5:
+ 	switch(mode) {
+   	case DMFE_10MHF:
+	case DMFE_100MHF:
+	case DMFE_10MFD:
+	case DMFE_100MFD:
+	case DMFE_1M_HPNA:
 		dmfe_media_mode = mode;
 		break;
-	default:
-		dmfe_media_mode = 8;
+	default:dmfe_media_mode = DMFE_AUTO;
 		break;
 	}
 
+	if (HPNA_mode > 4)
+		HPNA_mode = 0;		/* Default: LP/HS */
+	if (HPNA_rx_cmd > 1)
+		HPNA_rx_cmd = 0;	/* Default: Ignored remote cmd */
+	if (HPNA_tx_cmd > 1)
+		HPNA_tx_cmd = 0;	/* Default: Don't issue remote cmd */
+	if (HPNA_NoiseFloor > 15)
+		HPNA_NoiseFloor = 0;
+
 	rc = pci_module_init(&dmfe_driver);
 	if (rc < 0)
 		return rc;
@@ -1665,14 +2062,16 @@
 	return 0;
 }
 
+
 /*
- *	Description: 
+ *	Description:
  *	when user used rmmod to delete module, system invoked clean_module()
  *	to un-register all registered services.
  */
- 
+
 static void __exit dmfe_cleanup_module(void)
 {
+	DMFE_DBUG(0, "dmfe_clean_module() ", debug);
 	pci_unregister_driver(&dmfe_driver);
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.4.4/linux/drivers/net/epic100.c	Fri Apr 20 11:54:23 2001
+++ linux/drivers/net/epic100.c	Sat May 19 18:02:45 2001
@@ -41,8 +41,19 @@
 	* Merge becker version 1.11
 	* Move pci_enable_device before any PCI BAR len checks
 
+	LK1.1.7:
+	* { fill me in }
+
+	LK1.1.8:
+	* ethtool support (jgarzik)
+
 */
 
+#define DRV_NAME	"epic100"
+#define DRV_VERSION	"1.11+LK1.1.8"
+#define DRV_RELDATE	"May 18, 2001"
+
+
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
 
@@ -104,16 +115,18 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-"epic100.c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
+DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
 static char version2[] __devinitdata =
 "  http://www.scyld.com/network/epic100.html\n";
 static char version3[] __devinitdata =
-"  (unofficial 2.4.x kernel port, version 1.1.7, April 17, 2001)\n";
+"  (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
@@ -326,7 +339,7 @@
 static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int epic_rx(struct net_device *dev);
 static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int epic_close(struct net_device *dev);
 static struct net_device_stats *epic_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
@@ -375,7 +388,7 @@
 	}
 	SET_MODULE_OWNER(dev);
 
-	if (pci_request_regions(pdev, "epic100"))
+	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_free_netdev;
 
 #ifdef USE_IO_OPS
@@ -384,7 +397,7 @@
 	ioaddr = pci_resource_start (pdev, 1);
 	ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
 	if (!ioaddr) {
-		printk (KERN_ERR "epic100 %d: ioremap failed\n", card_idx);
+		printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
 		goto err_out_free_res;
 	}
 #endif
@@ -435,7 +448,7 @@
 		((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
 
 	if (debug > 2) {
-		printk(KERN_DEBUG "epic100(%s): EEPROM contents\n",
+		printk(KERN_DEBUG DRV_NAME "(%s): EEPROM contents\n",
 		       pdev->slot_name);
 		for (i = 0; i < 64; i++)
 			printk(" %4.4x%s", read_eeprom(ioaddr, i),
@@ -455,7 +468,7 @@
 			int mii_status = mdio_read(dev, phy, 1);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				ep->phys[phy_idx++] = phy;
-				printk(KERN_INFO "epic100(%s): MII transceiver #%d control "
+				printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
 					   "%4.4x status %4.4x.\n",
 					   pdev->slot_name, phy, mdio_read(dev, phy, 0), mii_status);
 			}
@@ -464,11 +477,11 @@
 		if (phy_idx != 0) {
 			phy = ep->phys[0];
 			ep->advertising = mdio_read(dev, phy, 4);
-			printk(KERN_INFO "epic100(%s): Autonegotiation advertising %4.4x link "
+			printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
 				   "partner %4.4x.\n",
 				   pdev->slot_name, ep->advertising, mdio_read(dev, phy, 5));
 		} else if ( ! (ep->chip_flags & NO_MII)) {
-			printk(KERN_WARNING "epic100(%s): ***WARNING***: No MII transceiver found!\n",
+			printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
 			       pdev->slot_name);
 			/* Use the known PHY address of the EPII. */
 			ep->phys[0] = 3;
@@ -483,7 +496,7 @@
 	/* The lower four bits are the media type. */
 	if (duplex) {
 		ep->duplex_lock = ep->full_duplex = 1;
-		printk(KERN_INFO "epic100(%s):  Forced full duplex operation requested.\n",
+		printk(KERN_INFO DRV_NAME "(%s):  Forced full duplex operation requested.\n",
 		       pdev->slot_name);
 	}
 	dev->if_port = ep->default_port = option;
@@ -496,7 +509,7 @@
 	dev->stop = &epic_close;
 	dev->get_stats = &epic_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
-	dev->do_ioctl = &mii_ioctl;
+	dev->do_ioctl = &netdev_ioctl;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
 
@@ -1331,13 +1344,39 @@
 	return;
 }
 
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct epic_private *np = dev->priv;
+	u32 ethcmd;
+		
+	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+		return -EFAULT;
+
+        switch (ethcmd) {
+        case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		strcpy(info.driver, DRV_NAME);
+		strcpy(info.version, DRV_VERSION);
+		strcpy(info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+
+        }
+	
+	return -EOPNOTSUPP;
+}
+
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
 
 	switch(cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
 		data[0] = ep->phys[0] & 0x1f;
 		/* Fall Through */
@@ -1432,7 +1471,7 @@
 
 
 static struct pci_driver epic_driver = {
-	name:		"epic100",
+	name:		DRV_NAME,
 	id_table:	epic_pci_tbl,
 	probe:		epic_init_one,
 	remove:		epic_remove_one,
diff -u --recursive --new-file v2.4.4/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.4.4/linux/drivers/net/eql.c	Wed Apr 18 14:40:06 2001
+++ linux/drivers/net/eql.c	Mon May 14 23:55:12 2001
@@ -422,6 +422,8 @@
 				slave_t *s = eql_new_slave ();
 				equalizer_t *eql = 
 					(equalizer_t *) master_dev->priv;
+				if (!s)
+					return -ENOMEM;
 				s->dev = slave_dev;
 				s->priority = srq.priority;
 				s->priority_bps = srq.priority;
diff -u --recursive --new-file v2.4.4/linux/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- v2.4.4/linux/drivers/net/fealnx.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/fealnx.c	Thu May 24 15:37:37 2001
@@ -0,0 +1,1777 @@
+/*
+	Written 1998-2000 by Donald Becker.
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	Support information and updates available at
+	http://www.scyld.com/network/pci-skeleton.html
+*/
+
+static int debug = 0;		/* 1-> print debug message */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */
+static int multicast_filter_limit = 32;
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme. */
+/* Setting to > 1518 effectively disables this feature.          */
+static int rx_copybreak = 0;
+
+/* Used to pass the media type, etc.                            */
+/* Both 'options[]' and 'full_duplex[]' should exist for driver */
+/* interoperability.                                            */
+/* The media type is usually passed in 'options[]'.             */
+#define MAX_UNITS 8		/* More are supported, limit only on options */
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+
+/* Operational parameters that are set at compile time.                 */
+/* Keep the ring sizes a power of two for compile efficiency.           */
+/* The compiler will convert <unsigned>'%'<2^N> into a bit mask.        */
+/* Making the Tx ring too large decreases the effectiveness of channel  */
+/* bonding and packet priority.                                         */
+/* There are no ill effects from too-large receive rings.               */
+// 88-12-9 modify,
+// #define TX_RING_SIZE    16
+// #define RX_RING_SIZE    32
+#define TX_RING_SIZE    6
+#define RX_RING_SIZE    12
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT      (2*HZ)
+
+#define PKT_BUF_SZ      1536	/* Size of each temporary Rx buffer. */
+
+
+/* Include files, designed to support most kernel versions 2.0.0 and later. */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <asm/processor.h>	/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+/* These identify the driver base version and may not be removed. */
+static char version[] __devinitdata =
+KERN_INFO "fealnx.c:v2.50 1/17/2001\n";
+
+
+/* This driver was written to use PCI memory space, however some x86 systems
+   work only with I/O space accesses. */
+#ifndef __alpha__
+#define USE_IO_OPS
+#endif
+
+#ifdef USE_IO_OPS
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+#define readb inb
+#define readw inw
+#define readl inl
+#define writeb outb
+#define writew outw
+#define writel outl
+#endif
+
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. */
+/* This is only in the support-all-kernels source code. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+MODULE_AUTHOR("Myson or whoever");
+MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(min_pci_latency, "i");
+MODULE_PARM(debug, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(multicast_filter_limit, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+
+#define MIN_REGION_SIZE 136
+
+enum pci_flags_bit {
+	PCI_USES_IO = 1,
+	PCI_USES_MEM = 2,
+	PCI_USES_MASTER = 4,
+	PCI_ADDR0 = 0x10 << 0,
+	PCI_ADDR1 = 0x10 << 1,
+	PCI_ADDR2 = 0x10 << 2,
+	PCI_ADDR3 = 0x10 << 3,
+};
+
+/* A chip capabilities table, matching the entries in pci_tbl[] above. */
+enum chip_capability_flags {
+	HAS_MII_XCVR,
+	HAS_CHIP_XCVR,
+};
+
+/* 89/6/13 add, */
+/* for different PHY */
+enum phy_type_flags {
+	MysonPHY = 1,
+	AhdocPHY = 2,
+	SeeqPHY = 3,
+	MarvellPHY = 4,
+	Myson981 = 5,
+	LevelOnePHY = 6,
+	OtherPHY = 10,
+};
+
+struct chip_info {
+	char *chip_name;
+	int io_size;
+	int flags;
+};
+
+static struct chip_info skel_netdrv_tbl[] = {
+	{"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
+	{"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR},
+	{"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
+};
+
+/* Offsets to the Command and Status Registers. */
+enum fealnx_offsets {
+	PAR0 = 0x0,		/* physical address 0-3 */
+	PAR1 = 0x04,		/* physical address 4-5 */
+	MAR0 = 0x08,		/* multicast address 0-3 */
+	MAR1 = 0x0C,		/* multicast address 4-7 */
+	FAR0 = 0x10,		/* flow-control address 0-3 */
+	FAR1 = 0x14,		/* flow-control address 4-5 */
+	TCRRCR = 0x18,		/* receive & transmit configuration */
+	BCR = 0x1C,		/* bus command */
+	TXPDR = 0x20,		/* transmit polling demand */
+	RXPDR = 0x24,		/* receive polling demand */
+	RXCWP = 0x28,		/* receive current word pointer */
+	TXLBA = 0x2C,		/* transmit list base address */
+	RXLBA = 0x30,		/* receive list base address */
+	ISR = 0x34,		/* interrupt status */
+	IMR = 0x38,		/* interrupt mask */
+	FTH = 0x3C,		/* flow control high/low threshold */
+	MANAGEMENT = 0x40,	/* bootrom/eeprom and mii management */
+	TALLY = 0x44,		/* tally counters for crc and mpa */
+	TSR = 0x48,		/* tally counter for transmit status */
+	BMCRSR = 0x4c,		/* basic mode control and status */
+	PHYIDENTIFIER = 0x50,	/* phy identifier */
+	ANARANLPAR = 0x54,	/* auto-negotiation advertisement and link
+				   partner ability */
+	ANEROCR = 0x58,		/* auto-negotiation expansion and pci conf. */
+	BPREMRPSR = 0x5c,	/* bypass & receive error mask and phy status */
+};
+
+/* Bits in the interrupt status/enable registers. */
+/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
+enum intr_status_bits {
+	RFCON = 0x00020000,	/* receive flow control xon packet */
+	RFCOFF = 0x00010000,	/* receive flow control xoff packet */
+	LSCStatus = 0x00008000,	/* link status change */
+	ANCStatus = 0x00004000,	/* autonegotiation completed */
+	FBE = 0x00002000,	/* fatal bus error */
+	FBEMask = 0x00001800,	/* mask bit12-11 */
+	ParityErr = 0x00000000,	/* parity error */
+	TargetErr = 0x00001000,	/* target abort */
+	MasterErr = 0x00000800,	/* master error */
+	TUNF = 0x00000400,	/* transmit underflow */
+	ROVF = 0x00000200,	/* receive overflow */
+	ETI = 0x00000100,	/* transmit early int */
+	ERI = 0x00000080,	/* receive early int */
+	CNTOVF = 0x00000040,	/* counter overflow */
+	RBU = 0x00000020,	/* receive buffer unavailable */
+	TBU = 0x00000010,	/* transmit buffer unavilable */
+	TI = 0x00000008,	/* transmit interrupt */
+	RI = 0x00000004,	/* receive interrupt */
+	RxErr = 0x00000002,	/* receive error */
+};
+
+/* Bits in the NetworkConfig register. */
+enum rx_mode_bits {
+	RxModeMask = 0xe0,
+	PROM = 0x80,		/* promiscuous mode */
+	AB = 0x40,		/* accept broadcast */
+	AM = 0x20,		/* accept mutlicast */
+	ARP = 0x08,		/* receive runt pkt */
+	ALP = 0x04,		/* receive long pkt */
+	SEP = 0x02,		/* receive error pkt */
+};
+
+/* The Tulip Rx and Tx buffer descriptors. */
+struct fealnx_desc {
+	s32 status;
+	s32 control;
+	u32 buffer;
+	u32 next_desc;
+	struct fealnx_desc *next_desc_logical;
+	struct sk_buff *skbuff;
+	u32 reserved1;
+	u32 reserved2;
+};
+
+/* Bits in network_desc.status */
+enum rx_desc_status_bits {
+	RXOWN = 0x80000000,	/* own bit */
+	FLNGMASK = 0x0fff0000,	/* frame length */
+	FLNGShift = 16,
+	MARSTATUS = 0x00004000,	/* multicast address received */
+	BARSTATUS = 0x00002000,	/* broadcast address received */
+	PHYSTATUS = 0x00001000,	/* physical address received */
+	RXFSD = 0x00000800,	/* first descriptor */
+	RXLSD = 0x00000400,	/* last descriptor */
+	ErrorSummary = 0x80,	/* error summary */
+	RUNT = 0x40,		/* runt packet received */
+	LONG = 0x20,		/* long packet received */
+	FAE = 0x10,		/* frame align error */
+	CRC = 0x08,		/* crc error */
+	RXER = 0x04,		/* receive error */
+};
+
+enum rx_desc_control_bits {
+	RXIC = 0x00800000,	/* interrupt control */
+	RBSShift = 0,
+};
+
+enum tx_desc_status_bits {
+	TXOWN = 0x80000000,	/* own bit */
+	JABTO = 0x00004000,	/* jabber timeout */
+	CSL = 0x00002000,	/* carrier sense lost */
+	LC = 0x00001000,	/* late collision */
+	EC = 0x00000800,	/* excessive collision */
+	UDF = 0x00000400,	/* fifo underflow */
+	DFR = 0x00000200,	/* deferred */
+	HF = 0x00000100,	/* heartbeat fail */
+	NCRMask = 0x000000ff,	/* collision retry count */
+	NCRShift = 0,
+};
+
+enum tx_desc_control_bits {
+	TXIC = 0x80000000,	/* interrupt control */
+	ETIControl = 0x40000000,	/* early transmit interrupt */
+	TXLD = 0x20000000,	/* last descriptor */
+	TXFD = 0x10000000,	/* first descriptor */
+	CRCEnable = 0x08000000,	/* crc control */
+	PADEnable = 0x04000000,	/* padding control */
+	RetryTxLC = 0x02000000,	/* retry late collision */
+	PKTSMask = 0x3ff800,	/* packet size bit21-11 */
+	PKTSShift = 11,
+	TBSMask = 0x000007ff,	/* transmit buffer bit 10-0 */
+	TBSShift = 0,
+};
+
+/* BootROM/EEPROM/MII Management Register */
+#define MASK_MIIR_MII_READ       0x00000000
+#define MASK_MIIR_MII_WRITE      0x00000008
+#define MASK_MIIR_MII_MDO        0x00000004
+#define MASK_MIIR_MII_MDI        0x00000002
+#define MASK_MIIR_MII_MDC        0x00000001
+
+/* ST+OP+PHYAD+REGAD+TA */
+#define OP_READ             0x6000	/* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
+#define OP_WRITE            0x5002	/* ST:01+OP:01+PHYAD+REGAD+TA:10 */
+
+/* ------------------------------------------------------------------------- */
+/*      Constants for Myson PHY                                              */
+/* ------------------------------------------------------------------------- */
+#define MysonPHYID      0xd0000302
+/* 89-7-27 add, (begin) */
+#define MysonPHYID0     0x0302
+#define StatusRegister  18
+#define SPEED100        0x0400	// bit10
+#define FULLMODE        0x0800	// bit11
+/* 89-7-27 add, (end) */
+
+/* ------------------------------------------------------------------------- */
+/*      Constants for Seeq 80225 PHY                                         */
+/* ------------------------------------------------------------------------- */
+#define SeeqPHYID0      0x0016
+
+#define MIIRegister18   18
+#define SPD_DET_100     0x80
+#define DPLX_DET_FULL   0x40
+
+/* ------------------------------------------------------------------------- */
+/*      Constants for Ahdoc 101 PHY                                          */
+/* ------------------------------------------------------------------------- */
+#define AhdocPHYID0     0x0022
+
+#define DiagnosticReg   18
+#define DPLX_FULL       0x0800
+#define Speed_100       0x0400
+
+/* 89/6/13 add, */
+/* -------------------------------------------------------------------------- */
+/*      Constants                                                             */
+/* -------------------------------------------------------------------------- */
+#define MarvellPHYID0           0x0141
+#define LevelOnePHYID0		0x0013
+
+#define MII1000BaseTControlReg  9
+#define MII1000BaseTStatusReg   10
+#define SpecificReg		17
+
+/* for 1000BaseT Control Register */
+#define PHYAbletoPerform1000FullDuplex  0x0200
+#define PHYAbletoPerform1000HalfDuplex  0x0100
+#define PHY1000AbilityMask              0x300
+
+// for phy specific status register, marvell phy.
+#define SpeedMask       0x0c000
+#define Speed_1000M     0x08000
+#define Speed_100M      0x4000
+#define Speed_10M       0
+#define Full_Duplex     0x2000
+
+// 89/12/29 add, for phy specific status register, levelone phy, (begin)
+#define LXT1000_100M    0x08000
+#define LXT1000_1000M   0x0c000
+#define LXT1000_Full    0x200
+// 89/12/29 add, for phy specific status register, levelone phy, (end)
+
+/* for 3-in-1 case */
+#define PS10            0x00080000
+#define FD              0x00100000
+#define PS1000          0x00010000
+#define LinkIsUp2	0x00040000
+
+/* for PHY */
+#define LinkIsUp        0x0004
+
+
+struct netdev_private {
+	/* Descriptor rings first for alignment. */
+	struct fealnx_desc rx_ring[RX_RING_SIZE];
+	struct fealnx_desc tx_ring[TX_RING_SIZE];
+
+	struct net_device_stats stats;
+
+	/* Media monitoring timer. */
+	struct timer_list timer;
+
+	/* Frequently used values: keep some adjacent for cache effect. */
+	int flags;
+	struct pci_dev *pci_dev;
+	unsigned long crvalue;
+	unsigned long bcrvalue;
+	unsigned long imrvalue;
+	struct fealnx_desc *cur_rx;
+	struct fealnx_desc *lack_rxbuf;
+	int really_rx_count;
+	struct fealnx_desc *cur_tx;
+	struct fealnx_desc *cur_tx_copy;
+	int really_tx_count;
+	int free_tx_count;
+	unsigned int rx_buf_sz;	/* Based on MTU+slack. */
+
+	/* These values are keep track of the transceiver/media in use. */
+	unsigned int linkok;
+	unsigned int line_speed;
+	unsigned int duplexmode;
+	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
+	unsigned int duplex_lock:1;
+	unsigned int medialock:1;	/* Do not sense media. */
+	unsigned int default_port:4;	/* Last dev->if_port value. */
+	unsigned int PHYType;
+
+	/* MII transceiver section. */
+	int mii_cnt;		/* MII device addresses. */
+	unsigned char phys[2];	/* MII device addresses. */
+};
+
+
+static unsigned int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static int netdev_open(struct net_device *dev);
+static void getlinktype(struct net_device *dev);
+static void getlinkstatus(struct net_device *dev);
+static void netdev_timer(unsigned long data);
+static void tx_timeout(struct net_device *dev);
+static void init_ring(struct net_device *dev);
+static int start_tx(struct sk_buff *skb, struct net_device *dev);
+static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static int netdev_rx(struct net_device *dev);
+static inline unsigned ether_crc(int length, unsigned char *data);
+static void set_rx_mode(struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_close(struct net_device *dev);
+
+
+void stop_nic_tx(long ioaddr, long crvalue)
+{
+	writel(crvalue & (~0x40000), ioaddr + TCRRCR);
+
+	/* wait for tx stop */
+	{
+		int i = 0, delay = 0x1000;
+
+		while ((!(readl(ioaddr + TCRRCR) & 0x04000000)) && (i < delay)) {
+			++i;
+		}
+	}
+}
+
+
+void stop_nic_rx(long ioaddr, long crvalue)
+{
+	writel(crvalue & (~0x1), ioaddr + TCRRCR);
+
+	/* wait for rx stop */
+	{
+		int i = 0, delay = 0x1000;
+
+		while ((!(readl(ioaddr + TCRRCR) & 0x00008000)) && (i < delay)) {
+			++i;
+		}
+	}
+}
+
+
+
+static int __devinit fealnx_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	struct netdev_private *np;
+	int i, option, err, irq;
+	static int card_idx = -1;
+	char boardname[12];
+	long ioaddr;
+	unsigned int chip_id = ent->driver_data;
+	struct net_device *dev;
+	
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+	static int printed_version;
+	if (!printed_version++)
+		printk (version);
+#endif
+	
+	card_idx++;
+	sprintf(boardname, "fealnx%d", card_idx);
+	
+	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
+
+	i = pci_enable_device(pdev);
+	if (i) return i;
+	pci_set_master(pdev);
+	
+#ifdef USE_IO_OPS
+	ioaddr = pci_resource_len(pdev, 0);
+#else
+	ioaddr = pci_resource_len(pdev, 1);
+#endif
+	if (ioaddr < MIN_REGION_SIZE) {
+		printk(KERN_ERR "%s: region size %ld too small, aborting\n",
+		       boardname, ioaddr);
+		return -ENODEV;
+	}
+
+	i = pci_request_regions(pdev, boardname);
+	if (i) return i;
+	
+	irq = pdev->irq;
+
+#ifdef USE_IO_OPS
+	ioaddr = pci_resource_start(pdev, 0);
+#else
+	ioaddr = (long) ioremap(pci_resource_start(pdev, 1),
+				pci_resource_len(pdev, 1));
+	if (!ioaddr) {
+		err = -ENOMEM;
+		goto err_out_res;
+	}
+#endif
+	
+	dev = alloc_etherdev(sizeof(struct netdev_private));
+	if (!dev) {
+		err = -ENOMEM;
+		goto err_out_unmap;
+	}
+	SET_MODULE_OWNER(dev);
+
+	/* read ethernet id */
+	for (i = 0; i < 6; ++i)
+		dev->dev_addr[i] = readb(ioaddr + PAR0 + i);
+
+	/* Reset the chip to erase previous misconfiguration. */
+	writel(0x00000001, ioaddr + BCR);
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	/* Make certain the descriptor lists are aligned. */
+	np = dev->priv;
+	np->pci_dev = pdev;
+	np->flags = skel_netdrv_tbl[chip_id].flags;
+	pci_set_drvdata(pdev, dev);
+
+	/* find the connected MII xcvrs */
+	if (np->flags == HAS_MII_XCVR) {
+		int phy, phy_idx = 0;
+
+		for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+			int mii_status = mdio_read(dev, phy, 1);
+
+			if (mii_status != 0xffff && mii_status != 0x0000) {
+				np->phys[phy_idx++] = phy;
+				printk(KERN_INFO
+				       "%s: MII PHY found at address %d, status "
+				       "0x%4.4x.\n", dev->name, phy, mii_status);
+				/* get phy type */
+				{
+					unsigned int data;
+
+					data = mdio_read(dev, np->phys[0], 2);
+					if (data == SeeqPHYID0)
+						np->PHYType = SeeqPHY;
+					else if (data == AhdocPHYID0)
+						np->PHYType = AhdocPHY;
+					else if (data == MarvellPHYID0)
+						np->PHYType = MarvellPHY;
+					else if (data == MysonPHYID0)
+						np->PHYType = Myson981;
+					else if (data == LevelOnePHYID0)
+						np->PHYType = LevelOnePHY;
+					else
+						np->PHYType = OtherPHY;
+				}
+			}
+		}
+
+		np->mii_cnt = phy_idx;
+		if (phy_idx == 0) {
+			printk(KERN_WARNING "%s: MII PHY not found -- this device may "
+			       "not operate correctly.\n", dev->name);
+		}
+	} else {
+		np->phys[0] = 32;
+/* 89/6/23 add, (begin) */
+		/* get phy type */
+		if (readl(dev->base_addr + PHYIDENTIFIER) == MysonPHYID)
+			np->PHYType = MysonPHY;
+		else
+			np->PHYType = OtherPHY;
+	}
+
+	if (dev->mem_start)
+		option = dev->mem_start;
+
+	/* The lower four bits are the media type. */
+	if (option > 0) {
+		if (option & 0x200)
+			np->full_duplex = 1;
+		np->default_port = option & 15;
+
+		if (np->default_port)
+			np->medialock = 1;
+	}
+
+	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+		np->full_duplex = full_duplex[card_idx];
+
+	if (np->full_duplex) {
+		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
+/* 89/6/13 add, (begin) */
+//      if (np->PHYType==MarvellPHY)
+		if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], 9);
+			data = (data & 0xfcff) | 0x0200;
+			mdio_write(dev, np->phys[0], 9, data);
+		}
+/* 89/6/13 add, (end) */
+		if (np->flags == HAS_MII_XCVR)
+			mdio_write(dev, np->phys[0], 4, 0x141);
+		else
+			writel(0x141, dev->base_addr + ANARANLPAR);
+		np->duplex_lock = 1;
+	}
+
+	/* The chip-specific entries in the device structure. */
+	dev->open = &netdev_open;
+	dev->hard_start_xmit = &start_tx;
+	dev->stop = &netdev_close;
+	dev->get_stats = &get_stats;
+	dev->set_multicast_list = &set_rx_mode;
+	dev->do_ioctl = &mii_ioctl;
+	dev->tx_timeout = tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	
+	err = register_netdev(dev);
+	if (err)
+		goto err_out_free;
+
+	printk(KERN_INFO "%s: %s at 0x%lx, ",
+	       dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
+	for (i = 0; i < 5; i++)
+		printk("%2.2x:", dev->dev_addr[i]);
+	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+
+	return 0;
+
+err_out_free:
+	kfree(dev);
+err_out_unmap:
+#ifndef USE_IO_OPS
+	iounmap((void *)ioaddr);
+err_out_res:
+#endif
+	pci_release_regions(pdev);
+	return err;
+}
+
+static void __devexit fealnx_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	if (dev) {
+		unregister_netdev(dev);
+#ifndef USE_IO_OPS
+		iounmap((void *)dev->base_addr);
+#endif
+		kfree(dev);
+		pci_release_regions(pdev);
+		pci_set_drvdata(pdev, NULL);
+	} else
+		printk(KERN_ERR "fealnx: remove for unknown device\n");
+}
+
+unsigned int m80x_read_tick(void)
+/* function: Reads the Timer tick count register which decrements by 2 from  */
+/*           65536 to 0 every 1/36.414 of a second. Each 2 decrements of the *//*           count represents 838 nsec's.                                    */
+/* input   : none.                                                           */
+/* output  : none.                                                           */
+{
+	unsigned char tmp;
+	int value;
+
+	writeb((char) 0x06, 0x43);	// Command 8254 to latch T0's count
+
+	// now read the count.
+	tmp = (unsigned char) readb(0x40);
+	value = ((int) tmp) << 8;
+	tmp = (unsigned char) readb(0x40);
+	value |= (((int) tmp) & 0xff);
+	return (value);
+}
+
+
+void m80x_delay(unsigned int interval)
+/* function: to wait for a specified time.                                   */
+/* input   : interval ... the specified time.                                */
+/* output  : none.                                                           */
+{
+	unsigned int interval1, interval2, i = 0;
+
+	interval1 = m80x_read_tick();	// get initial value
+	do {
+		interval2 = m80x_read_tick();
+		if (interval1 < interval2)
+			interval1 = interval2;
+		++i;
+	} while (((interval1 - interval2) < (ushort) interval) && (i < 65535));
+}
+
+
+static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
+{
+	ulong miir;
+	int i;
+	unsigned int mask, data;
+
+	/* enable MII output */
+	miir = (ulong) readl(miiport);
+	miir &= 0xfffffff0;
+
+	miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
+
+	/* send 32 1's preamble */
+	for (i = 0; i < 32; i++) {
+		/* low MDC; MDO is already high (miir) */
+		miir &= ~MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+
+		/* high MDC */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+	}
+
+	/* calculate ST+OP+PHYAD+REGAD+TA */
+	data = opcode | (phyad << 7) | (regad << 2);
+
+	/* sent out */
+	mask = 0x8000;
+	while (mask) {
+		/* low MDC, prepare MDO */
+		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
+		if (mask & data)
+			miir |= MASK_MIIR_MII_MDO;
+
+		writel(miir, miiport);
+		/* high MDC */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+		m80x_delay(30);
+
+		/* next */
+		mask >>= 1;
+		if (mask == 0x2 && opcode == OP_READ)
+			miir &= ~MASK_MIIR_MII_WRITE;
+	}
+	return miir;
+}
+
+
+static unsigned int mdio_read(struct net_device *dev, int phyad, int regad)
+{
+	long miiport = dev->base_addr + MANAGEMENT;
+	ulong miir;
+	unsigned int mask, data;
+
+	miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
+
+	/* read data */
+	mask = 0x8000;
+	data = 0;
+	while (mask) {
+		/* low MDC */
+		miir &= ~MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+
+		/* read MDI */
+		miir = readl(miiport);
+		if (miir & MASK_MIIR_MII_MDI)
+			data |= mask;
+
+		/* high MDC, and wait */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+		m80x_delay((int) 30);
+
+		/* next */
+		mask >>= 1;
+	}
+
+	/* low MDC */
+	miir &= ~MASK_MIIR_MII_MDC;
+	writel(miir, miiport);
+
+	return data;
+}
+
+
+static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
+{
+	long miiport = dev->base_addr + MANAGEMENT;
+	ulong miir;
+	unsigned int mask;
+
+	miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
+
+	/* write data */
+	mask = 0x8000;
+	while (mask) {
+		/* low MDC, prepare MDO */
+		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
+		if (mask & data)
+			miir |= MASK_MIIR_MII_MDO;
+		writel(miir, miiport);
+
+		/* high MDC */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+
+		/* next */
+		mask >>= 1;
+	}
+
+	/* low MDC */
+	miir &= ~MASK_MIIR_MII_MDC;
+	writel(miir, miiport);
+
+	return;
+}
+
+
+static int netdev_open(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	writel(0x00000001, ioaddr + BCR);	/* Reset */
+
+	if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))
+		return -EAGAIN;
+
+	init_ring(dev);
+
+	writel(virt_to_bus(np->rx_ring), ioaddr + RXLBA);
+	writel(virt_to_bus(np->tx_ring), ioaddr + TXLBA);
+
+	/* Initialize other registers. */
+	/* Configure the PCI bus bursts and FIFO thresholds.
+	   486: Set 8 longword burst.
+	   586: no burst limit.
+	   Burst length 5:3
+	   0 0 0   1
+	   0 0 1   4
+	   0 1 0   8
+	   0 1 1   16
+	   1 0 0   32
+	   1 0 1   64
+	   1 1 0   128
+	   1 1 1   256
+	   Wait the specified 50 PCI cycles after a reset by initializing
+	   Tx and Rx queues and the address filter list. */
+#if defined(__powerpc__)
+// 89/9/1 modify, 
+//   np->bcrvalue=0x04 | 0x0x38;  /* big-endian, 256 burst length */
+	np->bcrvalue = 0x04 | 0x10;	/* big-endian, tx 8 burst length */
+	np->crvalue = 0xe00;	/* rx 128 burst length */
+#elif defined(__alpha__)
+// 89/9/1 modify, 
+//   np->bcrvalue=0x38;           /* little-endian, 256 burst length */
+	np->bcrvalue = 0x10;	/* little-endian, 8 burst length */
+	np->crvalue = 0xe00;	/* rx 128 burst length */
+#elif defined(__i386__)
+#if defined(MODULE)
+// 89/9/1 modify, 
+//   np->bcrvalue=0x38;           /* little-endian, 256 burst length */
+	np->bcrvalue = 0x10;	/* little-endian, 8 burst length */
+	np->crvalue = 0xe00;	/* rx 128 burst length */
+#else
+	/* When not a module we can work around broken '486 PCI boards. */
+#define x86 boot_cpu_data.x86
+// 89/9/1 modify, 
+//   np->bcrvalue=(x86 <= 4 ? 0x10 : 0x38);
+	np->bcrvalue = 0x10;
+	np->crvalue = (x86 <= 4 ? 0xa00 : 0xe00);
+	if (x86 <= 4)
+		printk(KERN_INFO "%s: This is a 386/486 PCI system, setting burst "
+		       "length to %x.\n", dev->name, (x86 <= 4 ? 0x10 : 0x38));
+#endif
+#else
+// 89/9/1 modify,
+//   np->bcrvalue=0x38;
+	np->bcrvalue = 0x10;
+	np->cralue = 0xe00;	/* rx 128 burst length */
+#warning Processor architecture undefined!
+#endif
+// 89/12/29 add,
+// 90/1/16 modify,
+//   np->imrvalue=FBE|TUNF|CNTOVF|RBU|TI|RI;
+	np->imrvalue = TUNF | CNTOVF | RBU | TI | RI;
+	if (np->pci_dev->device == 0x891) {
+		np->bcrvalue |= 0x200;	/* set PROG bit */
+		np->crvalue |= 0x02000000;	/* set enhanced bit */
+		np->imrvalue |= ETI;
+	}
+	writel(np->bcrvalue, ioaddr + BCR);
+
+	if (dev->if_port == 0)
+		dev->if_port = np->default_port;
+
+	writel(0, dev->base_addr + RXPDR);
+// 89/9/1 modify,
+//   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
+	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
+	np->full_duplex = np->duplex_lock;
+	getlinkstatus(dev);
+	if (np->linkok)
+		getlinktype(dev);
+	set_rx_mode(dev);
+
+	netif_start_queue(dev);
+
+	/* Clear and Enable interrupts by setting the interrupt mask. */
+	writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+	writel(np->imrvalue, ioaddr + IMR);
+
+	if (debug)
+		printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);
+
+	/* Set the timer to check for link beat. */
+	init_timer(&np->timer);
+	np->timer.expires = RUN_AT(3 * HZ);
+	np->timer.data = (unsigned long) dev;
+	np->timer.function = &netdev_timer;
+
+	/* timer handler */
+	add_timer(&np->timer);
+
+	return 0;
+}
+
+
+static void getlinkstatus(struct net_device *dev)
+/* function: Routine will read MII Status Register to get link status.       */
+/* input   : dev... pointer to the adapter block.                            */
+/* output  : none.                                                           */
+{
+	struct netdev_private *np = dev->priv;
+	unsigned int i, DelayTime = 0x1000;
+
+	np->linkok = 0;
+
+	if (np->PHYType == MysonPHY) {
+		for (i = 0; i < DelayTime; ++i) {
+			if (readl(dev->base_addr + BMCRSR) & LinkIsUp2) {
+				np->linkok = 1;
+				return;
+			}
+			// delay
+			m80x_delay(100);
+		}
+	} else {
+		for (i = 0; i < DelayTime; ++i) {
+			if (mdio_read(dev, np->phys[0], 1) & 0x4) {
+				np->linkok = 1;
+				return;
+			}
+			// delay
+			m80x_delay(100);
+		}
+	}
+}
+
+
+static void getlinktype(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	if (np->PHYType == MysonPHY) {	/* 3-in-1 case */
+		if (readl(dev->base_addr + TCRRCR) & FD)
+			np->duplexmode = 2;	/* full duplex */
+		else
+			np->duplexmode = 1;	/* half duplex */
+		if (readl(dev->base_addr + TCRRCR) & PS10)
+			np->line_speed = 1;	/* 10M */
+		else
+			np->line_speed = 2;	/* 100M */
+	} else {
+		if (np->PHYType == SeeqPHY) {	/* this PHY is SEEQ 80225 */
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], MIIRegister18);
+			if (data & SPD_DET_100)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+			if (data & DPLX_DET_FULL)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+		} else if (np->PHYType == AhdocPHY) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], DiagnosticReg);
+			if (data & Speed_100)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+			if (data & DPLX_FULL)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+		}
+/* 89/6/13 add, (begin) */
+		else if (np->PHYType == MarvellPHY) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], SpecificReg);
+			if (data & Full_Duplex)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+			data &= SpeedMask;
+			if (data == Speed_1000M)
+				np->line_speed = 3;	/* 1000M */
+			else if (data == Speed_100M)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+		}
+/* 89/6/13 add, (end) */
+/* 89/7/27 add, (begin) */
+		else if (np->PHYType == Myson981) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], StatusRegister);
+
+			if (data & SPEED100)
+				np->line_speed = 2;
+			else
+				np->line_speed = 1;
+
+			if (data & FULLMODE)
+				np->duplexmode = 2;
+			else
+				np->duplexmode = 1;
+		}
+/* 89/7/27 add, (end) */
+/* 89/12/29 add */
+		else if (np->PHYType == LevelOnePHY) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], SpecificReg);
+			if (data & LXT1000_Full)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+			data &= SpeedMask;
+			if (data == LXT1000_1000M)
+				np->line_speed = 3;	/* 1000M */
+			else if (data == LXT1000_100M)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+		}
+		// chage crvalue
+		// np->crvalue&=(~PS10)&(~FD);
+		np->crvalue &= (~PS10) & (~FD) & (~PS1000);
+		if (np->line_speed == 1)
+			np->crvalue |= PS10;
+		else if (np->line_speed == 3)
+			np->crvalue |= PS1000;
+		if (np->duplexmode == 2)
+			np->crvalue |= FD;
+	}
+}
+
+
+static void allocate_rx_buffers(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	/*  allocate skb for rx buffers */
+	while (np->really_rx_count != RX_RING_SIZE) {
+		struct sk_buff *skb;
+
+		skb = dev_alloc_skb(np->rx_buf_sz);
+		np->lack_rxbuf->skbuff = skb;
+
+		if (skb == NULL)
+			break;	/* Better luck next round. */
+
+		skb->dev = dev;	/* Mark as being used by this device. */
+		np->lack_rxbuf->buffer = virt_to_bus(skb->tail);
+		np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+		++np->really_rx_count;
+	}
+}
+
+
+static void netdev_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	int next_tick = 10 * HZ;
+	int old_crvalue = np->crvalue;
+	unsigned int old_linkok = np->linkok;
+
+	if (debug)
+		printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "
+		       "config %8.8x.\n", dev->name, readl(ioaddr + ISR),
+		       readl(ioaddr + TCRRCR));
+
+	if (np->flags == HAS_MII_XCVR) {
+		getlinkstatus(dev);
+		if ((old_linkok == 0) && (np->linkok == 1)) {	/* we need to detect the media type again */
+			getlinktype(dev);
+			if (np->crvalue != old_crvalue) {
+				stop_nic_tx(ioaddr, np->crvalue);
+				stop_nic_rx(ioaddr, np->crvalue & (~0x40000));
+				writel(np->crvalue, ioaddr + TCRRCR);
+			}
+		}
+	}
+
+	allocate_rx_buffers(dev);
+
+	np->timer.expires = RUN_AT(next_tick);
+	add_timer(&np->timer);
+}
+
+
+static void tx_timeout(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
+	       " resetting...\n", dev->name, readl(ioaddr + ISR));
+
+#ifndef __alpha__
+	{
+		int i;
+
+		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int) np->rx_ring);
+		for (i = 0; i < RX_RING_SIZE; i++)
+			printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
+		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int) np->tx_ring);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk(" %4.4x", np->tx_ring[i].status);
+		printk("\n");
+	}
+#endif
+
+	/* Perhaps we should reinitialize the hardware here.  Just trigger a
+	   Tx demand for now. */
+	writel(0, dev->base_addr + TXPDR);
+	dev->if_port = 0;
+
+	/* Stop and restart the chip's Tx processes . */
+	dev->trans_start = jiffies;
+	np->stats.tx_errors++;
+
+	return;
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void init_ring(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	int i;
+
+	/* initialize rx variables */
+	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+	np->cur_rx = &np->rx_ring[0];
+	np->lack_rxbuf = NULL;
+	np->really_rx_count = 0;
+
+	/* initial rx descriptors. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].status = 0;
+		np->rx_ring[i].control = np->rx_buf_sz << RBSShift;
+		np->rx_ring[i].next_desc = virt_to_bus(&np->rx_ring[i + 1]);
+		np->rx_ring[i].next_desc_logical = &np->rx_ring[i + 1];
+		np->rx_ring[i].skbuff = NULL;
+	}
+
+	/* for the last rx descriptor */
+	np->rx_ring[i - 1].next_desc = virt_to_bus(&np->rx_ring[0]);
+	np->rx_ring[i - 1].next_desc_logical = &np->rx_ring[0];
+
+	/* allocate skb for rx buffers */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+
+		if (skb == NULL) {
+			np->lack_rxbuf = &np->rx_ring[i];
+			break;
+		}
+
+		++np->really_rx_count;
+		np->rx_ring[i].skbuff = skb;
+		skb->dev = dev;	/* Mark as being used by this device. */
+		np->rx_ring[i].buffer = virt_to_bus(skb->tail);
+		np->rx_ring[i].status = RXOWN;
+		np->rx_ring[i].control |= RXIC;
+	}
+
+	/* initialize tx variables */
+	np->cur_tx = &np->tx_ring[0];
+	np->cur_tx_copy = &np->tx_ring[0];
+	np->really_tx_count = 0;
+	np->free_tx_count = TX_RING_SIZE;
+
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		np->tx_ring[i].status = 0;
+		np->tx_ring[i].next_desc = virt_to_bus(&np->tx_ring[i + 1]);
+		np->tx_ring[i].next_desc_logical = &np->tx_ring[i + 1];
+		np->tx_ring[i].skbuff = NULL;
+	}
+
+	/* for the last tx descriptor */
+	np->tx_ring[i - 1].next_desc = virt_to_bus(&np->tx_ring[0]);
+	np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0];
+
+	return;
+}
+
+
+static int start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	np->cur_tx_copy->skbuff = skb;
+	np->cur_tx_copy->buffer = virt_to_bus(skb->data);
+
+#define one_buffer
+#define BPT 1022
+#if defined(one_buffer)
+	np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable;
+	np->cur_tx_copy->control |= (skb->len << PKTSShift);	/* pkt size */
+	np->cur_tx_copy->control |= (skb->len << TBSShift);	/* buffer size */
+// 89/12/29 add,
+	if (np->pci_dev->device == 0x891)
+		np->cur_tx_copy->control |= ETIControl | RetryTxLC;
+	np->cur_tx_copy->status = TXOWN;
+	np->cur_tx_copy = np->cur_tx_copy->next_desc_logical;
+	--np->free_tx_count;
+#elif defined(two_buffer)
+	if (skb->len > BPT) {
+		struct fealnx_desc *next;
+
+		/* for the first descriptor */
+		np->cur_tx_copy->control = TXIC | TXFD | CRCEnable | PADEnable;
+		np->cur_tx_copy->control |= (skb->len << PKTSShift);	/* pkt size */
+		np->cur_tx_copy->control |= (BPT << TBSShift);	/* buffer size */
+
+		/* for the last descriptor */
+		next = (struct fealnx *) np->cur_tx_copy.next_desc_logical;
+		next->skbuff = skb;
+		next->control = TXIC | TXLD | CRCEnable | PADEnable;
+		next->control |= (skb->len << PKTSShift);	/* pkt size */
+		next->control |= ((skb->len - BPT) << TBSShift);	/* buf size */
+// 89/12/29 add,
+		if (np->pci_dev->device == 0x891)
+			np->cur_tx_copy->control |= ETIControl | RetryTxLC;
+		next->buffer = virt_to_bus(skb->data) + BPT;
+
+		next->status = TXOWN;
+		np->cur_tx_copy->status = TXOWN;
+
+		np->cur_tx_copy = next->next_desc_logical;
+		np->free_tx_count -= 2;
+	} else {
+		np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable;
+		np->cur_tx_copy->control |= (skb->len << PKTSShift);	/* pkt size */
+		np->cur_tx_copy->control |= (skb->len << TBSShift);	/* buffer size */
+// 89/12/29 add,
+		if (np->pci_dev->device == 0x891)
+			np->cur_tx_copy->control |= ETIControl | RetryTxLC;
+		np->cur_tx_copy->status = TXOWN;
+		np->cur_tx_copy = np->cur_tx_copy->next_desc_logical;
+		--np->free_tx_count;
+	}
+#endif
+
+	if (np->free_tx_count < 2)
+		netif_stop_queue(dev);
+	++np->really_tx_count;
+	writel(0, dev->base_addr + TXPDR);
+	dev->trans_start = jiffies;
+
+	return 0;
+}
+
+
+void free_one_rx_descriptor(struct netdev_private *np)
+{
+	if (np->really_rx_count == RX_RING_SIZE)
+		np->cur_rx->status = RXOWN;
+	else {
+		np->lack_rxbuf->skbuff = np->cur_rx->skbuff;
+		np->lack_rxbuf->buffer = np->cur_rx->buffer;
+		np->lack_rxbuf->status = RXOWN;
+		++np->really_rx_count;
+		np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+	}
+	np->cur_rx = np->cur_rx->next_desc_logical;
+}
+
+
+void reset_rx_descriptors(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	stop_nic_rx(dev->base_addr, np->crvalue);
+
+	while (!(np->cur_rx->status & RXOWN))
+		free_one_rx_descriptor(np);
+
+	allocate_rx_buffers(dev);
+
+	writel(virt_to_bus(np->cur_rx), dev->base_addr + RXLBA);
+	writel(np->crvalue, dev->base_addr + TCRRCR);
+}
+
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+{
+	struct net_device *dev = (struct net_device *) dev_instance;
+	struct netdev_private *np = dev->priv;
+	long ioaddr, boguscnt = max_interrupt_work;
+	unsigned int num_tx = 0;
+
+	writel(0, dev->base_addr + IMR);
+
+	ioaddr = dev->base_addr;
+	np = (struct netdev_private *) dev->priv;
+
+	do {
+		u32 intr_status = readl(ioaddr + ISR);
+
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		writel(intr_status, ioaddr + ISR);
+
+		if (debug)
+			printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name,
+			       intr_status);
+
+		if (!(intr_status & np->imrvalue))
+			break;
+
+// 90/1/16 delete,
+//
+//      if (intr_status & FBE)
+//      {   /* fatal error */
+//          stop_nic_tx(ioaddr, 0);
+//          stop_nic_rx(ioaddr, 0);
+//          break;
+//      };
+
+		if (intr_status & TUNF)
+			writel(0, ioaddr + TXPDR);
+
+		if (intr_status & CNTOVF) {
+			/* missed pkts */
+			np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+
+			/* crc error */
+			np->stats.rx_crc_errors +=
+			    (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+		}
+
+		if (intr_status & (RI | RBU)) {
+			if (intr_status & RI)
+				netdev_rx(dev);
+			else
+				reset_rx_descriptors(dev);
+		}
+
+		while (np->really_tx_count) {
+			long tx_status = np->cur_tx->status;
+			long tx_control = np->cur_tx->control;
+
+			if (!(tx_control & TXLD)) {	/* this pkt is combined by two tx descriptors */
+				struct fealnx_desc *next;
+
+				next = np->cur_tx->next_desc_logical;
+				tx_status = next->status;
+				tx_control = next->control;
+			}
+
+			if (tx_status & TXOWN)
+				break;
+
+			if (!(np->crvalue & 0x02000000)) {
+				if (tx_status & (CSL | LC | EC | UDF | HF)) {
+					np->stats.tx_errors++;
+					if (tx_status & EC)
+						np->stats.tx_aborted_errors++;
+					if (tx_status & CSL)
+						np->stats.tx_carrier_errors++;
+					if (tx_status & LC)
+						np->stats.tx_window_errors++;
+					if (tx_status & UDF)
+						np->stats.tx_fifo_errors++;
+					if ((tx_status & HF) && np->full_duplex == 0)
+						np->stats.tx_heartbeat_errors++;
+
+#ifdef ETHER_STATS
+					if (tx_status & EC)
+						np->stats.collisions16++;
+#endif
+				} else {
+#ifdef ETHER_STATS
+					if (tx_status & DFR)
+						np->stats.tx_deferred++;
+#endif
+
+					np->stats.tx_bytes +=
+					    ((tx_control & PKTSMask) >> PKTSShift);
+
+					np->stats.collisions +=
+					    ((tx_status & NCRMask) >> NCRShift);
+					np->stats.tx_packets++;
+				}
+			} else {
+				np->stats.tx_bytes +=
+				    ((tx_control & PKTSMask) >> PKTSShift);
+				np->stats.tx_packets++;
+			}
+
+			/* Free the original skb. */
+			dev_kfree_skb_irq(np->cur_tx->skbuff);
+			np->cur_tx->skbuff = NULL;
+			--np->really_tx_count;
+			if (np->cur_tx->control & TXLD) {
+				np->cur_tx = np->cur_tx->next_desc_logical;
+				++np->free_tx_count;
+			} else {
+				np->cur_tx = np->cur_tx->next_desc_logical;
+				np->cur_tx = np->cur_tx->next_desc_logical;
+				np->free_tx_count += 2;
+			}
+			num_tx++;
+		}		/* end of for loop */
+		
+		if (num_tx && np->free_tx_count >= 2)
+			netif_wake_queue(dev);
+
+		/* read transmit status for enhanced mode only */
+		if (np->crvalue & 0x02000000) {
+			long data;
+
+			data = readl(ioaddr + TSR);
+			np->stats.tx_errors += (data & 0xff000000) >> 24;
+			np->stats.tx_aborted_errors += (data & 0xff000000) >> 24;
+			np->stats.tx_window_errors += (data & 0x00ff0000) >> 16;
+#ifdef ETHER_STATS
+			np->stats.collisions16 += (data & 0xff000000) >> 24;
+#endif
+			np->stats.collisions += (data & 0x0000ffff);
+		}
+
+		if (--boguscnt < 0) {
+			printk(KERN_WARNING "%s: Too much work at interrupt, "
+			       "status=0x%4.4x.\n", dev->name, intr_status);
+			break;
+		}
+	} while (1);
+
+	/* read the tally counters */
+	/* missed pkts */
+	np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+
+	/* crc error */
+	np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+
+	if (debug)
+		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
+		       dev->name, readl(ioaddr + ISR));
+
+	writel(np->imrvalue, ioaddr + IMR);
+
+	return;
+}
+
+
+/* This routine is logically part of the interrupt handler, but seperated
+   for clarity and better register allocation. */
+static int netdev_rx(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	/* If EOP is set on the next entry, it's a new packet. Send it up. */
+	while (!(np->cur_rx->status & RXOWN)) {
+		s32 rx_status = np->cur_rx->status;
+
+		if (np->really_rx_count == 0)
+			break;
+
+		if (debug)
+			printk(KERN_DEBUG "  netdev_rx() status was %8.8x.\n", rx_status);
+
+		if ((!((rx_status & RXFSD) && (rx_status & RXLSD)))
+		    || (rx_status & ErrorSummary)) {
+			if (rx_status & ErrorSummary) {	/* there was a fatal error */
+				if (debug)
+					printk(KERN_DEBUG
+					       "%s: Receive error, Rx status %8.8x.\n",
+					       dev->name, rx_status);
+
+				np->stats.rx_errors++;	/* end of a packet. */
+				if (rx_status & (LONG | RUNT))
+					np->stats.rx_length_errors++;
+				if (rx_status & RXER)
+					np->stats.rx_frame_errors++;
+				if (rx_status & CRC)
+					np->stats.rx_crc_errors++;
+			} else {
+				int need_to_reset = 0;
+				int desno = 0;
+
+				if (rx_status & RXFSD) {	/* this pkt is too long, over one rx buffer */
+					struct fealnx_desc *cur;
+
+					/* check this packet is received completely? */
+					cur = np->cur_rx;
+					while (desno <= np->really_rx_count) {
+						++desno;
+						if ((!(cur->status & RXOWN))
+						    && (cur->status & RXLSD))
+							break;
+						/* goto next rx descriptor */
+						cur = cur->next_desc_logical;
+					}
+					if (desno > np->really_rx_count)
+						need_to_reset = 1;
+				} else	/* RXLSD did not find, something error */
+					need_to_reset = 1;
+
+				if (need_to_reset == 0) {
+					int i;
+
+					np->stats.rx_length_errors++;
+
+					/* free all rx descriptors related this long pkt */
+					for (i = 0; i < desno; ++i)
+						free_one_rx_descriptor(np);
+					continue;
+				} else {	/* something error, need to reset this chip */
+					reset_rx_descriptors(dev);
+				}
+				break;	/* exit the while loop */
+			}
+		} else {	/* this received pkt is ok */
+
+			struct sk_buff *skb;
+			/* Omit the four octet CRC from the length. */
+			short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
+
+#ifndef final_version
+			if (debug)
+				printk(KERN_DEBUG "  netdev_rx() normal Rx pkt length %d"
+				       " status %x.\n", pkt_len, rx_status);
+#endif
+
+			/* Check if the packet is long enough to accept without copying
+			   to a minimally-sized skbuff. */
+			if (pkt_len < rx_copybreak &&
+			    (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+				/* Call copy + cksum if available. */
+
+#if ! defined(__alpha__)
+				eth_copy_and_sum(skb, bus_to_virt(np->cur_rx->buffer),
+						 pkt_len, 0);
+				skb_put(skb, pkt_len);
+#else
+				memcpy(skb_put(skb, pkt_len),
+				       bus_to_virt(np->cur_rx->buffer), pkt_len);
+#endif
+			} else {
+				skb_put(skb = np->cur_rx->skbuff, pkt_len);
+				np->cur_rx->skbuff = NULL;
+				if (np->really_rx_count == RX_RING_SIZE)
+					np->lack_rxbuf = np->cur_rx;
+				--np->really_rx_count;
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->last_rx = jiffies;
+			np->stats.rx_packets++;
+			np->stats.rx_bytes += pkt_len;
+		}
+
+		if (np->cur_rx->skbuff == NULL) {
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(np->rx_buf_sz);
+
+			if (skb != NULL) {
+				skb->dev = dev;	/* Mark as being used by this device. */
+				np->cur_rx->buffer = virt_to_bus(skb->tail);
+				np->cur_rx->skbuff = skb;
+				++np->really_rx_count;
+			}
+		}
+
+		if (np->cur_rx->skbuff != NULL)
+			free_one_rx_descriptor(np);
+	}			/* end of while loop */
+
+	/*  allocate skb for rx buffers */
+	allocate_rx_buffers(dev);
+
+	return 0;
+}
+
+
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+
+	/* The chip only need report frame silently dropped. */
+	if (netif_running(dev)) {
+		np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+		np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+	}
+
+	return &np->stats;
+}
+
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+	int crc = -1;
+
+	while (--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
+			crc = (crc << 1) ^
+			    ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+		}
+	}
+
+	return crc;
+}
+
+
+static void set_rx_mode(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	u32 mc_filter[2];	/* Multicast hash filter */
+	u32 rx_mode;
+
+	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
+		/* Unconditionally log net taps. */
+		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
+		memset(mc_filter, 0xff, sizeof(mc_filter));
+		rx_mode = PROM | AB | AM;
+	} else if ((dev->mc_count > multicast_filter_limit)
+		   || (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to match, or accept all multicasts. */
+		memset(mc_filter, 0xff, sizeof(mc_filter));
+		rx_mode = AB | AM;
+	} else {
+		struct dev_mc_list *mclist;
+		int i;
+
+		memset(mc_filter, 0, sizeof(mc_filter));
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+		     i++, mclist = mclist->next) {
+			set_bit((ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F,
+				mc_filter);
+		}
+		rx_mode = AB | AM;
+	}
+
+	stop_nic_tx(ioaddr, np->crvalue);
+	stop_nic_rx(ioaddr, np->crvalue & (~0x40000));
+
+	writel(mc_filter[0], ioaddr + MAR0);
+	writel(mc_filter[1], ioaddr + MAR1);
+	np->crvalue &= ~RxModeMask;
+	np->crvalue |= rx_mode;
+	writel(np->crvalue, ioaddr + TCRRCR);
+}
+
+
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	u16 *data = (u16 *) & rq->ifr_data;
+
+	switch (cmd) {
+	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
+		data[0] = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
+		/* Fall Through */
+	case SIOCDEVPRIVATE + 1:	/* Read the specified MII register. */
+		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+		return 0;
+	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+		if (!suser())
+			return -EPERM;
+		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int netdev_close(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+	int i;
+
+	netif_stop_queue(dev);
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	writel(0x0000, ioaddr + IMR);
+
+	/* Stop the chip's Tx and Rx processes. */
+	stop_nic_tx(ioaddr, 0);
+	stop_nic_rx(ioaddr, 0);
+
+	del_timer_sync(&np->timer);
+
+	free_irq(dev->irq, dev);
+
+	/* Free all the skbuffs in the Rx queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].status = 0;
+		if (np->rx_ring[i].skbuff)
+			dev_kfree_skb(np->rx_ring[i].skbuff);
+		np->rx_ring[i].skbuff = NULL;
+	}
+
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (np->tx_ring[i].skbuff)
+			dev_kfree_skb(np->tx_ring[i].skbuff);
+		np->tx_ring[i].skbuff = NULL;
+	}
+
+	return 0;
+}
+
+static struct pci_device_id fealnx_pci_tbl[] = __devinitdata {
+	{0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+	{} /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, fealnx_pci_tbl);
+
+
+static struct pci_driver fealnx_driver = {
+	name:		"fealnx",
+	id_table:	fealnx_pci_tbl,
+	probe:		fealnx_init_one,
+	remove:		fealnx_remove_one,
+};
+
+static int __init fealnx_init(void)
+{
+/* when a module, this is printed whether or not devices are found in probe */
+#ifdef MODULE
+	printk (version);
+#endif
+
+	return pci_module_init(&fealnx_driver);
+}
+
+static void __exit fealnx_exit(void)
+{
+	pci_unregister_driver(&fealnx_driver);
+}
+
+module_init(fealnx_init);
+module_exit(fealnx_exit);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/gmac.c linux/drivers/net/gmac.c
--- v2.4.4/linux/drivers/net/gmac.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/gmac.c	Wed May 16 09:58:36 2001
@@ -9,7 +9,7 @@
  * Changes:
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000
  * - check init_etherdev return in gmac_probe1
- * BenH <bh40@calva.net> - 03/09/2000
+ * BenH <benh@kernel.crashing.org> - 03/09/2000
  * - Add support for new PHYs
  * - Add some PowerBook sleep code
  * 
@@ -47,10 +47,11 @@
 #define DEBUG_PHY
 
 /* Driver version 1.3, kernel 2.4.x */
-#define GMAC_VERSION	"v1.3k4"
+#define GMAC_VERSION	"v1.4k4"
 
-static unsigned char dummy_buf[RX_BUF_ALLOC_SIZE + RX_OFFSET + GMAC_BUFFER_ALIGN];
-static struct net_device *gmacs = NULL;
+#define DUMMY_BUF_LEN	RX_BUF_ALLOC_SIZE + RX_OFFSET + GMAC_BUFFER_ALIGN
+static unsigned char *dummy_buf;
+static struct net_device *gmacs;
 
 /* Prototypes */
 static int mii_read(struct gmac *gm, int phy, int r);
@@ -62,6 +63,7 @@
 static void mii_setup_phy(struct gmac *gm);
 static int mii_do_reset_phy(struct gmac *gm, int phy_addr);
 static void mii_init_BCM5400(struct gmac *gm);
+static void mii_init_BCM5401(struct gmac *gm);
 
 static void gmac_set_power(struct gmac *gm, int power_up);
 static int gmac_powerup_and_reset(struct net_device *dev);
@@ -211,10 +213,12 @@
 		int		link_100 = 0;
 		int		gigabit = 0;
 #ifdef DEBUG_PHY
-		printk("Link state change, phy_status: 0x%04x\n", phy_status);
+		printk("%s: Link state change, phy_status: 0x%04x\n",
+			gm->dev->name, phy_status);
 #endif
 		gm->phy_status = phy_status;
 
+		/* Should we enable that in generic mode ? */
 		lpar_ability = mii_read(gm, gm->phy_addr, MII_ANLPA);
 		if (lpar_ability & MII_ANLPA_PAUS)
 			GM_BIS(GM_MAC_CTRL_CONFIG, GM_MAC_CTRL_CONF_SND_PAUSE_EN);
@@ -249,6 +253,9 @@
 #endif
 		    	full_duplex = ((stat2 & MII_LXT971_STATUS2_FULLDUPLEX) != 0);
 		    	link_100 = ((stat2 & MII_LXT971_STATUS2_SPEED) != 0);
+		    } else {
+		    	full_duplex = (lpar_ability & MII_ANLPA_FDAM) != 0;
+		    	link_100 = (lpar_ability & MII_ANLPA_100M) != 0;
 		    }
 #ifdef DEBUG_PHY
 		    printk("    full_duplex: %d, speed: %s\n", full_duplex,
@@ -274,6 +281,144 @@
 	}
 }
 
+/* Power management: stop PHY chip for suspend mode
+ */
+static void
+gmac_suspend(struct gmac* gm)
+{
+	int data, timeout;
+	unsigned long flags;
+	
+	gm->sleeping = 1;
+	netif_stop_queue(gm->dev);
+
+
+	spin_lock_irqsave(&gm->lock, flags);
+	if (gm->opened) {
+		disable_irq(gm->dev->irq);
+		/* Stop polling PHY */
+		mii_poll_stop(gm);
+	}
+	/* Mask out all chips interrupts */
+	GM_OUT(GM_IRQ_MASK, 0xffffffff);
+	spin_unlock_irqrestore(&gm->lock, flags);
+	
+	if (gm->opened) {
+		int i;
+		/* Empty Tx ring of any remaining gremlins */
+		gmac_tx_cleanup(gm->dev, 1);
+	
+		/* Empty Rx ring of any remaining gremlins */
+		for (i = 0; i < NRX; ++i) {
+			if (gm->rx_buff[i] != 0) {
+				dev_kfree_skb_irq(gm->rx_buff[i]);
+				gm->rx_buff[i] = 0;
+			}
+		}
+	}
+
+	/* Clear interrupts on 5201 */
+	if (gm->phy_type == PHY_B5201)
+		mii_write(gm, gm->phy_addr, MII_BCM5201_INTERRUPT, 0);
+		
+	/* Drive MDIO high */
+	GM_OUT(GM_MIF_CFG, 0);
+	
+	/* Unchanged, don't ask me why */
+	data = mii_read(gm, gm->phy_addr, MII_ANLPA);
+	mii_write(gm, gm->phy_addr, MII_ANLPA, data);
+	
+	/* Put MDIO in sane state */
+	GM_OUT(GM_MIF_CFG, GM_MIF_CFGBB);
+	GM_OUT(GM_MIF_BB_CLOCK, 0);
+	GM_OUT(GM_MIF_BB_DATA, 0);
+	GM_OUT(GM_MIF_BB_OUT_ENABLE, 0);
+	
+	/* Stop everything */
+	GM_OUT(GM_MAC_RX_CONFIG, 0);
+	GM_OUT(GM_MAC_TX_CONFIG, 0);
+	GM_OUT(GM_MAC_XIF_CONFIG, 0);
+	GM_OUT(GM_TX_CONF, 0);
+	GM_OUT(GM_RX_CONF, 0);
+	
+	/* Set reset state */
+	GM_OUT(GM_RESET, GM_RESET_TX | GM_RESET_RX);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mdelay(10);
+		if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0)
+			break;
+	}
+	GM_OUT(GM_MAC_TX_RESET, GM_MAC_TX_RESET_NOW);
+	GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW);
+
+	/* Superisolate PHY */
+	if (gm->phy_type == PHY_B5201)
+		mii_write(gm, gm->phy_addr, MII_BCM5201_MULTIPHY,
+			MII_BCM5201_MULTIPHY_SUPERISOLATE);
+
+	/* Unclock chip */
+	gmac_set_power(gm, 0);
+}
+
+static void
+gmac_resume(struct gmac *gm)
+{
+	int data;
+
+	if (gmac_powerup_and_reset(gm->dev)) {
+		printk(KERN_ERR "%s: Couldn't revive gmac ethernet !\n", gm->dev->name);
+		return;
+	}
+
+	gm->sleeping = 0;
+	
+	if (gm->opened) {
+		/* Create fresh rings */
+		gmac_init_rings(gm, 1);
+		/* re-initialize the MAC */
+		gmac_mac_init(gm, gm->dev->dev_addr);	
+		/* re-initialize the multicast tables & promisc mode if any */
+		gmac_set_multicast(gm->dev);
+	}
+
+	/* Early enable Tx and Rx so that we are clocked */
+	GM_BIS(GM_TX_CONF, GM_TX_CONF_DMA_EN);
+	mdelay(20);
+	GM_BIS(GM_RX_CONF, GM_RX_CONF_DMA_EN);
+	mdelay(20);
+	GM_BIS(GM_MAC_TX_CONFIG, GM_MAC_TX_CONF_ENABLE);
+	mdelay(20);
+	GM_BIS(GM_MAC_RX_CONFIG, GM_MAC_RX_CONF_ENABLE);
+	mdelay(20);
+	if (gm->phy_type == PHY_B5201) {
+		data = mii_read(gm, gm->phy_addr, MII_BCM5201_MULTIPHY);
+		mii_write(gm, gm->phy_addr, MII_BCM5201_MULTIPHY,
+			data & ~MII_BCM5201_MULTIPHY_SUPERISOLATE);
+	}
+	mdelay(1);
+
+	if (gm->opened) {
+		/* restart polling PHY */
+		mii_interrupt(gm);
+		/* restart DMA operations */
+		gmac_start_dma(gm);
+		netif_start_queue(gm->dev);
+		enable_irq(gm->dev->irq);
+	} else {
+		/* Driver not opened, just leave things off. Note that
+		 * we could be smart and superisolate the PHY when the
+		 * driver is closed, but I won't do that unless I have
+		 * a better understanding of some electrical issues with
+		 * this PHY chip --BenH
+		 */
+		GM_OUT(GM_MAC_RX_CONFIG, 0);
+		GM_OUT(GM_MAC_TX_CONFIG, 0);
+		GM_OUT(GM_MAC_XIF_CONFIG, 0);
+		GM_OUT(GM_TX_CONF, 0);
+		GM_OUT(GM_RX_CONF, 0);
+	}
+}
+
 static int
 mii_do_reset_phy(struct gmac *gm, int phy_addr)
 {
@@ -326,6 +471,40 @@
 	mii_write(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL, data);
 }
 
+static void
+mii_init_BCM5401(struct gmac *gm)
+{
+	int data;
+	int rev;
+
+	rev = mii_read(gm, gm->phy_addr, MII_ID1) & 0x000f;
+	if (rev == 0 || rev == 3) {
+		/* A bit of black magic from Apple */
+		mii_write(gm, gm->phy_addr, 0x18, 0x0c20);
+		mii_write(gm, gm->phy_addr, 0x17, 0x0012);
+		mii_write(gm, gm->phy_addr, 0x15, 0x1804);
+		mii_write(gm, gm->phy_addr, 0x17, 0x0013);
+		mii_write(gm, gm->phy_addr, 0x15, 0x1204);
+		mii_write(gm, gm->phy_addr, 0x17, 0x8006);
+		mii_write(gm, gm->phy_addr, 0x15, 0x0132);
+		mii_write(gm, gm->phy_addr, 0x17, 0x8006);
+		mii_write(gm, gm->phy_addr, 0x15, 0x0232);
+		mii_write(gm, gm->phy_addr, 0x17, 0x201f);
+		mii_write(gm, gm->phy_addr, 0x15, 0x0a20);
+	}
+	
+	data = mii_read(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	mii_write(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL, data);
+
+	mdelay(10);
+	mii_do_reset_phy(gm, 0x1f);
+	
+	data = mii_read(gm, 0x1f, MII_BCM5201_MULTIPHY);
+	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+	mii_write(gm, 0x1f, MII_BCM5201_MULTIPHY, data);
+}
+
 static int
 mii_lookup_and_reset(struct gmac *gm)
 {
@@ -335,10 +514,7 @@
 	gm->phy_type = PHY_UNKNOWN;
 
 	/* Hard reset the PHY */
-	feature_set_gmac_phy_reset(gm->of_node, KL_GPIO_ETH_PHY_RESET_ASSERT);
-	mdelay(10);
-	feature_set_gmac_phy_reset(gm->of_node, KL_GPIO_ETH_PHY_RESET_RELEASE);
-	mdelay(10);
+	feature_gmac_phy_reset(gm->of_node);
 	
 	/* Find the PHY */
 	for(i=0; i<=31; i++) {
@@ -367,14 +543,22 @@
 		printk(KERN_ERR "%s Found Broadcom BCM5400 PHY (Gigabit)\n",
 			gm->dev->name);
 		mii_init_BCM5400(gm);		
+	} else if ((gm->phy_id & MII_BCM5401_MASK) == MII_BCM5401_ID) {
+		gm->phy_type = PHY_B5401;
+		printk(KERN_ERR "%s Found Broadcom BCM5401 PHY (Gigabit)\n",
+			gm->dev->name);
+		mii_init_BCM5401(gm);		
 	} else if ((gm->phy_id & MII_BCM5201_MASK) == MII_BCM5201_ID) {
 		gm->phy_type = PHY_B5201;
 		printk(KERN_INFO "%s Found Broadcom BCM5201 PHY\n", gm->dev->name);
+	} else if ((gm->phy_id & MII_BCM5221_MASK) == MII_BCM5221_ID) {
+		gm->phy_type = PHY_B5201; /* Same as 5201 for now */
+		printk(KERN_INFO "%s Found Broadcom BCM5221 PHY\n", gm->dev->name);
 	} else if ((gm->phy_id & MII_LXT971_MASK) == MII_LXT971_ID) {
 		gm->phy_type = PHY_LXT971;
 		printk(KERN_INFO "%s Found LevelOne LX971 PHY\n", gm->dev->name);
 	} else {
-		printk(KERN_ERR "%s: Warning ! Unknown PHY ID 0x%08x !\n",
+		printk(KERN_ERR "%s: Warning ! Unknown PHY ID 0x%08x, using generic mode...\n",
 			gm->dev->name, gm->phy_id);
 	}
 
@@ -448,8 +632,6 @@
 	    			PCI_CACHE_LINE_SIZE, 8);
 		}
 	} else {
-		/* FIXME: Add PHY power down */
-		gm->phy_type = 0;
 		feature_set_gmac_power(gm->of_node, 0);
 	}
 }
@@ -472,11 +654,14 @@
 		if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0) {
 			/* Mask out all chips interrupts */
 			GM_OUT(GM_IRQ_MASK, 0xffffffff);
+			GM_OUT(GM_MAC_TX_RESET, GM_MAC_TX_RESET_NOW);
+			GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW);
 			return 0;
 		}
 	}
 	printk(KERN_ERR "%s reset failed!\n", dev->name);
 	gmac_set_power(gm, 0);
+	gm->phy_type = 0;
 	return -1;
 }
 
@@ -747,7 +932,9 @@
 	int multicast_hash = 0;
 	int multicast_all = 0;
 	int promisc = 0;
-	
+
+	if (gm->sleeping)
+		return;
 
 	/* Lock out others. */
 	netif_stop_queue(dev);
@@ -881,6 +1068,7 @@
 	
 	/* Shut down chip */
 	gmac_set_power(gm, 0);
+	gm->phy_type = 0;
 
 	/* Empty rings of any remaining gremlins */
 	for (i = 0; i < NRX; ++i) {
@@ -904,7 +1092,6 @@
 gmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
 	struct gmac *gm;
-	int i;
 	
 	/* XXX should handle more than one */
 	if (gmacs == NULL)
@@ -920,38 +1107,10 @@
 	case PBOOK_SLEEP_REJECT:
 		break;
 	case PBOOK_SLEEP_NOW:
-		disable_irq(gm->dev->irq);
-		netif_stop_queue(gm->dev);
-		gmac_stop_dma(gm);
-		mii_poll_stop(gm);
-		gmac_set_power(gm, 0);
-		for (i = 0; i < NRX; ++i) {
-			if (gm->rx_buff[i] != 0) {
-				dev_kfree_skb(gm->rx_buff[i]);
-				gm->rx_buff[i] = 0;
-			}
-		}
-		for (i = 0; i < NTX; ++i) {
-			if (gm->tx_buff[i] != 0) {
-				dev_kfree_skb(gm->tx_buff[i]);
-				gm->tx_buff[i] = 0;
-			}
-		}
+		gmac_suspend(gm);
 		break;
 	case PBOOK_WAKE:
-		/* see if this is enough */
-		gmac_powerup_and_reset(gm->dev);
-		gm->full_duplex = 0;
-		gm->phy_status = 0;
-		mii_lookup_and_reset(gm);
-		mii_setup_phy(gm);
-		gmac_init_rings(gm, 0);
-		gmac_mac_init(gm, gm->dev->dev_addr);
-		gmac_set_multicast(gm->dev);
-		mii_interrupt(gm);
-		gmac_start_dma(gm);
-		netif_start_queue(gm->dev);
-		enable_irq(gm->dev->irq);
+		gmac_resume(gm);
 		break;
 	}
 	return PBOOK_SLEEP_OK;
@@ -967,7 +1126,10 @@
 	struct gmac *gm = (struct gmac *) dev->priv;
 	int i, timeout;
 	unsigned long flags;
-		
+
+	if (gm->sleeping)
+		return;
+
 	printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 
 	spin_lock_irqsave(&gm->lock, flags);
@@ -990,6 +1152,8 @@
 		if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0) {
 			/* Mask out all chips interrupts */
 			GM_OUT(GM_IRQ_MASK, 0xffffffff);
+			GM_OUT(GM_MAC_TX_RESET, GM_MAC_TX_RESET_NOW);
+			GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW);
 			break;
 		}
 	}
@@ -1022,6 +1186,9 @@
 	unsigned long flags;
 	int i;
 
+	if (gm->sleeping)
+		return 1;
+		
 	spin_lock_irqsave(&gm->lock, flags);
 
 	i = gm->next_tx;
@@ -1274,7 +1441,7 @@
 	struct gmac *gm = (struct gmac *) dev->priv;
 	struct net_device_stats *stats = &gm->stats;
 
-	if (gm && gm->opened) {
+	if (gm && gm->opened && !gm->sleeping) {
 		stats->rx_crc_errors += GM_IN(GM_MAC_RX_CRC_ERR_CTR);
 		GM_OUT(GM_MAC_RX_CRC_ERR_CTR, 0);
 
@@ -1315,10 +1482,14 @@
 	     gmac = gmac->next)
 		gmac_probe1(gmac);
 
+#ifdef CONFIG_PMAC_PBOOK
+	if (gmacs)
+		pmu_register_sleep_notifier(&gmac_sleep_notifier);
+#endif
 
 	MOD_DEC_USE_COUNT;
 
-	return 0;
+	return gmacs? 0: -ENODEV;
 }
 
 static void
@@ -1343,6 +1514,14 @@
 		return;
 	}
 
+	if (dummy_buf == NULL) {
+		dummy_buf = kmalloc(DUMMY_BUF_LEN, GFP_KERNEL);
+		if (dummy_buf == NULL) {
+			printk(KERN_ERR "GMAC: failed to allocated dummy buffer\n");
+			return;
+		}
+	}
+
 	tx_descpage = get_free_page(GFP_KERNEL);
 	if (tx_descpage == 0) {
 		printk(KERN_ERR "GMAC: can't get a page for tx descriptors\n");
@@ -1351,17 +1530,13 @@
 	rx_descpage = get_free_page(GFP_KERNEL);
 	if (rx_descpage == 0) {
 		printk(KERN_ERR "GMAC: can't get a page for rx descriptors\n");
-		free_page(tx_descpage);
-		return;
+		goto out_txdesc;
 	}
 
 	dev = init_etherdev(NULL, sizeof(struct gmac));
-
 	if (!dev) {
 		printk(KERN_ERR "GMAC: init_etherdev failed, out of memory\n");
-		free_page(tx_descpage);
-		free_page(rx_descpage);
-		return;
+		goto out_rxdesc;
 	}
 	SET_MODULE_OWNER(dev);
 
@@ -1369,6 +1544,10 @@
 	dev->base_addr = gmac->addrs[0].address;
 	gm->regs = (volatile unsigned int *)
 		ioremap(gmac->addrs[0].address, 0x10000);
+	if (!gm->regs) {
+		printk(KERN_ERR "GMAC: unable to map I/O registers\n");
+		goto out_unreg;
+	}
 	dev->irq = gmac->intrs[0].line;
 	gm->dev = dev;
 	gm->of_node = gmac;
@@ -1394,6 +1573,7 @@
 
 	gm->phy_addr = 0;
 	gm->opened = 0;
+	gm->sleeping = 0;
 
 	dev->open = gmac_open;
 	dev->stop = gmac_close;
@@ -1404,13 +1584,18 @@
 	dev->watchdog_timeo = 5*HZ;
 
 	ether_setup(dev);
-	
+
 	gm->next_gmac = gmacs;
 	gmacs = dev;
+	return;
 
-#ifdef CONFIG_PMAC_PBOOK
-	pmu_register_sleep_notifier(&gmac_sleep_notifier);
-#endif
+out_unreg:
+	unregister_netdev(dev);
+	kfree(dev);
+out_rxdesc:
+	free_page(rx_descpage);
+out_txdesc:
+	free_page(tx_descpage);
 }
 
 MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
@@ -1421,16 +1606,25 @@
 	struct gmac *gm;
 	struct net_device *dev;
 
+#ifdef CONFIG_PMAC_PBOOK
+	if (gmacs)
+		pmu_unregister_sleep_notifier(&gmac_sleep_notifier);
+#endif
+
 	while ((dev = gmacs) != NULL) {
 		gm = (struct gmac *) dev->priv;
 		unregister_netdev(dev);
+		iounmap((void *) gm->regs);
 		free_page(gm->tx_desc_page);
 		free_page(gm->rx_desc_page);
 		gmacs = gm->next_gmac;
 		kfree(dev);
 	}
+	if (dummy_buf != NULL) {
+		kfree(dummy_buf);
+		dummy_buf = NULL;
+	}
 }
 
 module_init(gmac_probe);
 module_exit(gmac_cleanup_module);
-
diff -u --recursive --new-file v2.4.4/linux/drivers/net/gmac.h linux/drivers/net/gmac.h
--- v2.4.4/linux/drivers/net/gmac.h	Sun Sep 17 09:48:05 2000
+++ linux/drivers/net/gmac.h	Wed May 16 09:58:36 2001
@@ -722,6 +722,13 @@
 #define MII_ANLPA_CSMA 0x0001      /* CSMA-CD Capable */
 #define MII_ANLPA_PAUS 0x0400 
 
+/* Generic PHYs
+ * 
+ * These GENERIC values assumes that the PHY devices follow 802.3u and
+ * allow parallel detection to set the link partner ability register.
+ * Detection of 100Base-TX [H/F Duplex] and 100Base-T4 is supported.
+ */
+
 /*
  * Model-specific PHY registers
  *
@@ -731,6 +738,7 @@
 
 /* Supported PHYs (phy_type field ) */
 #define PHY_B5400	0x5400
+#define PHY_B5401	0x5401
 #define PHY_B5201	0x5201
 #define PHY_LXT971	0x0971
 #define PHY_UNKNOWN	0
@@ -741,11 +749,21 @@
 #define MII_BCM5201_REV                         0x01
 #define MII_BCM5201_ID                          ((MII_BCM5201_OUI << 10) | (MII_BCM5201_MODEL << 4))
 #define MII_BCM5201_MASK                        0xfffffff0
+#define MII_BCM5221_OUI                         0x001018
+#define MII_BCM5221_MODEL                       0x1e
+#define MII_BCM5221_REV                         0x00
+#define MII_BCM5221_ID                          ((MII_BCM5221_OUI << 10) | (MII_BCM5221_MODEL << 4))
+#define MII_BCM5221_MASK                        0xfffffff0
 #define MII_BCM5400_OUI                         0x000818
 #define MII_BCM5400_MODEL                       0x04
 #define MII_BCM5400_REV                         0x01
 #define MII_BCM5400_ID                          ((MII_BCM5400_OUI << 10) | (MII_BCM5400_MODEL << 4))
 #define MII_BCM5400_MASK                        0xfffffff0
+#define MII_BCM5401_OUI                         0x000818
+#define MII_BCM5401_MODEL                       0x05
+#define MII_BCM5401_REV                         0x01
+#define MII_BCM5401_ID                          ((MII_BCM5401_OUI << 10) | (MII_BCM5401_MODEL << 4))
+#define MII_BCM5401_MASK                        0xfffffff0
 #define MII_LXT971_OUI                          0x0004de
 #define MII_LXT971_MODEL                        0x0e
 #define MII_LXT971_REV                          0x00
@@ -791,7 +809,6 @@
 #define MII_LXT971_STATUS2_AUTONEG_COMPLETE	0x0080
 
 
-
 	/*
 	 * DMA descriptors
 	 */
@@ -877,6 +894,7 @@
 	u8				pci_devfn;
 	spinlock_t			lock;
 	int				opened;
+	int				sleeping;
 	struct net_device		*next_gmac;
 };
 
diff -u --recursive --new-file v2.4.4/linux/drivers/net/hamachi.c linux/drivers/net/hamachi.c
--- v2.4.4/linux/drivers/net/hamachi.c	Fri Apr 20 11:54:23 2001
+++ linux/drivers/net/hamachi.c	Sat May 19 18:02:45 2001
@@ -23,10 +23,21 @@
 	or
 	http://www.parl.clemson.edu/~keithu/hamachi.html
 
-	For best viewing, set your tabs to 3.
+
+
+	Linux kernel changelog:
+
+	LK1.0.1:
+	- fix lack of pci_dev<->dev association
+	- ethtool support (jgarzik)
 
 */
 
+#define DRV_NAME	"hamachi"
+#define DRV_VERSION	"1.01+LK1.0.1"
+#define DRV_RELDATE	"5/18/2001"
+
+
 /* A few user-configurable values. */
 
 static int debug = 1;		/* 1 normal messages, 0 quiet .. 7 verbose.  */
@@ -116,7 +127,7 @@
 #define RX_RING_SIZE	512
 
 /*
- * Enable mii_ioctl.  Added interrupt coalescing parameter adjustment.
+ * Enable netdev_ioctl.  Added interrupt coalescing parameter adjustment.
  * 2/19/99 Pete Wyckoff <wyckoff@ca.sandia.gov>
  */
 
@@ -152,7 +163,9 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/ethtool.h>
 
+#include <asm/uaccess.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -166,7 +179,7 @@
 #include <linux/delay.h>
 
 static char version[] __initdata =
-KERN_INFO "hamachi.c:v1.01 5/16/2000  Written by Donald Becker\n"
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "   Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
 KERN_INFO "   Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
 
@@ -502,7 +515,7 @@
 	unsigned char phys[MII_CNT];		/* MII device addresses, only first one used. */
 	u_int32_t rx_int_var, tx_int_var;	/* interrupt control variables */
 	u_int32_t option;							/* Hold on to a copy of the options */
-	u_int8_t pad[16];							/* Used for 32-byte alignment */
+	struct pci_dev *pci_dev;
 };
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>, Eric Kasten <kasten@nscl.msu.edu>, Keith Underwood <keithu@parl.clemson.edu>");
@@ -527,7 +540,7 @@
 static int mdio_read(long ioaddr, int phy_id, int location);
 static void mdio_write(long ioaddr, int phy_id, int location, int value);
 static int hamachi_open(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void hamachi_timer(unsigned long data);
 static void hamachi_tx_timeout(struct net_device *dev);
 static void hamachi_init_ring(struct net_device *dev);
@@ -569,7 +582,7 @@
 
 	pci_set_master(pdev);
 
-	i = pci_request_regions(pdev, "hamachi");
+	i = pci_request_regions(pdev, DRV_NAME);
 	if (i) return i;
 
 	irq = pdev->irq;
@@ -633,8 +646,10 @@
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
+	pci_set_drvdata(pdev, dev);
 
 	hmp->chip_id = chip_id;
+	hmp->pci_dev = pdev;
 
 	/* The lower four bits are the media type. */
 	if (option > 0) {
@@ -676,7 +691,7 @@
 	dev->stop = &hamachi_close;
 	dev->get_stats = &hamachi_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
-	dev->do_ioctl = &mii_ioctl;
+	dev->do_ioctl = &netdev_ioctl;
 	dev->tx_timeout = &hamachi_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (mtu)
@@ -687,6 +702,7 @@
 		kfree(dev);
 		iounmap((char *)ioaddr);
 		pci_release_regions(pdev);
+		pci_set_drvdata(pdev, NULL);
 		return i;
 	}
 
@@ -1815,12 +1831,38 @@
 	}
 }
 
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct hamachi_private *np = dev->priv;
+	u32 ethcmd;
+		
+	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+		return -EFAULT;
+
+        switch (ethcmd) {
+        case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		strcpy(info.driver, DRV_NAME);
+		strcpy(info.version, DRV_VERSION);
+		strcpy(info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+
+        }
+	
+	return -EOPNOTSUPP;
+}
+
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
 
 	switch(cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
 		data[0] = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
@@ -1878,7 +1920,7 @@
 MODULE_DEVICE_TABLE(pci, hamachi_pci_tbl);
 
 static struct pci_driver hamachi_driver = {
-	name:		"hamachi",
+	name:		DRV_NAME,
 	id_table:	hamachi_pci_tbl,
 	probe:		hamachi_init_one,
 	remove:		hamachi_remove_one,
diff -u --recursive --new-file v2.4.4/linux/drivers/net/hp100.h linux/drivers/net/hp100.h
--- v2.4.4/linux/drivers/net/hp100.h	Wed May 20 18:55:04 1998
+++ linux/drivers/net/hp100.h	Wed May 16 10:25:38 2001
@@ -38,10 +38,10 @@
 #define HP100_REG_HW_ID		0x00	/* R:  (16) Unique card ID           */
 #define HP100_REG_TRACE		0x00	/* W:  (16) Used for debug output    */
 #define HP100_REG_PAGING	0x02	/* R:  (16),15:4 Card ID             */
-                                        /* W:  (16),3:0 Switch pages         */
+					/* W:  (16),3:0 Switch pages         */
 #define HP100_REG_OPTION_LSW	0x04	/* RW: (16) Select card functions    */
 #define HP100_REG_OPTION_MSW	0x06	/* RW: (16) Select card functions    */
-                                        
+
 /*  Page 0 - Performance  */
 
 #define HP100_REG_IRQ_STATUS	0x08	/* RW: (16) Which ints are pending   */
@@ -53,27 +53,27 @@
 #define HP100_REG_DATA32	0x10	/* RW: (32) I/O mode data port       */
 #define HP100_REG_DATA16	0x12	/* RW: WORDs must be read from here  */
 #define HP100_REG_TX_MEM_FREE	0x14	/* RD: (32) Amount of free Tx mem    */
-#define HP100_REG_TX_PDA_L      0x14    /* W: (32) BM: Ptr to PDL, Low Pri  */
-#define HP100_REG_TX_PDA_H      0x1c    /* W: (32) BM: Ptr to PDL, High Pri */
+#define HP100_REG_TX_PDA_L      0x14	/* W: (32) BM: Ptr to PDL, Low Pri  */
+#define HP100_REG_TX_PDA_H      0x1c	/* W: (32) BM: Ptr to PDL, High Pri */
 #define HP100_REG_RX_PKT_CNT	0x18	/* RD: (8) Rx count of pkts on card  */
 #define HP100_REG_TX_PKT_CNT	0x19	/* RD: (8) Tx count of pkts on card  */
-#define HP100_REG_RX_PDL        0x1a    /* R: (8) BM: # rx pdl not executed */
-#define HP100_REG_TX_PDL        0x1b    /* R: (8) BM: # tx pdl not executed */
-#define HP100_REG_RX_PDA        0x18    /* W: (32) BM: Up to 31 addresses */
-                                        /*             which point to a PDL */
-#define HP100_REG_SL_EARLY      0x1c    /*    (32) Enhanced Slave Early Rx */
-#define HP100_REG_STAT_DROPPED  0x20    /* R (12) Dropped Packet Counter */
-#define HP100_REG_STAT_ERRORED  0x22    /* R (8) Errored Packet Counter */
-#define HP100_REG_STAT_ABORT    0x23    /* R (8) Abort Counter/OW Coll. Flag */
-#define HP100_REG_RX_RING       0x24    /* W (32) Slave: RX Ring Pointers */
-#define HP100_REG_32_FRAGMENT_LEN 0x28  /* W (13) Slave: Fragment Length Reg */
-#define HP100_REG_32_OFFSET     0x2c    /* W (16) Slave: Offset Register */
+#define HP100_REG_RX_PDL        0x1a	/* R: (8) BM: # rx pdl not executed */
+#define HP100_REG_TX_PDL        0x1b	/* R: (8) BM: # tx pdl not executed */
+#define HP100_REG_RX_PDA        0x18	/* W: (32) BM: Up to 31 addresses */
+					/*             which point to a PDL */
+#define HP100_REG_SL_EARLY      0x1c	/*    (32) Enhanced Slave Early Rx */
+#define HP100_REG_STAT_DROPPED  0x20	/* R (12) Dropped Packet Counter */
+#define HP100_REG_STAT_ERRORED  0x22	/* R (8) Errored Packet Counter */
+#define HP100_REG_STAT_ABORT    0x23	/* R (8) Abort Counter/OW Coll. Flag */
+#define HP100_REG_RX_RING       0x24	/* W (32) Slave: RX Ring Pointers */
+#define HP100_REG_32_FRAGMENT_LEN 0x28	/* W (13) Slave: Fragment Length Reg */
+#define HP100_REG_32_OFFSET     0x2c	/* W (16) Slave: Offset Register */
 
 /*  Page 1 - MAC Address/Hash Table  */
 
-#define HP100_REG_MAC_ADDR	0x08	/* RW: (8) Cards MAC address	     */
+#define HP100_REG_MAC_ADDR	0x08	/* RW: (8) Cards MAC address         */
 #define HP100_REG_HASH_BYTE0	0x10	/* RW: (8) Cards multicast filter    */
-                                        
+
 /*  Page 2 - Hardware Mapping  */
 
 #define HP100_REG_MEM_MAP_LSW	0x08	/* RW: (16) LSW of cards mem addr    */
@@ -84,44 +84,44 @@
 #define HP100_REG_BM		0x0f	/* RW: (8) Controls BM functions     */
 
 /* New on Page 2 for ETR chips: */
-#define HP100_REG_MODECTRL1     0x10    /* RW: (8) Mode Control 1 */
-#define HP100_REG_MODECTRL2     0x11    /* RW: (8) Mode Control 2 */
-#define HP100_REG_PCICTRL1      0x12    /* RW: (8) PCI Cfg 1 */
-#define HP100_REG_PCICTRL2      0x13    /* RW: (8) PCI Cfg 2 */
-#define HP100_REG_PCIBUSMLAT    0x15    /* RW: (8) PCI Bus Master Latency */
-#define HP100_REG_EARLYTXCFG    0x16    /* RW: (16) Early TX Cfg/Cntrl Reg */
-#define HP100_REG_EARLYRXCFG    0x18    /* RW: (8) Early RX Cfg/Cntrl Reg */
-#define HP100_REG_ISAPNPCFG1    0x1a    /* RW: (8) ISA PnP Cfg/Cntrl Reg 1 */
-#define HP100_REG_ISAPNPCFG2    0x1b    /* RW: (8) ISA PnP Cfg/Cntrl Reg 2 */
-                                        
+#define HP100_REG_MODECTRL1     0x10	/* RW: (8) Mode Control 1 */
+#define HP100_REG_MODECTRL2     0x11	/* RW: (8) Mode Control 2 */
+#define HP100_REG_PCICTRL1      0x12	/* RW: (8) PCI Cfg 1 */
+#define HP100_REG_PCICTRL2      0x13	/* RW: (8) PCI Cfg 2 */
+#define HP100_REG_PCIBUSMLAT    0x15	/* RW: (8) PCI Bus Master Latency */
+#define HP100_REG_EARLYTXCFG    0x16	/* RW: (16) Early TX Cfg/Cntrl Reg */
+#define HP100_REG_EARLYRXCFG    0x18	/* RW: (8) Early RX Cfg/Cntrl Reg */
+#define HP100_REG_ISAPNPCFG1    0x1a	/* RW: (8) ISA PnP Cfg/Cntrl Reg 1 */
+#define HP100_REG_ISAPNPCFG2    0x1b	/* RW: (8) ISA PnP Cfg/Cntrl Reg 2 */
+
 /*  Page 3 - EEPROM/Boot ROM  */
 
 #define HP100_REG_EEPROM_CTRL	0x08	/* RW: (16) Used to load EEPROM      */
 #define HP100_REG_BOOTROM_CTRL  0x0a
-                                        
+
 /*  Page 4 - LAN Configuration  (MAC_CTRL) */
 
 #define HP100_REG_10_LAN_CFG_1	0x08	/* RW: (8) Set 10M XCVR functions   */
-#define HP100_REG_10_LAN_CFG_2  0x09    /* RW: (8)     10M XCVR functions   */
+#define HP100_REG_10_LAN_CFG_2  0x09	/* RW: (8)     10M XCVR functions   */
 #define HP100_REG_VG_LAN_CFG_1	0x0a	/* RW: (8) Set 100M XCVR functions  */
-#define HP100_REG_VG_LAN_CFG_2  0x0b    /* RW: (8) 100M LAN Training cfgregs */
+#define HP100_REG_VG_LAN_CFG_2  0x0b	/* RW: (8) 100M LAN Training cfgregs */
 #define HP100_REG_MAC_CFG_1	0x0c	/* RW: (8) Types of pkts to accept   */
 #define HP100_REG_MAC_CFG_2	0x0d	/* RW: (8) Misc MAC functions        */
-#define HP100_REG_MAC_CFG_3     0x0e    /* RW: (8) Misc MAC functions */
-#define HP100_REG_MAC_CFG_4     0x0f    /* R:  (8) Misc MAC states */
-#define HP100_REG_DROPPED	0x10	/* R:  (16),11:0 Pkts cant fit in mem*/
+#define HP100_REG_MAC_CFG_3     0x0e	/* RW: (8) Misc MAC functions */
+#define HP100_REG_MAC_CFG_4     0x0f	/* R:  (8) Misc MAC states */
+#define HP100_REG_DROPPED	0x10	/* R:  (16),11:0 Pkts cant fit in mem */
 #define HP100_REG_CRC		0x12	/* R:  (8) Pkts with CRC             */
 #define HP100_REG_ABORT		0x13	/* R:  (8) Aborted Tx pkts           */
-#define HP100_REG_TRAIN_REQUEST 0x14    /* RW: (16) Endnode MAC register.*/
-#define HP100_REG_TRAIN_ALLOW   0x16    /* R:  (16) Hub allowed register */
-                    
+#define HP100_REG_TRAIN_REQUEST 0x14	/* RW: (16) Endnode MAC register. */
+#define HP100_REG_TRAIN_ALLOW   0x16	/* R:  (16) Hub allowed register */
+
 /*  Page 5 - MMU  */
 
 #define HP100_REG_RX_MEM_STOP	0x0c	/* RW: (16) End of Rx ring addr      */
 #define HP100_REG_TX_MEM_STOP	0x0e	/* RW: (16) End of Tx ring addr      */
-#define HP100_REG_PDL_MEM_STOP  0x10    /* Not used by 802.12 devices */
-#define HP100_REG_ECB_MEM_STOP  0x14    /* I've no idea what this is */
-          
+#define HP100_REG_PDL_MEM_STOP  0x10	/* Not used by 802.12 devices */
+#define HP100_REG_ECB_MEM_STOP  0x14	/* I've no idea what this is */
+
 /*  Page 6 - Card ID/Physical LAN Address  */
 
 #define HP100_REG_BOARD_ID	0x08	/* R:  (8) EISA/ISA card ID          */
@@ -129,7 +129,7 @@
 #define HP100_REG_SOFT_MODEL	0x0d	/* R:  (8) Config program defined    */
 #define HP100_REG_LAN_ADDR	0x10	/* R:  (8) MAC addr of card          */
 #define HP100_REG_LAN_ADDR_CHCK 0x16	/* R:  (8) Added to addr to get FFh  */
-                                        
+
 /*  Page 7 - MMU Current Pointers  */
 
 #define HP100_REG_PTR_RXSTART	0x08	/* R:  (16) Current begin of Rx ring */
@@ -146,7 +146,7 @@
 /* 
  * Hardware ID Register I (Always available, HW_ID, Offset 0x00)
  */
-#define HP100_HW_ID_CASCADE     0x4850  /* Identifies Cascade Chip */
+#define HP100_HW_ID_CASCADE     0x4850	/* Identifies Cascade Chip */
 
 /* 
  * Hardware ID Register 2 & Paging Register
@@ -154,12 +154,12 @@
  * Bits 15:4 are for the Chip ID 
  */
 #define HP100_CHIPID_MASK        0xFFF0
-#define HP100_CHIPID_SHASTA      0x5350  /* Not 802.12 compliant */
-                                         /* EISA BM/SL, MCA16/32 SL, ISA SL */
-#define HP100_CHIPID_RAINIER     0x5360  /* Not 802.12 compliant EISA BM,*/
-                                         /* PCI SL, MCA16/32 SL, ISA SL */
-#define HP100_CHIPID_LASSEN      0x5370  /* 802.12 compliant PCI BM, PCI SL */
-                                         /* LRF supported */
+#define HP100_CHIPID_SHASTA      0x5350	/* Not 802.12 compliant */
+					 /* EISA BM/SL, MCA16/32 SL, ISA SL */
+#define HP100_CHIPID_RAINIER     0x5360	/* Not 802.12 compliant EISA BM, */
+					 /* PCI SL, MCA16/32 SL, ISA SL */
+#define HP100_CHIPID_LASSEN      0x5370	/* 802.12 compliant PCI BM, PCI SL */
+					 /* LRF supported */
 
 /*
  *  Option Registers I and II 
@@ -167,24 +167,24 @@
  */
 #define HP100_DEBUG_EN		0x8000	/* 0:Dis., 1:Enable Debug Dump Ptr. */
 #define HP100_RX_HDR		0x4000	/* 0:Dis., 1:Enable putting pkt into */
-                                        /*   system mem. before Rx interrupt */
+					/*   system mem. before Rx interrupt */
 #define HP100_MMAP_DIS		0x2000	/* 0:Enable, 1:Disable mem.mapping. */
-                                        /*   MMAP_DIS must be 0 and MEM_EN */
-                                        /*   must be 1 for memory-mapped */
-                                        /*   mode to be enabled */
+					/*   MMAP_DIS must be 0 and MEM_EN */
+					/*   must be 1 for memory-mapped */
+					/*   mode to be enabled */
 #define HP100_EE_EN		0x1000	/* 0:Disable,1:Enable EEPROM writing */
 #define HP100_BM_WRITE		0x0800	/* 0:Slave, 1:Bus Master for Tx data */
 #define HP100_BM_READ		0x0400	/* 0:Slave, 1:Bus Master for Rx data */
 #define HP100_TRI_INT		0x0200	/* 0:Don't, 1:Do tri-state the int */
 #define HP100_MEM_EN		0x0040	/* Config program set this to */
-                                        /*   0:Disable, 1:Enable mem map. */
-                                        /*   See MMAP_DIS. */
+					/*   0:Disable, 1:Enable mem map. */
+					/*   See MMAP_DIS. */
 #define HP100_IO_EN		0x0020	/* 1:Enable I/O transfers */
 #define HP100_BOOT_EN		0x0010	/* 1:Enable boot ROM access */
 #define HP100_FAKE_INT		0x0008	/* 1:int */
 #define HP100_INT_EN		0x0004	/* 1:Enable ints from card */
 #define HP100_HW_RST		0x0002	/* 0:Reset, 1:Out of reset */
-                                        /* NIC reset on 0 to 1 transition */
+					/* NIC reset on 0 to 1 transition */
 
 /*
  *  Option Register III 
@@ -193,9 +193,9 @@
 #define HP100_PRIORITY_TX	0x0080	/* 1:Do all Tx pkts as priority */
 #define HP100_EE_LOAD		0x0040	/* 1:EEPROM loading, 0 when done */
 #define HP100_ADV_NXT_PKT	0x0004	/* 1:Advance to next pkt in Rx queue */
-                                        /*   h/w will set to 0 when done */
+					/*   h/w will set to 0 when done */
 #define HP100_TX_CMD		0x0002	/* 1:Tell h/w download done, h/w */
-                                        /*   will set to 0 when done */
+					/*   will set to 0 when done */
 
 /*
  * Interrupt Status Registers I and II
@@ -208,10 +208,10 @@
 #define HP100_RX_PDL_FILL_COMPL 0x0800
 #define HP100_RX_PACKET		0x0400	/* 0:No, 1:Yes pkt has been Rx */
 #define HP100_RX_ERROR		0x0200	/* 0:No, 1:Yes Rx pkt had error */
-#define HP100_TX_PDA_ZERO       0x0020  /* 1 when PDA count goes to zero */
+#define HP100_TX_PDA_ZERO       0x0020	/* 1 when PDA count goes to zero */
 #define HP100_TX_SPACE_AVAIL	0x0010	/* 0:<8192, 1:>=8192 Tx free bytes */
 #define HP100_TX_COMPLETE	0x0008	/* 0:No, 1:Yes a Tx has completed */
-#define HP100_MISC_ERROR        0x0004  /* 0:No, 1:Lan Link down or bus error*/
+#define HP100_MISC_ERROR        0x0004	/* 0:No, 1:Lan Link down or bus error */
 #define HP100_TX_ERROR		0x0002	/* 0:No, 1:Yes Tx pkt had error */
 
 /*
@@ -229,7 +229,7 @@
 #define HP100_IRQ_SCRAMBLE      0x40
 #define HP100_BOND_HP           0x20
 #define HP100_LEVEL_IRQ		0x10	/* 0:Edge, 1:Level type interrupts. */
-                                        /* (Only valid on EISA cards) */
+					/* (Only valid on EISA cards) */
 #define HP100_IRQMASK		0x0F	/* Isolate the IRQ bits */
 
 /*
@@ -237,20 +237,20 @@
  * (Page HW_MAP, SRAM, Offset 0x0e)
  */
 #define HP100_RAM_SIZE_MASK	0xe0	/* AND to get SRAM size index */
-#define HP100_RAM_SIZE_SHIFT	0x05	/* Shift count(put index in lwr bits)*/
+#define HP100_RAM_SIZE_SHIFT	0x05	/* Shift count(put index in lwr bits) */
 
 /*
  * Bus Master Register
  * (Page HW_MAP, BM, Offset 0x0f)
  */
-#define HP100_BM_BURST_RD       0x01    /* EISA only: 1=Use burst trans. fm system */
-                                        /* memory to chip (tx) */
-#define HP100_BM_BURST_WR       0x02    /* EISA only: 1=Use burst trans. fm system */
-                                        /* memory to chip (rx) */
+#define HP100_BM_BURST_RD       0x01	/* EISA only: 1=Use burst trans. fm system */
+					/* memory to chip (tx) */
+#define HP100_BM_BURST_WR       0x02	/* EISA only: 1=Use burst trans. fm system */
+					/* memory to chip (rx) */
 #define HP100_BM_MASTER		0x04	/* 0:Slave, 1:BM mode */
-#define HP100_BM_PAGE_CK        0x08    /* This bit should be set whenever in*/
-                                        /* an EISA system */
-#define HP100_BM_PCI_8CLK       0x40    /* ... cycles 8 clocks apart */
+#define HP100_BM_PAGE_CK        0x08	/* This bit should be set whenever in */
+					/* an EISA system */
+#define HP100_BM_PCI_8CLK       0x40	/* ... cycles 8 clocks apart */
 
 
 /* 
@@ -258,82 +258,82 @@
  * (Page HW_MAP, MODECTRL1, Offset0x10)
  */
 #define HP100_TX_DUALQ          0x10
-   /* If set and BM -> dual tx pda queues*/
-#define HP100_ISR_CLRMODE       0x02   /* If set ISR will clear all pending */
-                                       /* interrupts on read (etr only?) */
-#define HP100_EE_NOLOAD         0x04   /* Status whether res will be loaded */
-                                       /* from the eeprom */
-#define HP100_TX_CNT_FLG        0x08   /* Controls Early TX Reg Cnt Field */
-#define HP100_PDL_USE3          0x10   /* If set BM engine will read only */
-                                       /* first three data elements of a PDL */
-                                       /* on the first access. */
-#define HP100_BUSTYPE_MASK      0xe0   /* Three bit bus type info */
+   /* If set and BM -> dual tx pda queues */
+#define HP100_ISR_CLRMODE       0x02	/* If set ISR will clear all pending */
+				       /* interrupts on read (etr only?) */
+#define HP100_EE_NOLOAD         0x04	/* Status whether res will be loaded */
+				       /* from the eeprom */
+#define HP100_TX_CNT_FLG        0x08	/* Controls Early TX Reg Cnt Field */
+#define HP100_PDL_USE3          0x10	/* If set BM engine will read only */
+				       /* first three data elements of a PDL */
+				       /* on the first access. */
+#define HP100_BUSTYPE_MASK      0xe0	/* Three bit bus type info */
 
 /*
  * Mode Control Register II
  * (Page HW_MAP, MODECTRL2, Offset0x11)
  */
-#define HP100_EE_MASK           0x0f   /* Tell EEPROM circuit not to load */ 
-                                       /* certain resources */
-#define HP100_DIS_CANCEL        0x20   /* For tx dualq mode operation */
-#define HP100_EN_PDL_WB         0x40   /* 1: Status of PDL completion may be */
-                                       /* written back to system mem */
-#define HP100_EN_BUS_FAIL       0x80   /* Enables bus-fail portion of misc */
-                                       /* interrupt */
+#define HP100_EE_MASK           0x0f	/* Tell EEPROM circuit not to load */
+				       /* certain resources */
+#define HP100_DIS_CANCEL        0x20	/* For tx dualq mode operation */
+#define HP100_EN_PDL_WB         0x40	/* 1: Status of PDL completion may be */
+				       /* written back to system mem */
+#define HP100_EN_BUS_FAIL       0x80	/* Enables bus-fail portion of misc */
+				       /* interrupt */
 
 /* 
  * PCI Configuration and Control Register I
  * (Page HW_MAP, PCICTRL1, Offset 0x12)
  */
-#define HP100_LO_MEM            0x01   /* 1: Mapped Mem requested below 1MB */
-#define HP100_NO_MEM            0x02   /* 1: Disables Req for sysmem to PCI */ 
-                                       /* bios */
-#define HP100_USE_ISA           0x04   /* 1: isa type decodes will occur */
-                                       /* simultaneously with PCI decodes */
-#define HP100_IRQ_HI_MASK       0xf0   /* pgmed by pci bios */
-#define HP100_PCI_IRQ_HI_MASK   0x78    /* Isolate 4 bits for PCI IRQ  */
- 
+#define HP100_LO_MEM            0x01	/* 1: Mapped Mem requested below 1MB */
+#define HP100_NO_MEM            0x02	/* 1: Disables Req for sysmem to PCI */
+				       /* bios */
+#define HP100_USE_ISA           0x04	/* 1: isa type decodes will occur */
+				       /* simultaneously with PCI decodes */
+#define HP100_IRQ_HI_MASK       0xf0	/* pgmed by pci bios */
+#define HP100_PCI_IRQ_HI_MASK   0x78	/* Isolate 4 bits for PCI IRQ  */
+
 /*
  * PCI Configuration and Control Register II
  * (Page HW_MAP, PCICTRL2, Offset 0x13)
  */
-#define HP100_RD_LINE_PDL       0x01   /* 1: PCI command Memory Read Line en */
-#define HP100_RD_TX_DATA_MASK   0x06   /* choose PCI memread cmds for TX */ 
-#define HP100_MWI               0x08   /* 1: en. PCI memory write invalidate */
-#define HP100_ARB_MODE          0x10   /* Select PCI arbitor type */
-#define HP100_STOP_EN           0x20   /* Enables PCI state machine to issue */
-                                       /* pci stop if cascade not ready */
-#define HP100_IGNORE_PAR        0x40   /* 1: PCI state machine ignores parity*/
-#define HP100_PCI_RESET         0x80   /* 0->1: Reset PCI block */
+#define HP100_RD_LINE_PDL       0x01	/* 1: PCI command Memory Read Line en */
+#define HP100_RD_TX_DATA_MASK   0x06	/* choose PCI memread cmds for TX */
+#define HP100_MWI               0x08	/* 1: en. PCI memory write invalidate */
+#define HP100_ARB_MODE          0x10	/* Select PCI arbitor type */
+#define HP100_STOP_EN           0x20	/* Enables PCI state machine to issue */
+				       /* pci stop if cascade not ready */
+#define HP100_IGNORE_PAR        0x40	/* 1: PCI state machine ignores parity */
+#define HP100_PCI_RESET         0x80	/* 0->1: Reset PCI block */
 
 /*
  * Early TX Configuration and Control Register
  * (Page HW_MAP, EARLYTXCFG, Offset 0x16)
  */
-#define HP100_EN_EARLY_TX       0x8000  /* 1=Enable Early TX */
-#define HP100_EN_ADAPTIVE       0x4000  /* 1=Enable adaptive mode */
-#define HP100_EN_TX_UR_IRQ      0x2000  /* reserved, must be 0 */
-#define HP100_EN_LOW_TX         0x1000  /* reserved, must be 0 */
-#define HP100_ET_CNT_MASK       0x0fff  /* bits 11..0: ET counters */
+#define HP100_EN_EARLY_TX       0x8000	/* 1=Enable Early TX */
+#define HP100_EN_ADAPTIVE       0x4000	/* 1=Enable adaptive mode */
+#define HP100_EN_TX_UR_IRQ      0x2000	/* reserved, must be 0 */
+#define HP100_EN_LOW_TX         0x1000	/* reserved, must be 0 */
+#define HP100_ET_CNT_MASK       0x0fff	/* bits 11..0: ET counters */
 
 /*
  * Early RX Configuration and Control Register
  * (Page HW_MAP, EARLYRXCFG, Offset 0x18)
  */
-#define HP100_EN_EARLY_RX       0x80     /* 1=Enable Early RX */
-#define HP100_EN_LOW_RX         0x40     /* reserved, must be 0 */
-#define HP100_RX_TRIP_MASK      0x1f     /* bits 4..0: threshold at which the
-					  * early rx circuit will start the
-					  * dma of received packet into system
-					  * memory for BM */
+#define HP100_EN_EARLY_RX       0x80	/* 1=Enable Early RX */
+#define HP100_EN_LOW_RX         0x40	/* reserved, must be 0 */
+#define HP100_RX_TRIP_MASK      0x1f	/* bits 4..0: threshold at which the
+					 * early rx circuit will start the
+					 * dma of received packet into system
+					 * memory for BM */
 
 /*
  *  Serial Devices Control Register
  * (Page EEPROM_CTRL, EEPROM_CTRL, Offset 0x08)
  */
 #define HP100_EEPROM_LOAD	0x0001	/* 0->1 loads EEPROM into registers. */
-                                        /* When it goes back to 0, load is   */
-                                        /* complete. This should take ~600us.*/
+					/* When it goes back to 0, load is   */
+					/* complete. This should take ~600us. */
 
 /*
  * 10MB LAN Control and Configuration Register I
@@ -345,7 +345,7 @@
 #define HP100_LINK_BEAT_DIS	0x08	/* 0:Enable, 1:Disable link beat */
 #define HP100_LINK_BEAT_ST	0x04	/* 0:No, 1:Yes link beat being Rx */
 #define HP100_R_ROL_ST		0x02	/* 0:No, 1:Yes Rx twisted pair has */
-                                        /*             been reversed */
+					/*             been reversed */
 #define HP100_AUI_ST		0x01	/* 0:No, 1:Yes use AUI on TP card */
 
 /*
@@ -353,9 +353,9 @@
  * (Page MAC_CTRL, 10_LAN_CFG_2, Offset 0x09)
  */
 #define HP100_SQU_ST		0x01	/* 0:No, 1:Yes collision signal sent */
-                                        /*       after Tx.Only used for AUI. */
-#define HP100_FULLDUP           0x02    /* 1: LXT901 XCVR fullduplx enabled */
-#define HP100_DOT3_MAC          0x04    /* 1: DOT 3 Mac sel. unless Autosel */
+					/*       after Tx.Only used for AUI. */
+#define HP100_FULLDUP           0x02	/* 1: LXT901 XCVR fullduplx enabled */
+#define HP100_DOT3_MAC          0x04	/* 1: DOT 3 Mac sel. unless Autosel */
 
 /*
  * MAC Selection, use with MAC10_SEL bits
@@ -372,9 +372,9 @@
 #define HP100_FRAME_FORMAT	0x08	/* 0:802.3, 1:802.5 frames */
 #define HP100_BRIDGE		0x04	/* 0:No, 1:Yes tell hub i am a bridge */
 #define HP100_PROM_MODE		0x02	/* 0:No, 1:Yes tell hub card is */
-                                        /*         promiscuous */
+					/*         promiscuous */
 #define HP100_REPEATER		0x01	/* 0:No, 1:Yes tell hub MAC wants to */
-                                        /*         be a cascaded repeater */
+					/*         be a cascaded repeater */
 
 /*
  * 100MB LAN Control and Configuration Register
@@ -383,16 +383,16 @@
 #define HP100_VG_SEL	        0x80	/* 0:No, 1:Yes use 100 Mbit MAC */
 #define HP100_LINK_UP_ST	0x40	/* 0:No, 1:Yes endnode logged in */
 #define HP100_LINK_CABLE_ST	0x20	/* 0:No, 1:Yes cable can hear tones */
-                                        /*         from  hub */
+					/*         from  hub */
 #define HP100_LOAD_ADDR		0x10	/* 0->1 card addr will be sent  */
-                                        /* 100ms later the link status  */
-                                        /* bits are valid */
+					/* 100ms later the link status  */
+					/* bits are valid */
 #define HP100_LINK_CMD		0x08	/* 0->1 link will attempt to log in. */
-                                        /* 100ms later the link status */
-                                        /* bits are valid */
-#define HP100_TRN_DONE          0x04    /* NEW ETR-Chips only: Will be reset */
-                                        /* after LinkUp Cmd is given and set */
-                                        /* when training has completed. */
+					/* 100ms later the link status */
+					/* bits are valid */
+#define HP100_TRN_DONE          0x04	/* NEW ETR-Chips only: Will be reset */
+					/* after LinkUp Cmd is given and set */
+					/* when training has completed. */
 #define HP100_LINK_GOOD_ST	0x02	/* 0:No, 1:Yes cable passed training */
 #define HP100_VG_RESET		0x01	/* 0:Yes, 1:No reset the 100VG MAC */
 
@@ -414,7 +414,7 @@
 #define HP100_MAC1MODE2		0x00
 #define HP100_MAC1MODE3		HP100_MAC1MODE2 | HP100_ACC_BC
 #define HP100_MAC1MODE4		HP100_MAC1MODE3 | HP100_ACC_MC
-#define HP100_MAC1MODE5		HP100_MAC1MODE4 /* set mc hash to all ones also */
+#define HP100_MAC1MODE5		HP100_MAC1MODE4	/* set mc hash to all ones also */
 #define HP100_MAC1MODE6		HP100_MAC1MODE5 | HP100_ACC_PHY	/* Promiscuous */
 /* Note MODE6 will receive all GOOD packets on the LAN. This really needs
    a mode 7 defined to be LAN Analyzer mode, which will receive errored and
@@ -428,14 +428,14 @@
 #define HP100_TR_MODE		0x80	/* 0:No, 1:Yes support Token Ring formats */
 #define HP100_TX_SAME		0x40	/* 0:No, 1:Yes Tx same packet continuous */
 #define HP100_LBK_XCVR		0x20	/* 0:No, 1:Yes loopback through MAC & */
-                                        /*   transceiver */
+					/*   transceiver */
 #define HP100_LBK_MAC		0x10	/* 0:No, 1:Yes loopback through MAC */
 #define HP100_CRC_I		0x08	/* 0:No, 1:Yes inhibit CRC on Tx packets */
-#define HP100_ACCNA             0x04    /* 1: For 802.5: Accept only token ring
+#define HP100_ACCNA             0x04	/* 1: For 802.5: Accept only token ring
 					 * group addr that maches NA mask */
 #define HP100_KEEP_CRC		0x02	/* 0:No, 1:Yes keep CRC on Rx packets. */
-                                        /*   The length will reflect this. */
-#define HP100_ACCFA             0x01    /* 1: For 802.5: Accept only functional
+					/*   The length will reflect this. */
+#define HP100_ACCFA             0x01	/* 1: For 802.5: Accept only functional
 					 * addrs that match FA mask (page1) */
 #define HP100_MAC2MODEMASK	0x02
 #define HP100_MAC2MODE1		0x00
@@ -450,58 +450,58 @@
  * MAC Configuration Register III 
  * (Page MAC_CTRL, MAC_CFG_3, Offset 0x0e) 
  */
-#define HP100_PACKET_PACE       0x03     /* Packet Pacing:
-					  * 00: No packet pacing
-                                          * 01: 8 to 16 uS delay
-                                          * 10: 16 to 32 uS delay
-                                          * 11: 32 to 64 uS delay
-					  */
-#define HP100_LRF_EN            0x04     /* 1: External LAN Rcv Filter and
-					  * TCP/IP Checksumming enabled. */
-#define HP100_AUTO_MODE         0x10     /* 1: AutoSelect between 10/100 */
+#define HP100_PACKET_PACE       0x03	/* Packet Pacing:
+					 * 00: No packet pacing
+					 * 01: 8 to 16 uS delay
+					 * 10: 16 to 32 uS delay
+					 * 11: 32 to 64 uS delay
+					 */
+#define HP100_LRF_EN            0x04	/* 1: External LAN Rcv Filter and
+					 * TCP/IP Checksumming enabled. */
+#define HP100_AUTO_MODE         0x10	/* 1: AutoSelect between 10/100 */
 
 /*
  * MAC Configuration Register IV 
  * (Page MAC_CTRL, MAC_CFG_4, Offset 0x0f)
  */
-#define HP100_MAC_SEL_ST        0x01      /* (R): Status of external VGSEL
-					   * Signal, 1=100VG, 0=10Mbit sel. */
-#define HP100_LINK_FAIL_ST      0x02      /* (R): Status of Link Fail portion
-                                           * of the Misc. Interrupt */
+#define HP100_MAC_SEL_ST        0x01	/* (R): Status of external VGSEL
+					 * Signal, 1=100VG, 0=10Mbit sel. */
+#define HP100_LINK_FAIL_ST      0x02	/* (R): Status of Link Fail portion
+					 * of the Misc. Interrupt */
 
 /* 
  *  100 MB LAN Training Request/Allowed Registers 
  * (Page MAC_CTRL, TRAIN_REQUEST and TRAIN_ALLOW, Offset 0x14-0x16)(ETR parts only)
  */
-#define HP100_MACRQ_REPEATER         0x0001  /* 1: MAC tells HUB it wants to be 
-				              *    a cascaded repeater
-					      * 0: ... wants to be a DTE */
-#define HP100_MACRQ_PROMSC           0x0006  /* 2 bits: Promiscious mode
-					      * 00: Rcv only unicast packets
-					      *     specifically addr to this
-					      *     endnode
-					      * 10: Rcv all pckts fwded by 
-					      *     the local repeater */
-#define HP100_MACRQ_FRAMEFMT_EITHER  0x0018  /* 11: either format allowed */
-#define HP100_MACRQ_FRAMEFMT_802_3   0x0000  /* 00: 802.3 is requested */
-#define HP100_MACRQ_FRAMEFMT_802_5   0x0010  /* 10: 802.5 format is requested */
-#define HP100_CARD_MACVER            0xe000  /* R: 3 bit Cards 100VG MAC version */
-#define HP100_MALLOW_REPEATER        0x0001  /* If reset, requested access as an
-					      * end node is allowed */
-#define HP100_MALLOW_PROMSC          0x0004  /* 2 bits: Promiscious mode
-					      * 00: Rcv only unicast packets
-					      *     specifically addr to this
-					      *     endnode
-					      * 10: Rcv all pckts fwded by 
-					      *     the local repeater */
-#define HP100_MALLOW_FRAMEFMT        0x00e0  /* 2 bits: Frame Format
-					      * 00: 802.3 format will be used
-					      * 10: 802.5 format will be used */
-#define HP100_MALLOW_ACCDENIED       0x0400  /* N bit */
-#define HP100_MALLOW_CONFIGURE       0x0f00  /* C bit */
-#define HP100_MALLOW_DUPADDR         0x1000  /* D bit */
-#define HP100_HUB_MACVER             0xe000  /* R: 3 bit 802.12 MAC/RMAC training */
-                                             /*    protocol of repeater */
+#define HP100_MACRQ_REPEATER         0x0001	/* 1: MAC tells HUB it wants to be 
+						 *    a cascaded repeater
+						 * 0: ... wants to be a DTE */
+#define HP100_MACRQ_PROMSC           0x0006	/* 2 bits: Promiscious mode
+						 * 00: Rcv only unicast packets
+						 *     specifically addr to this
+						 *     endnode
+						 * 10: Rcv all pckts fwded by 
+						 *     the local repeater */
+#define HP100_MACRQ_FRAMEFMT_EITHER  0x0018	/* 11: either format allowed */
+#define HP100_MACRQ_FRAMEFMT_802_3   0x0000	/* 00: 802.3 is requested */
+#define HP100_MACRQ_FRAMEFMT_802_5   0x0010	/* 10: 802.5 format is requested */
+#define HP100_CARD_MACVER            0xe000	/* R: 3 bit Cards 100VG MAC version */
+#define HP100_MALLOW_REPEATER        0x0001	/* If reset, requested access as an
+						 * end node is allowed */
+#define HP100_MALLOW_PROMSC          0x0004	/* 2 bits: Promiscious mode
+						 * 00: Rcv only unicast packets
+						 *     specifically addr to this
+						 *     endnode
+						 * 10: Rcv all pckts fwded by 
+						 *     the local repeater */
+#define HP100_MALLOW_FRAMEFMT        0x00e0	/* 2 bits: Frame Format
+						 * 00: 802.3 format will be used
+						 * 10: 802.5 format will be used */
+#define HP100_MALLOW_ACCDENIED       0x0400	/* N bit */
+#define HP100_MALLOW_CONFIGURE       0x0f00	/* C bit */
+#define HP100_MALLOW_DUPADDR         0x1000	/* D bit */
+#define HP100_HUB_MACVER             0xe000	/* R: 3 bit 802.12 MAC/RMAC training */
+					     /*    protocol of repeater */
 
 /* ****************************************************************************** */
 
@@ -516,7 +516,7 @@
 /*
  *  Misc. Constants
  */
-#define HP100_LAN_100		100     /* lan_type value for VG */
+#define HP100_LAN_100		100	/* lan_type value for VG */
 #define HP100_LAN_10		10	/* lan_type value for 10BaseT */
 #define HP100_LAN_ERR		(-1)	/* lan_type value for link down */
 
@@ -528,10 +528,10 @@
  * Bus Master Data Structures  ----------------------------------------------
  */
 
-#define MAX_RX_PDL              30   /* Card limit = 31 */
-#define MAX_RX_FRAG             2    /* Don't need more... */
+#define MAX_RX_PDL              30	/* Card limit = 31 */
+#define MAX_RX_FRAG             2	/* Don't need more... */
 #define MAX_TX_PDL              29
-#define MAX_TX_FRAG             2   /* Limit = 31 */
+#define MAX_TX_FRAG             2	/* Limit = 31 */
 
 /* Define total PDL area size in bytes (should be 4096) */
 /* This is the size of kernel (dma) memory that will be allocated. */
@@ -539,16 +539,16 @@
 
 /* Ethernet Packet Sizes */
 #define MIN_ETHER_SIZE          60
-#define MAX_ETHER_SIZE          1514    /* Needed for preallocation of */
-                                        /* skb buffer when busmastering */
+#define MAX_ETHER_SIZE          1514	/* Needed for preallocation of */
+					/* skb buffer when busmastering */
 
 /* Tx or Rx Ring Entry */
 typedef struct hp100_ring {
-  u_int                     *pdl;       /* Address of PDLs PDH, dword before
-					 * this address is used for rx hdr */
-  u_int                     pdl_paddr;  /* Physical address of PDL */
-  struct sk_buff            *skb;
-  struct hp100_ring         *next;      
+	u_int *pdl;		/* Address of PDLs PDH, dword before
+				 * this address is used for rx hdr */
+	u_int pdl_paddr;	/* Physical address of PDL */
+	struct sk_buff *skb;
+	struct hp100_ring *next;
 } hp100_ring_t;
 
 
@@ -564,12 +564,12 @@
 #define HP100_SKEW_ERR		0x2000	/* 0:No, 1:Yes skew out of range */
 #define HP100_BAD_SYMBOL_ERR	0x1000	/* 0:No, 1:Yes invalid symbol received */
 #define HP100_RCV_IPM_ERR	0x0800	/* 0:No, 1:Yes pkt had an invalid packet */
-                                        /*   marker */
+					/*   marker */
 #define HP100_SYMBOL_BAL_ERR	0x0400	/* 0:No, 1:Yes symbol balance error */
 #define HP100_VG_ALN_ERR	0x0200	/* 0:No, 1:Yes non-octet received */
 #define HP100_TRUNC_ERR		0x0100	/* 0:No, 1:Yes the packet was truncated */
 #define HP100_RUNT_ERR		0x0040	/* 0:No, 1:Yes pkt length < Min Pkt */
-                                        /*   Length Reg. */
+					/*   Length Reg. */
 #define HP100_ALN_ERR		0x0010	/* 0:No, 1:Yes align error. */
 #define HP100_CRC_ERR		0x0008	/* 0:No, 1:Yes CRC occurred. */
 
@@ -616,11 +616,3 @@
 	outw( HP100_MMAP_DIS | HP100_RESET_HB, ioaddr + HP100_REG_OPTION_LSW )
 #define hp100_mem_map_disable() \
 	outw( HP100_MMAP_DIS | HP100_SET_HB, ioaddr + HP100_REG_OPTION_LSW )
-
-
-/*
- * Local variables:
- *  c-indent-level: 2
- *  tab-width: 8
- * End:
-*/
diff -u --recursive --new-file v2.4.4/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- v2.4.4/linux/drivers/net/ioc3-eth.c	Tue Mar 20 12:04:58 2001
+++ linux/drivers/net/ioc3-eth.c	Wed May 16 10:25:38 2001
@@ -402,7 +402,7 @@
 
 static struct net_device_stats *ioc3_get_stats(struct net_device *dev)
 {
-	struct ioc3_private *ip = (struct ioc3_private *) dev->priv;
+	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 
 	ip->stats.collisions += (ioc3->etcdc & ETCDC_COLLCNT_MASK);
@@ -566,7 +566,7 @@
    after the Tx thread.  */
 static void ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *)_dev;
+	struct net_device *dev = _dev;
 	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 	const u32 enabled = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO |
@@ -595,7 +595,7 @@
 static void negotiate(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct ioc3_private *ip = (struct ioc3_private *) dev->priv;
+	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 
 	mod_timer(&ip->negtimer, jiffies + 20 * HZ);
@@ -864,7 +864,7 @@
 		return -EAGAIN;
 	}
 
-	ip = (struct ioc3_private *) dev->priv;
+	ip = dev->priv;
 
 	ip->ehar_h = 0;
 	ip->ehar_l = 0;
@@ -1131,7 +1131,7 @@
 /* Provide ioctl() calls to examine the MII xcvr state. */
 static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct ioc3_private *ip = (struct ioc3_private *) dev->priv;
+	struct ioc3_private *ip = dev->priv;
 	u16 *data = (u16 *)&rq->ifr_data;
 	struct ioc3 *ioc3 = ip->regs;
 	int phy = ip->phy;
diff -u --recursive --new-file v2.4.4/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.4.4/linux/drivers/net/irda/Config.in	Fri Jan 28 19:36:22 2000
+++ linux/drivers/net/irda/Config.in	Tue May  1 16:05:00 2001
@@ -5,14 +5,6 @@
 dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
 dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
 
-comment 'FIR device drivers'
-dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR  $CONFIG_IRDA
-dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
-dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
-if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
-fi
-
 comment 'Dongle support' 
 bool 'Serial dongle support' CONFIG_DONGLE
 if [ "$CONFIG_DONGLE" != "n" ]; then
@@ -22,6 +14,15 @@
    dep_tristate '  Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
    dep_tristate '  Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
    dep_tristate '  Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA   
+fi
+
+comment 'FIR device drivers'
+dep_tristate 'IrDA USB dongles (Experimental)' CONFIG_USB_IRDA $CONFIG_IRDA $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR  $CONFIG_IRDA
+dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
+if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
 fi
 
 endmenu
diff -u --recursive --new-file v2.4.4/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.4.4/linux/drivers/net/irda/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/irda/Makefile	Tue May  1 16:05:00 2001
@@ -12,6 +12,7 @@
 
 obj-$(CONFIG_IRTTY_SIR)		+= irtty.o
 obj-$(CONFIG_IRPORT_SIR)	+= 		irport.o
+obj-$(CONFIG_USB_IRDA)		+= irda-usb.o
 obj-$(CONFIG_NSC_FIR)		+= nsc-ircc.o
 obj-$(CONFIG_WINBOND_FIR)	+= w83977af_ir.o
 obj-$(CONFIG_TOSHIBA_FIR)	+= toshoboe.o
diff -u --recursive --new-file v2.4.4/linux/drivers/net/irda/irda-usb.c linux/drivers/net/irda/irda-usb.c
--- v2.4.4/linux/drivers/net/irda/irda-usb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/irda-usb.c	Tue May  1 16:05:00 2001
@@ -0,0 +1,1176 @@
+/*****************************************************************************
+ *
+ * Filename:      irda-usb.c
+ * Version:       0.9
+ * Description:   IrDA-USB Driver
+ * Status:        Experimental 
+ * Author:        Dag Brattli <dag@brattli.net>
+ *
+ *      Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+ *      Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ *	Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+ *          
+ *	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/malloc.h>
+#include <linux/rtnetlink.h>
+#include <linux/usb.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/wrapper.h>
+
+#include <net/irda/irda-usb.h>
+
+static u32 min_turn_times[]  = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
+static int qos_mtt_bits = 0;
+
+static void irda_usb_dump_class_desc(struct irda_class_desc *desc);
+static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum);
+static void irda_usb_disconnect(struct usb_device *dev, void *ptr);
+static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
+static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev);
+static int irda_usb_open(struct irda_usb_cb *self);
+static int irda_usb_close(struct irda_usb_cb *self);
+static void irda_usb_write_bulk(struct irda_usb_cb *self, purb_t purb);
+static void write_bulk_callback(purb_t purb);
+static void irda_usb_receive(purb_t purb);
+static int irda_usb_net_init(struct net_device *dev);
+static int irda_usb_net_open(struct net_device *dev);
+static int irda_usb_net_close(struct net_device *dev);
+static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void irda_usb_net_timeout(struct net_device *dev);
+static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev);
+
+/* Master instance for each hardware found */
+#define NIRUSB 4		/* Max number of USB-IrDA dongles */
+static struct irda_usb_cb irda_instance[NIRUSB];
+
+/* These are the currently known IrDA USB dongles. Add new dongles here */
+static struct usb_device_id dongles[] = {
+	/* ACTiSYS Corp,  ACT-IR2000U FIR-USB Adapter */
+	{ USB_DEVICE(0x9c4, 0x011), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW },
+	/* KC Technology Inc.,  KC-180 USB IrDA Device */
+	{ USB_DEVICE(0x50f, 0x180), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW },
+	/* Extended Systems, Inc.,  XTNDAccess IrDA USB (ESI-9685) */
+	{ USB_DEVICE(0x8e9, 0x100), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW },
+	{ match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
+	  bInterfaceClass: USB_CLASS_APP_SPEC,
+	  bInterfaceSubClass: USB_CLASS_IRDA,
+	  driver_info: IUC_DEFAULT, },
+	{ }, /* The end */
+};
+
+MODULE_DEVICE_TABLE(usb, dongles);
+
+/*
+ * This routine is called by the USB subsystem for each new device
+ * in the system. We need to check if the device is ours, and in
+ * this case start handling it.
+ * Note : it might be worth protecting this function by a global
+ * spinlock...
+ */
+static void *irda_usb_probe(struct usb_device *dev, unsigned int ifnum,
+			   const struct usb_device_id *id)
+{
+	struct irda_usb_cb *self = NULL;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct irda_class_desc *irda_desc;
+	int capability = id->driver_info;
+	int ret;
+	int ep;
+	int i;
+
+	IRDA_DEBUG(0, "Vendor: %x, Product: %x\n", dev->descriptor.idVendor, dev->descriptor.idProduct);
+	
+	MESSAGE("IRDA-USB found at address %d\n", dev->devnum);
+
+	/* Try to cleanup all instance that have a pending disconnect
+	 * Instance will be in this state is the disconnect() occurs
+	 * before the net_close().
+	 * Jean II */
+	for (i = 0; i < NIRUSB; i++) {
+		struct irda_usb_cb *irda = &irda_instance[i];
+		if ((irda->usbdev != NULL) &&
+		    (irda->present == 0) &&
+		    (irda->netopen == 0)) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), found a zombie instance !!!\n");
+			irda_usb_disconnect(irda->usbdev, (void *) irda);
+		}
+	}
+
+	/* Find an free instance to handle this new device... */
+	self = NULL;
+	for (i = 0; i < NIRUSB; i++) {
+		if(irda_instance[i].usbdev == NULL) {
+			self = &irda_instance[i];
+			break;
+		}
+	}
+	if (self == NULL) {
+		IRDA_DEBUG(0, "Too many USB IrDA devices !!! (max = %d)\n",
+			   NIRUSB);
+		return NULL;
+	}
+
+	/* Reset the instance */
+	self->present = 0;
+	self->netopen = 0;
+
+       /* Is this really necessary? */
+	if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) {
+		err("set_configuration failed");
+		return NULL;
+	}
+	
+        /* Is this really necessary? */
+	ret = usb_set_interface(dev, ifnum, 0);
+	IRDA_DEBUG(0, "usb-irda: set interface result %d\n", ret);
+	switch (ret) {
+		case USB_ST_NOERROR:		/* 0 */
+			break;
+		case USB_ST_STALL:		/* -EPIPE = -32 */
+			usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
+			IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" );
+			break;
+		default:
+			IRDA_DEBUG(0, __FUNCTION__ "(), Unknown error %d\n", ret);
+			return NULL;
+			break;
+	}
+	
+	/* Find our endpoints */
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	endpoint = interface->endpoint;
+	ep = endpoint[0].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	if ((endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+		self->bulk_in_ep = ep;
+	else {
+		self->bulk_out_ep = ep;
+		self->bulk_out_mtu = endpoint[0].wMaxPacketSize;
+	}
+
+	ep = endpoint[1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	if ((endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+		self->bulk_in_ep = ep;
+	else {
+		self->bulk_out_ep = ep;
+		self->bulk_out_mtu = endpoint[1].wMaxPacketSize;
+	}
+
+	if (self->bulk_out_ep == 0 || self->bulk_in_ep == 0 ||
+	    endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK ||
+	    endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) 
+	{
+		ERROR(__FUNCTION__ "(), Bogus endpoints");
+		return NULL;
+	}
+
+	/* Find IrDA class descriptor */
+	irda_desc = irda_usb_find_class_desc(dev, ifnum);
+	if (irda_desc == NULL)
+		return NULL;
+	
+	self->irda_desc =  irda_desc;	
+	self->present = 1;
+	self->netopen = 0;
+	self->capability = capability;
+	self->usbdev = dev;
+	ret = irda_usb_open(self);
+	if (ret)
+		return NULL;
+
+	return self;
+}
+
+/*
+ * Function irda_usb_find_class_desc(dev, ifnum)
+ *
+ *    Returns instance of IrDA class descriptor, or NULL if not found
+ *
+ */
+static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
+{
+	struct usb_interface_descriptor *interface;
+	struct irda_class_desc *desc, *ptr;
+	int ret;
+		
+	desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
+	if (desc == NULL) 
+		return NULL;
+	memset(desc, 0, sizeof(struct irda_class_desc));
+	
+	ret = usb_get_class_descriptor(dev, ifnum, USB_DT_IRDA, 0, (void *) desc, sizeof(struct irda_class_desc));
+	IRDA_DEBUG(0, __FUNCTION__ "(), ret=%d\n", ret);
+	if (ret) {
+		WARNING("usb-irda: usb_get_class_descriptor failed (0x%x)\n", ret);  
+	}
+
+	/* Check if we found it? */
+	if (desc->bDescriptorType == USB_DT_IRDA)
+		return desc;
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), parsing extra descriptors ...\n");
+	
+	/* Check if the class descriptor is interleaved with standard descriptors */
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	ret = usb_get_extra_descriptor(interface, USB_DT_IRDA, &ptr);
+	if (ret) {
+		kfree(desc);
+		return NULL;
+	}
+	*desc = *ptr;
+#if 0
+	irda_usb_dump_class_desc(desc);
+#endif	
+	return desc;
+}
+
+/*
+ * Function usb_irda_dump_class_desc(desc)
+ *
+ *    Prints out the contents of the IrDA class descriptor
+ *
+ */
+static void irda_usb_dump_class_desc(struct irda_class_desc *desc)
+{
+	printk("bLength=%x\n", desc->bLength);
+	printk("bDescriptorType=%x\n", desc->bDescriptorType);
+	printk("bcdSpecRevision=%x\n", desc->bcdSpecRevision); 
+	printk("bmDataSize=%x\n", desc->bmDataSize);
+	printk("bmWindowSize=%x\n", desc->bmWindowSize);
+	printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime);
+	printk("wBaudRate=%x\n", desc->wBaudRate);
+	printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs);
+	printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff);
+	printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList);
+}												
+	
+static void irda_usb_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct irda_usb_cb *self = (struct irda_usb_cb *) ptr;
+	int i;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Oups ! We are not there any more */
+	self->present = 0;
+
+	/* Hum... Check if networking is still active */
+	if (self->netopen) {
+		/* Accept no more transmissions */
+		/*netif_device_detach(self->netdev);*/
+		netif_stop_queue(self->netdev);
+		/* Stop all the receive URBs */
+		for (i = 0; i < IU_MAX_RX_URBS; i++)
+			usb_unlink_urb(&(self->rx_urb[i]));
+		/* Cancel Tx and speed URB */
+		usb_unlink_urb(&(self->tx_urb));
+		usb_unlink_urb(&(self->speed_urb));
+
+		IRDA_DEBUG(0, __FUNCTION__ "(), postponing disconnect, network is still active...\n");
+		/* better not do anything just yet, usb_irda_cleanup()
+		 * will do whats needed */
+		return;
+	}
+
+	/* Cleanup the device stuff */
+	irda_usb_close(self);
+	/* No longer attached to USB bus */
+	self->usbdev = NULL;
+	IRDA_DEBUG(0, __FUNCTION__ "(), USB IrDA Disconnected\n");
+}
+
+static struct usb_driver irda_driver = {
+	name:		"irda-usb",
+	probe:		irda_usb_probe,
+	disconnect:	irda_usb_disconnect,
+	id_table:	dongles,
+};
+
+static void irda_usb_init_qos(struct irda_usb_cb *self)
+{
+	struct irda_class_desc *desc;
+
+	desc = self->irda_desc;
+	
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&self->qos);
+
+	self->qos.baud_rate.bits       = desc->wBaudRate;
+	self->qos.min_turn_time.bits   = desc->bmMinTurnaroundTime;
+	self->qos.additional_bofs.bits = desc->bmAdditionalBOFs;
+	self->qos.window_size.bits     = desc->bmWindowSize;
+	self->qos.data_size.bits       = desc->bmDataSize;
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits);
+
+	/* Don't always trust what the dongle tell us */
+	if (self->capability & IUC_SIR_ONLY)
+		self->qos.baud_rate.bits	&= 0xff;
+	if (self->capability & IUC_SMALL_PKT)
+		self->qos.data_size.bits	 = 0x07;
+	if (self->capability & IUC_NO_WINDOW)
+		self->qos.window_size.bits	 = 0x01;
+	if (self->capability & IUC_MAX_WINDOW)
+		self->qos.window_size.bits	 = 0x7f;
+	if (self->capability & IUC_MAX_XBOFS)
+		self->qos.additional_bofs.bits	 = 0x01;
+
+#if 1
+	/* Module parameter can override the rx window size */
+	if (qos_mtt_bits)
+		self->qos.min_turn_time.bits = qos_mtt_bits;
+#endif	    
+	/* 
+	 * Note : most of those values apply only for the receive path,
+	 * the transmit path will be set differently - Jean II 
+	 */
+	irda_qos_bits_to_value(&self->qos);
+
+	self->flags |= IFF_SIR;
+	if (self->qos.baud_rate.value > 115200)
+		self->flags |= IFF_MIR;
+	if (self->qos.baud_rate.value > 1152000)
+		self->flags |= IFF_FIR;
+	if (self->qos.baud_rate.value > 4000000)
+		self->flags |= IFF_VFIR;
+}
+
+static int irda_usb_open(struct irda_usb_cb *self)
+{
+	struct net_device *netdev;
+	int err;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	spin_lock_init(&self->lock);
+
+	irda_usb_init_qos(self);
+	
+	self->tx_list = hashbin_new(HB_GLOBAL);
+
+	/* Create a network device for us */
+	if (!(netdev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -1;
+	}
+	self->netdev = netdev;
+ 	netdev->priv = (void *) self;
+
+	/* Override the network functions we need to use */
+	netdev->init            = irda_usb_net_init;
+	netdev->hard_start_xmit = irda_usb_hard_xmit;
+	netdev->tx_timeout	= irda_usb_net_timeout;
+	netdev->watchdog_timeo  = 110*HZ/1000;  /* 110 ms > USB timeout */
+	netdev->open            = irda_usb_net_open;
+	netdev->stop            = irda_usb_net_close;
+	netdev->get_stats	= irda_usb_net_get_stats;
+	netdev->do_ioctl        = irda_usb_net_ioctl;
+
+	rtnl_lock();
+	err = register_netdevice(netdev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
+	MESSAGE("IrDA: Registered device %s\n", netdev->name);
+
+	return 0;
+}
+
+static int irda_usb_close(struct irda_usb_cb *self)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		self->netdev = NULL;
+		rtnl_unlock();
+	}
+	hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any);
+	
+	return 0;
+}
+
+/*
+ * Function irda_usb_build_header(self, skb, header)
+ *
+ *   Builds USB-IrDA outbound header
+ *
+ * Important note : the USB-IrDA spec 1.0 say very clearly in chapter 5.4.2.2
+ * that the setting of the link speed and xbof number in this outbound header
+ * should be applied *AFTER* the frame has been sent.
+ * Unfortunately, some devices are not compliant with that... It seems that
+ * reading the spec is far too difficult...
+ * Jean II
+ */
+static void irda_usb_build_header(struct irda_usb_cb *self, u8 *header,
+				  int force)
+{
+	/* Set the negotiated link speed */
+	if (self->new_speed != -1) {
+		/* Hum... Ugly hack :-(
+		 * Some device are not compliant with the spec and change
+		 * parameters *before* sending the frame. - Jean II
+		 */
+		if ((self->capability & IUC_SPEED_BUG) &&
+		    (!force) && (self->speed != -1)) 
+		{
+			/* No speed and xbofs change here
+			 * (we'll do it later in the write callback) */
+			IRDA_DEBUG(2, __FUNCTION__ "(), not changing speed yet\n");
+			*header = 0;
+			return;
+		}
+
+		IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed);
+		self->speed = self->new_speed;
+		self->new_speed = -1;
+
+		switch (self->speed) {
+		case 2400:
+		        *header = SPEED_2400;
+			break;
+		default:
+		case 9600:
+			*header = SPEED_9600;
+			break;
+		case 19200:
+			*header = SPEED_19200;
+			break;
+		case 38400:
+			*header = SPEED_38400;
+			break;
+		case 57600:
+		        *header = SPEED_57600;
+			break;
+		case 115200:
+		        *header = SPEED_115200;
+			break;
+		case 576000:
+		        *header = SPEED_576000;
+			break;
+		case 1152000:
+		        *header = SPEED_1152000;
+			break;
+		case 4000000:
+		        *header = SPEED_4000000;
+			self->new_xbofs = 0;
+			break;
+		}
+	} else
+		/* No change */
+		*header = 0;
+	
+	/* Set the negotiated additional XBOFS */
+	if (self->new_xbofs != -1) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs);
+		self->xbofs = self->new_xbofs;
+		self->new_xbofs = -1;
+
+		switch (self->xbofs) {
+		case 48:
+			*header |= 0x10;
+			break;
+		case 28:
+		case 24: /* USB spec 1.0 says 24 */
+			*header |= 0x20;
+			break;
+		default:
+		case 12:
+			*header |= 0x30;
+			break;
+		case 5: /* Bug in IrLAP spec? (should be 6) */
+		case 6:
+			*header |= 0x40;
+			break;
+		case 3:
+			*header |= 0x50;
+			break;
+		case 2:
+			*header |= 0x60;
+			break;
+		case 1:
+			*header |= 0x70;
+			break;
+		case 0:
+			*header |= 0x80;
+			break;
+		}
+	}
+}
+
+static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	purb_t purb;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, xbofs=%d\n",
+		   self->new_speed, self->new_xbofs);
+
+	purb = &self->speed_urb;
+	if (purb->status != USB_ST_NOERROR) {
+		WARNING(__FUNCTION__ "(), URB still in use!\n");
+		return;
+	}
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Allocate the fake frame */
+	skb = dev_alloc_skb(IRDA_USB_SPEED_MTU);
+	if (!skb)
+		return;
+	((struct irda_skb_cb *)skb->cb)->context = self;
+
+	/* Set the new speed and xbofs in this fake frame */
+	irda_usb_build_header(self, skb_put(skb, USB_IRDA_HEADER), 1);
+
+	/* Submit the 0 length IrDA frame to trigger new speed settings */
+        FILL_BULK_URB(purb, self->usbdev,
+		      usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
+                      skb->data, IRDA_USB_MAX_MTU,
+                      write_bulk_callback, skb);
+	purb->transfer_buffer_length = skb->len;
+	purb->transfer_flags |= USB_QUEUE_BULK;
+	purb->timeout = MSECS_TO_JIFFIES(100);
+
+	if ((ret = usb_submit_urb(purb))) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), failed Speed URB\n");
+	}
+	spin_unlock_irqrestore(&self->lock, flags);
+}
+
+static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct irda_usb_cb *self = netdev->priv;
+	purb_t purb = &self->tx_urb;
+	unsigned long flags;
+	s32 speed;
+	s16 xbofs;
+	int mtt;
+
+	/* Check if the device is still there */
+	if ((!self) || (!self->present)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n");
+		return 1;	/* Failed */
+	}
+
+	netif_stop_queue(netdev);
+
+	/* Check if we need to change the number of xbofs */
+        xbofs = irda_get_next_xbofs(skb);
+        if ((xbofs != self->xbofs) && (xbofs != -1)) {
+		self->new_xbofs = xbofs;
+	}
+
+        /* Check if we need to change the speed */
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->speed) && (speed != -1)) {
+		/* Set the desired speed */
+		self->new_speed = speed;
+
+		/* Check for empty frame */
+		if (!skb->len) {
+			/* IrLAP send us an empty frame to make us change the
+			 * speed. Changing speed with the USB adapter is in
+			 * fact sending an empty frame to the adapter, so we
+			 * could just let the present function do its job.
+			 * However, we would wait for min turn time,
+			 * do an extra memcpy and increment packet counters...
+			 * Jean II */
+			irda_usb_change_speed_xbofs(self);
+			netdev->trans_start = jiffies;
+			dev_kfree_skb(skb);
+			/* Will netif_wake_queue() in callback */
+			return 0;
+		}
+	}
+
+	if (purb->status != USB_ST_NOERROR) {
+		WARNING(__FUNCTION__ "(), URB still in use!\n");
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	/* Make room for IrDA-USB header */
+	if (skb_cow(skb, USB_IRDA_HEADER)) {
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	spin_lock_irqsave(&self->lock, flags);
+	
+	/* Change setting for next frame */
+	irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0);
+
+	/* FIXME: Make macro out of this one */
+	((struct irda_skb_cb *)skb->cb)->context = self;
+
+        FILL_BULK_URB(purb, self->usbdev, 
+		      usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
+                      skb->data, IRDA_USB_MAX_MTU,
+                      write_bulk_callback, skb);
+	purb->transfer_buffer_length = skb->len;
+	purb->transfer_flags |= USB_QUEUE_BULK;
+	purb->timeout = MSECS_TO_JIFFIES(100);
+	
+	/* Generate min turn time */
+	mtt = irda_get_mtt(skb);
+	if (mtt) {
+		int diff;
+		get_fast_time(&self->now);
+		diff = self->now.tv_usec - self->stamp.tv_usec;
+		if (diff < 0)
+			diff += 1000000;
+
+                /* Check if the mtt is larger than the time we have
+		 * already used by all the protocol processing
+		 */
+		if (mtt > diff) {
+			mtt -= diff;
+			if (mtt > 1000) {
+				/* 
+				* FIXME: can we do better than this? Maybe call
+				* a function which sends a frame to a non 
+				* existing device, or change the speed to the 
+				* current one a number of times just to burn 
+				* time a better way.
+				*/															
+				mdelay(mtt/1000);
+				irda_usb_write_bulk(self, purb);
+				goto out;	
+			} else
+				udelay(mtt);
+		}
+	}	
+	irda_usb_write_bulk(self, purb);
+out:
+	spin_unlock_irqrestore(&self->lock, flags);
+	
+	return 0;
+}
+
+static void irda_usb_write_bulk(struct irda_usb_cb *self, purb_t purb)
+{
+	int len = purb->transfer_buffer_length; 
+	int res;
+	
+	if ((res = usb_submit_urb(purb))) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), failed Tx URB\n");
+		self->stats.tx_errors++;
+		netif_start_queue(self->netdev);
+
+		return;
+	}
+	self->stats.tx_packets++;
+        self->stats.tx_bytes += len;
+	self->netdev->trans_start = jiffies;
+	
+	/* Send empty frame if size if a multiple of the USB max packet size */
+	ASSERT(self->bulk_out_mtu == 64, return;);
+	if ((len % self->bulk_out_mtu) == 0) {
+		/* Borrow speed urb */
+		purb = &self->speed_urb;
+		FILL_BULK_URB(purb, self->usbdev,
+			      usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
+			      self, /* Anything not on the stack will do */
+			      IRDA_USB_MAX_MTU, NULL, NULL);
+		purb->transfer_buffer_length = 0;
+		purb->transfer_flags |= USB_QUEUE_BULK;
+		res = usb_submit_urb(purb);
+	}
+}
+
+/*
+ * Note : this function will be called with both tx_urb and speed_urb...
+ */
+static void write_bulk_callback(purb_t purb)
+{
+	struct sk_buff *skb = purb->context;
+	struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context;
+	
+	/* We should always have a context */
+	if (self == NULL) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Bug : self == NULL\n");
+		return;
+	}
+
+	/* urb is now available */
+	purb->status = USB_ST_NOERROR;
+
+	dev_kfree_skb_any(skb);
+	purb->context = NULL;
+
+        /* Check for timeout and other USB nasties */
+        if (purb->status != USB_ST_NOERROR) {
+	        /* I get a lot of -ECONNABORTED = -103 here - Jean II */
+	        WARNING(__FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", 
+			purb->status, purb->transfer_flags);
+	        /* Don't do anything here, that might confuse the USB layer,
+	         * and we could go in recursion and blow the kernel stack...
+	         * Instead, we will wait for irda_usb_net_timeout(), the
+	         * network layer watchdog, to fix the situation.
+	         * Jean II */
+	        /* A reset of the dongle might be welcomed here - Jean II */
+	        return;
+	}
+													
+
+	/* URB is now available */
+	purb->status = USB_ST_NOERROR;
+
+	/* If the network is closed, stop everything */
+	if ((!self->netopen) || (!self->present)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone...\n");
+		return;
+	}
+
+	/* If we need to change the speed or xbofs, do it now */
+	if ((self->new_speed != -1) || (self->new_xbofs != -1)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Changing speed now...\n");
+		irda_usb_change_speed_xbofs(self);
+	} else {
+		/* Otherwise, allow the stack to send more packets */
+		netif_wake_queue(self->netdev);
+	}
+}
+
+static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, purb_t purb)
+{
+	struct irda_skb_cb *cb;
+	int ret;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	/* Check that we have an urb */
+	if (!purb) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Bug : purb == NULL\n");
+		return;
+	}
+
+	/* Allocate new skb if it has not been recycled */
+	if (!skb) {
+		skb = dev_alloc_skb(IRDA_USB_MAX_MTU + 1);
+		if (!skb) {
+			/* If this ever happen, we are in deep s***.
+			 * Basically, the Rx path will stop... */
+			IRDA_DEBUG(0, __FUNCTION__ "(), Failed to allocate Rx skb\n");
+			return;
+		}
+	} else  {
+		/* Reset recycled skb */
+		skb->data = skb->tail = skb->head;
+		skb->len = 0;
+	}
+	/* Make sure IP header get aligned (IrDA header is 5 bytes ) */
+	skb_reserve(skb, 1);
+
+	/* Save ourselves */
+	cb = (struct irda_skb_cb *) skb->cb;
+	cb->context = self;
+
+	/* Reinitialize URB */
+	FILL_BULK_URB(purb, self->usbdev, 
+		      usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep), 
+		      skb->data, skb->truesize,
+                      irda_usb_receive, skb);
+	purb->transfer_flags |= USB_QUEUE_BULK;
+	purb->status = USB_ST_NOERROR;
+	purb->next = NULL; /* Make sure we don't auto resubmit */ 
+	
+	ret = usb_submit_urb(purb);
+	if (ret) {
+		/* If this ever happen, we are in deep s***.
+		 * Basically, the Rx path will stop... */
+		IRDA_DEBUG(0, __FUNCTION__ "(), Failed to submit Rx URB %d\n", ret);
+	}
+}
+
+/*
+ * Function irda_usb_receive(purb)
+ *
+ *     Called by the USB subsystem when a frame has been received
+ *
+ */
+static void irda_usb_receive(purb_t purb) 
+{
+	struct sk_buff *skb = (struct sk_buff *) purb->context;
+	struct irda_usb_cb *self; 
+	struct irda_skb_cb *cb;
+	struct sk_buff *new;
+	
+	/* Find ourselves */
+	cb = (struct irda_skb_cb *) skb->cb;
+	ASSERT(cb != NULL, return;);
+	self = (struct irda_usb_cb *) cb->context;
+	ASSERT(self != NULL, return;);
+
+	/* If the network is closed or the device gone, stop everything */
+	if ((!self->netopen) || (!self->present)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone!\n");
+		/* Don't re-submit the URB : will stall the Rx path */
+		return;
+	}
+	
+	/* Check the status */
+	if (purb->status != USB_ST_NOERROR) {
+		switch (purb->status) {
+		case USB_ST_CRC:		/* -EILSEQ */
+			self->stats.rx_errors++;
+			self->stats.rx_crc_errors++;	
+			break;
+		case -ECONNRESET:
+		        WARNING(__FUNCTION__ "(), Connection Reset !!!\n");
+			/* uhci_cleanup_unlink() is going to kill the Rx
+			 * URB just after we return. No problem, at this
+			 * point the URB will be idle ;-) - Jean II */
+			break;
+		default:
+			WARNING(__FUNCTION__ "(), RX status %d\n", purb->status);
+			break;
+		}
+		goto done;
+	}
+
+	/* Check for empty frames */
+	if (purb->actual_length <= USB_IRDA_HEADER) {
+		WARNING(__FUNCTION__ "(), empty frame!\n");
+		goto done;
+	}
+
+	/*  
+	 * Remember the time we received this frame, so we can
+	 * reduce the min turn time a bit since we will know
+	 * how much time we have used for protocol processing
+	 */
+        get_fast_time(&self->stamp);
+
+	/* Fix skb, and remove USB-IrDA header */
+	skb_put(skb, purb->actual_length);
+	skb_pull(skb, USB_IRDA_HEADER);
+
+	/* Don't waste a lot of memory on small IrDA frames */
+	if (skb->len < RX_COPY_THRESHOLD) {
+		new = dev_alloc_skb(skb->len+1);
+		if (!new) {
+			self->stats.rx_dropped++;
+			goto done;  
+		}
+
+		/* Make sure IP header get aligned (IrDA header is 5 bytes) */
+		skb_reserve(new, 1);
+		
+		/* Copy packet, so we can recycle the original */
+		memcpy(skb_put(new, skb->len), skb->data, skb->len);
+		/* We will cleanup the skb in irda_usb_submit */
+	} else {
+		/* Deliver the original skb */
+		new = skb;
+		skb = NULL;
+	}
+	
+	self->stats.rx_bytes += new->len;
+	self->stats.rx_packets++;
+
+	/* Ask the networking layer to queue the packet for the IrDA stack */
+        new->dev = self->netdev;
+        new->mac.raw  = new->data;
+        new->protocol = htons(ETH_P_IRDA);
+        netif_rx(new);
+done:
+	/* Recycle Rx URB (and possible the skb as well) */
+	irda_usb_submit(self, skb, self->rx_idle_urb);
+
+        /* Recycle Rx URB : Now, the idle URB is the present one */
+	self->rx_idle_urb = purb;
+	purb->context = NULL;
+	/* Prevent the USB layer playing games with our URBs */
+	purb->status = -ENOENT;
+}
+
+static int irda_usb_net_init(struct net_device *dev)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	
+	/* Set up to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function irda_usb_net_open (dev)
+ *
+ *    Network device is taken up. Usually this is done by "ifconfig irda0 up" 
+ *   
+ * Note : don't mess with self->netopen - Jean II
+ */
+static int irda_usb_net_open(struct net_device *netdev)
+{
+	struct irda_usb_cb *self;
+	int i;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(netdev != NULL, return -1;);
+	self = (struct irda_usb_cb *) netdev->priv;
+	ASSERT(self != NULL, return -1;);
+
+	/* Can only open the device if it's there */
+	if(!self->present) {
+		WARNING(__FUNCTION__ "(), device not present!\n");
+		return -1;
+	}
+
+	/* Initialise default speed and xbofs value
+	 * (IrLAP will change that soon) */
+	self->speed = -1;
+	self->xbofs = -1;
+	self->new_speed = -1;
+	self->new_xbofs = -1;
+
+	/* To do *before* submitting Rx urbs and starting net Tx queue
+	 * Jean II */
+	self->netopen = 1;
+
+	/* 
+	 * Now that everything should be initialized properly,
+	 * Open new IrLAP layer instance to take care of us...
+	 * Note : will send immediately a speed change...
+	 */
+	self->irlap = irlap_open(netdev, &self->qos);
+	ASSERT(self->irlap != NULL, return -1;);
+
+	/* Allow IrLAP to send data to us */
+	netif_start_queue(netdev);
+
+	/* Now that we can pass data to IrLAP, allow the USB layer
+	 * to send us some data... */
+	for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++)
+		irda_usb_submit(self, NULL, &(self->rx_urb[i]));
+	/* Note : we submit all the Rx URB except for one - Jean II */
+	self->rx_idle_urb = &(self->rx_urb[IU_MAX_ACTIVE_RX_URBS]);
+	self->rx_idle_urb->context = NULL;
+
+	/* Ready to play !!! */
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+/*
+ * Function irda_usb_net_close (self)
+ *
+ *    Network device is taken down. Usually this is done by 
+ *    "ifconfig irda0 down" 
+ */
+static int irda_usb_net_close(struct net_device *netdev)
+{
+	struct irda_usb_cb *self;
+	int i;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(netdev != NULL, return -1;);
+	self = (struct irda_usb_cb *) netdev->priv;
+	ASSERT(self != NULL, return -1;);
+
+	/* Clear this flag *before* unlinking the urbs and *before*
+	 * stopping the network Tx queue - Jean II */
+	self->netopen = 0;
+
+	/* Stop network Tx queue */
+	netif_stop_queue(netdev);
+
+	/* Deallocate all the Rx path buffers (URBs and skb) */
+	for (i = 0; i < IU_MAX_RX_URBS; i++) {
+		purb_t purb = &(self->rx_urb[i]);
+		struct sk_buff *skb = (struct sk_buff *) purb->context;
+		/* Cancel the receive command */
+		usb_unlink_urb(purb);
+		/* The skb is ours, free it */
+		if (skb) {
+			dev_kfree_skb(skb);
+			purb->context = NULL;
+		}
+	}
+	/* Cancel Tx and speed URB */
+	usb_unlink_urb(&self->tx_urb);
+	usb_unlink_urb(&self->speed_urb);
+	
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static void irda_usb_net_timeout(struct net_device *netdev)
+{
+	struct irda_usb_cb *self = netdev->priv;
+	int done = 0;	/* If we have made any progress */
+	purb_t purb;
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n");
+
+	if (!self || !self->present) {
+		WARNING(__FUNCTION__ "(), device not present!\n");
+		netif_stop_queue(netdev);
+		return;
+	}
+	WARNING("%s: Tx timed out\n", netdev->name);
+
+	/* Check Tx URB */
+	purb = &self->tx_urb;
+	switch (purb->status) {
+		case -ECONNABORTED:	/* Can't find proper USB_ST_* code */
+			purb->status = USB_ST_NOERROR;
+			netif_wake_queue(self->netdev);
+			done = 1;
+			break;
+		case USB_ST_URB_PENDING:	/* -EINPROGRESS == -115 */
+			usb_unlink_urb(purb);
+			done = 1;
+			break;
+		default:
+			break;
+	}
+	/* Check speed URB */
+	purb = &self->speed_urb;
+	switch (purb->status) {
+		case -ECONNABORTED:	/* Can't find proper USB_ST_* code */
+			purb->status = USB_ST_NOERROR;
+			netif_wake_queue(self->netdev);
+			done = 1;
+			break;
+		case USB_ST_URB_PENDING:	/* -EINPROGRESS */
+			usb_unlink_urb(purb);
+			done = 1;
+			break;
+		default:
+			break;
+	}
+	/* Maybe we need a reset */
+	/* if(done == 0) */
+}
+
+static int irda_usb_is_receiving(struct irda_usb_cb *self)
+{
+	return 0; /* For now */
+}
+
+static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct irda_usb_cb *self;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+	self = dev->priv;
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+
+	/* Check if the device is still there */
+	if (!self->present)
+		return -EFAULT;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		/* Set the desired speed */
+		self->new_speed = irq->ifr_baudrate;
+		irda_usb_change_speed_xbofs(self);
+		/* Note : will spinlock in above function */
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = irda_usb_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	return ret;
+}
+
+static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev)
+{
+	struct irda_usb_cb *self = dev->priv;
+	return &self->stats;
+}
+
+int __init usb_irda_init(void)
+{
+	if (usb_register(&irda_driver) < 0)
+		return -1;
+
+	MESSAGE("USB IrDA support registered\n");
+	return 0;
+}
+module_init(usb_irda_init);
+
+void __exit usb_irda_cleanup(void)
+{
+	struct irda_usb_cb *irda = NULL;
+	int i;
+
+	/* Find zombie instances and kill them... */
+	for (i = 0; i < NIRUSB; i++) {
+		irda = &irda_instance[i];
+		/* If the Device is zombie */
+		if((irda->usbdev != NULL) && (irda->present == 0)) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), disconnect zombie now !\n");
+			irda_usb_disconnect(irda->usbdev, (void *) irda);
+		}
+	}
+	/* Deregister the driver and remove all pending instances */
+	usb_deregister(&irda_driver);
+}
+module_exit(usb_irda_cleanup);
+
+MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
+MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); 
+
+
+
diff -u --recursive --new-file v2.4.4/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c
--- v2.4.4/linux/drivers/net/irda/nsc-ircc.c	Tue Mar 20 12:04:59 2001
+++ linux/drivers/net/irda/nsc-ircc.c	Tue May  1 16:05:00 2001
@@ -251,9 +251,14 @@
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
+	MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
+		info->cfg_base);
+
 	if ((nsc_ircc_setup(info)) == -1)
 		return -1;
 
+	MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+
 	/* Allocate new instance of the driver */
 	self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
 	if (self == NULL) {
@@ -315,8 +320,8 @@
 	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
 					      GFP_KERNEL|GFP_DMA);
 	if (self->tx_buff.head == NULL) {
-		kfree(self);
 		kfree(self->rx_buff.head);
+		kfree(self);
 		return -ENOMEM;
 	}
 	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
@@ -699,8 +704,6 @@
 		ERROR("%s, Wrong chip version %02x\n", driver_name, version);
 		return -1;
 	}
-	MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, 
-		info->cfg_base);
 
 	/* Switch to advanced mode */
 	switch_bank(iobase, BANK2);
@@ -729,8 +732,6 @@
 	outb(0x0d, iobase+2); /* Set SIR pulse width to 1.6us */
 	outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
 
-	MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
-
 	/* Enable receive interrupts */
 	switch_bank(iobase, BANK0);
 	outb(IER_RXHDL_IE, iobase+IER);
@@ -1858,7 +1859,7 @@
 	if (request_dma(self->io.dma, dev->name)) {
 		WARNING("%s, unable to allocate dma=%d\n", driver_name, 
 			self->io.dma);
-		free_irq(self->io.irq, self);
+		free_irq(self->io.irq, dev);
 		return -EAGAIN;
 	}
 	
@@ -2008,18 +2009,10 @@
 
 static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
 {
-	int iobase;
-
 	if (!self->io.suspended)
 		return;
 
-	iobase = self->io.fir_base;
-
-	/* Switch to advanced mode */
-	switch_bank(iobase, BANK2);
-	outb(ECR1_EXT_SL, iobase+ECR1);
-	switch_bank(iobase, BANK0);
-
+	nsc_ircc_setup(&self->io);
 	nsc_ircc_net_open(self->netdev);
 	
 	MESSAGE("%s, Waking up\n", driver_name);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.4.4/linux/drivers/net/irda/toshoboe.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/irda/toshoboe.c	Tue May  1 16:05:00 2001
@@ -81,10 +81,18 @@
 
 #include <net/irda/toshoboe.h>
 
-static char *driver_name = "toshoboe";
+#define PCI_DEVICE_ID_FIR701b  0x0d01
 
-static struct toshoboe_cb *dev_self[NSELFS + 1] =
-{NULL, NULL, NULL, NULL, NULL};
+static struct pci_device_id toshoboe_pci_tbl[] __initdata = {
+	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701b, PCI_ANY_ID, PCI_ANY_ID, },
+	{ }			/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl);
+
+static const char *driver_name = "toshoboe";
+
+static struct toshoboe_cb *dev_self[NSELFS + 1];
 
 static int max_baud = 4000000;
 
@@ -191,8 +199,8 @@
   outb_p (OBOE_NTR_VAL, OBOE_NTR);
   outb_p (0xf0, OBOE_REG_D);
   outb_p (0xff, OBOE_ISR);
-  outb_p (0x0f, OBOE_REG_1A);
-  outb_p (0xff, OBOE_REG_1B);
+  outb_p (0x0f, OBOE_REG_1B);
+  outb_p (0xff, OBOE_REG_1A);
 
 
   physaddr = virt_to_bus (self->taskfile);
@@ -608,18 +616,21 @@
 	/* Disable interrupts & save flags */
 	save_flags(flags);
 	cli();
-	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			goto out;
+		}
 		/* toshoboe_setbaud(self, irq->ifr_baudrate); */
                 /* Just change speed once - inserted by Paul Bristow */
 	        self->new_speed = irq->ifr_baudrate;
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			goto out;
+		}
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
@@ -628,9 +639,8 @@
 	default:
 		ret = -EOPNOTSUPP;
 	}
-	
+out:
 	restore_flags(flags);
-	
 	return ret;
 }
 
@@ -712,6 +722,9 @@
       return -ENOMEM;
     }
 
+  if ((err=pci_enable_device(pci_dev)))
+	  return err;
+
   self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
 
   if (self == NULL)
@@ -898,7 +911,7 @@
 /*FIXME: can't sleep here wait one second */
 
   while ((i--) && (self->txpending))
-    mdelay (100);
+    udelay (100);
 
   toshoboe_stopchip (self);
   toshoboe_disablebm (self);
@@ -978,6 +991,24 @@
 
     }
   while (pci_dev);
+
+  if (!found) do
+    {
+      pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA,
+                                 PCI_DEVICE_ID_FIR701b, pci_dev);
+      if (pci_dev)
+        {
+          printk (KERN_WARNING "ToshOboe: Found 701b chip at 0x%0lx irq %d\n",
+		  pci_dev->resource[0].start,
+                  pci_dev->irq);
+
+          if (!toshoboe_open (pci_dev))
+	      found++;
+        }
+
+    }
+  while (pci_dev);
+
 
 
   if (found)
diff -u --recursive --new-file v2.4.4/linux/drivers/net/mace.c linux/drivers/net/mace.c
--- v2.4.4/linux/drivers/net/mace.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/mace.c	Sun May 20 12:11:38 2001
@@ -5,6 +5,7 @@
  * Copyright (C) 1996 Paul Mackerras.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
@@ -21,6 +22,9 @@
 #include "mace.h"
 
 static struct net_device *mace_devs;
+static int port_aaui = -1;
+
+MODULE_PARM(port_aaui, "i");
 
 #define N_RX_RING	8
 #define N_TX_RING	6
@@ -53,6 +57,7 @@
     struct net_device_stats stats;
     struct timer_list tx_timeout;
     int timeout_active;
+    int port_aaui;
     struct net_device *next_mace;
 };
 
@@ -178,6 +183,21 @@
 	init_timer(&mp->tx_timeout);
 	mp->timeout_active = 0;
 
+	if (port_aaui >= 0)
+		mp->port_aaui = port_aaui;
+	else {
+		/* Apple Network Server uses the AAUI port */
+		if (machine_is_compatible("AAPL,ShinerESB"))
+			mp->port_aaui = 1;
+		else {
+#ifdef CONFIG_MACE_AAUI_PORT
+			mp->port_aaui = 1;
+#else
+			mp->port_aaui = 0;
+#endif			
+		}
+	}
+
 	dev->open = mace_open;
 	dev->stop = mace_close;
 	dev->hard_start_xmit = mace_xmit_start;
@@ -261,7 +281,10 @@
     /* done changing address */
     out_8(&mb->iac, 0);
 
-    out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
+    if (mp->port_aaui)
+    	out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
+    else
+    	out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
 }
 
 static void __mace_set_address(struct net_device *dev, void *addr)
diff -u --recursive --new-file v2.4.4/linux/drivers/net/natsemi.c linux/drivers/net/natsemi.c
--- v2.4.4/linux/drivers/net/natsemi.c	Fri Apr 20 11:54:23 2001
+++ linux/drivers/net/natsemi.c	Sat May 19 18:02:45 2001
@@ -34,9 +34,30 @@
 		- Clean up PCI enable (davej)
 	Version 1.0.4:
 		- Merge Donald Becker's natsemi.c version 1.07
+	Version 1.0.5:
+		- { fill me in }
+	Version 1.0.6:
+		* ethtool support (jgarzik)
+		* Proper initialization of the card (which sometimes
+		fails to occur and leaves the card in a non-functional
+		state). (uzi)
+
+		* Some documented register settings to optimize some
+		of the 100Mbit autodetection circuitry in rev C cards. (uzi)
+
+		* Polling of the PHY intr for stuff like link state
+		change and auto- negotiation to finally work properly. (uzi)
+
+		* One-liner removal of a duplicate declaration of
+		netdev_error(). (uzi)
 
 */
 
+#define DRV_NAME	"natsemi"
+#define DRV_VERSION	"1.07+LK1.0.6"
+#define DRV_RELDATE	"May 18, 2001"
+
+
 /* Updated to recommendations in pci-skeleton v2.03. */
 
 /* Automatically extracted configuration info:
@@ -98,8 +119,6 @@
 #error You must compile this driver with "-O".
 #endif
 
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -114,15 +133,17 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/ethtool.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "natsemi.c:v1.07 1/9/2001  Written by Donald Becker <becker@scyld.com>\n"
+KERN_INFO DRV_NAME ".c:v1.07 1/9/2001  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO "  http://www.scyld.com/network/natsemi.html\n"
-KERN_INFO "  (unofficial 2.4.x kernel port, version 1.0.5, April 17, 2001 Jeff Garzik, Tjeerd Mulder)\n";
+KERN_INFO "  (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "  Jeff Garzik, Tjeerd Mulder)\n";
 
 /* Condensed operations for readability. */
 #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
@@ -257,9 +278,12 @@
 	TxRingPtr=0x20, TxConfig=0x24,
 	RxRingPtr=0x30, RxConfig=0x34, ClkRun=0x3C,
 	WOLCmd=0x40, PauseCmd=0x44, RxFilterAddr=0x48, RxFilterData=0x4C,
-	BootRomAddr=0x50, BootRomData=0x54, StatsCtrl=0x5C, StatsData=0x60,
-	RxPktErrs=0x60, RxMissed=0x68, RxCRCErrs=0x64,
-	PCIPM = 0x44,
+	BootRomAddr=0x50, BootRomData=0x54, SiliconRev=0x58, StatsCtrl=0x5C,
+	StatsData=0x60, RxPktErrs=0x60, RxMissed=0x68, RxCRCErrs=0x64,
+	PCIPM=0x44, PhyStatus=0xC0, MIntrCtrl=0xC4, MIntrStatus=0xC8,
+
+	/* These are from the spec, around page 78... on a separate table. */
+	PGSEL=0xCC, PMDCSR=0xE4, TSTDAT=0xFC, DSPCFG=0xF4, SDCFG=0x8C
 };
 
 /* Bit in ChipCmd. */
@@ -353,10 +377,9 @@
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
 static void netdev_error(struct net_device *dev, int intr_status);
 static int  netdev_rx(struct net_device *dev);
-static void netdev_error(struct net_device *dev, int intr_status);
 static void set_rx_mode(struct net_device *dev);
 static struct net_device_stats *get_stats(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  netdev_close(struct net_device *dev);
 
 
@@ -468,7 +491,7 @@
 	dev->stop = &netdev_close;
 	dev->get_stats = &get_stats;
 	dev->set_multicast_list = &set_rx_mode;
-	dev->do_ioctl = &mii_ioctl;
+	dev->do_ioctl = &netdev_ioctl;
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -582,7 +605,26 @@
 	long ioaddr = dev->base_addr;
 	int i;
 
-	/* Do we need to reset the chip??? */
+	/* Reset the chip, just in case. */
+	writel(ChipReset, ioaddr + ChipCmd);
+
+	/* On page 78 of the spec, they recommend some settings for "optimum
+	   performance" to be done in sequence.  These settings optimize some
+	   of the 100Mbit autodetection circuitry.  Also, we only want to do
+	   this for rev C of the chip.
+	*/
+	if (readl(ioaddr + SiliconRev) == 0x302) {
+		writew(0x0001, ioaddr + PGSEL);
+		writew(0x189C, ioaddr + PMDCSR);
+		writew(0x0000, ioaddr + TSTDAT);
+		writew(0x5040, ioaddr + DSPCFG);
+		writew(0x008C, ioaddr + SDCFG);
+	}
+
+	/* Enable PHY Specific event based interrupts.  Link state change
+	   and Auto-Negotiation Completion are among the affected.
+	*/
+	writew(0x0002, ioaddr + MIntrCtrl);
 
 	i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
 	if (i) return i;
@@ -818,14 +860,6 @@
 	long ioaddr;
 	int boguscnt = max_interrupt_work;
 
-#ifndef final_version			/* Can never occur. */
-	if (dev == NULL) {
-		printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown "
-				"device.\n", irq);
-		return;
-	}
-#endif
-
 	ioaddr = dev->base_addr;
 	np = dev->priv;
 
@@ -853,9 +887,7 @@
 				break;
 			if (np->tx_ring[entry].cmd_status & cpu_to_le32(0x08000000)) {
 				np->stats.tx_packets++;
-#if LINUX_VERSION_CODE > 0x20127
 				np->stats.tx_bytes += np->tx_skbuff[entry]->len;
-#endif
 			} else {			/* Various Tx errors */
 				int tx_status = le32_to_cpu(np->tx_ring[entry].cmd_status);
 				if (tx_status & 0x04010000) np->stats.tx_aborted_errors++;
@@ -891,18 +923,6 @@
 	if (debug > 3)
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, (int)readl(ioaddr + IntrStatus));
-
-#ifndef final_version
-	/* Code that should never be run!  Perhaps remove after testing.. */
-	{
-		static int stopit = 10;
-		if (!netif_running(dev)  &&  --stopit < 0) {
-			printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
-				   dev->name);
-			free_irq(irq, dev);
-		}
-	}
-#endif
 }
 
 /* This routine is logically part of the interrupt handler, but separated
@@ -966,27 +986,12 @@
 						   skb->head, temp);
 #endif
 			}
-#ifndef final_version				/* Remove after testing. */
-			/* You will want this info for the initial debug. */
-			if (debug > 5)
-				printk(KERN_DEBUG "  Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:"
-					   "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x "
-					   "%d.%d.%d.%d.\n",
-					   skb->data[0], skb->data[1], skb->data[2], skb->data[3],
-					   skb->data[4], skb->data[5], skb->data[6], skb->data[7],
-					   skb->data[8], skb->data[9], skb->data[10],
-					   skb->data[11], skb->data[12], skb->data[13],
-					   skb->data[14], skb->data[15], skb->data[16],
-					   skb->data[17]);
-#endif
 			skb->protocol = eth_type_trans(skb, dev);
 			/* W/ hardware checksum: skb->ip_summed = CHECKSUM_UNNECESSARY; */
 			netif_rx(skb);
 			dev->last_rx = jiffies;
 			np->stats.rx_packets++;
-#if LINUX_VERSION_CODE > 0x20127
 			np->stats.rx_bytes += pkt_len;
-#endif
 		}
 		entry = (++np->cur_rx) % RX_RING_SIZE;
 		np->rx_head_desc = &np->rx_ring[entry];
@@ -1023,6 +1028,8 @@
 		printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising"
 			   " %4.4x  partner %4.4x.\n", dev->name,
 			   (int)readl(ioaddr + 0x90), (int)readl(ioaddr + 0x94));
+		/* read MII int status to clear the flag */
+		readw(ioaddr + MIntrStatus);
 		check_duplex(dev);
 	}
 	if (intr_status & StatsMax) {
@@ -1124,12 +1131,38 @@
 	np->cur_rx_mode = rx_mode;
 }
 
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+		
+	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+		return -EFAULT;
+
+        switch (ethcmd) {
+        case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		strcpy(info.driver, DRV_NAME);
+		strcpy(info.version, DRV_VERSION);
+		strcpy(info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+
+        }
+	
+	return -EOPNOTSUPP;
+}
+
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
 	u16 *data = (u16 *)&rq->ifr_data;
 
 	switch(cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
 		data[0] = 1;
 		/* Fall Through */
@@ -1209,9 +1242,6 @@
 		np->rx_ring[i].cmd_status = 0;
 		np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
 		if (np->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
-			np->rx_skbuff[i]->free = 1;
-#endif
 			dev_kfree_skb(np->rx_skbuff[i]);
 		}
 		np->rx_skbuff[i] = 0;
@@ -1243,7 +1273,7 @@
 }
 
 static struct pci_driver natsemi_driver = {
-	name:		"natsemi",
+	name:		DRV_NAME,
 	id_table:	natsemi_pci_tbl,
 	probe:		natsemi_probe1,
 	remove:		natsemi_remove1,
diff -u --recursive --new-file v2.4.4/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.4.4/linux/drivers/net/net_init.c	Wed Apr 18 14:40:06 2001
+++ linux/drivers/net/net_init.c	Wed May 16 10:25:39 2001
@@ -205,11 +205,12 @@
 }
 
 /**
- * alloc_etherdev - Register ethernet device
+ * alloc_etherdev - Allocates and sets up an ethernet device
  * @sizeof_priv: Size of additional driver-private structure to be allocated
  *	for this ethernet device
  *
- * Fill in the fields of the device structure with ethernet-generic values.
+ * Fill in the fields of the device structure with ethernet-generic
+ * values. Basically does everything except registering the device.
  *
  * Constructs a new net device, complete with a private data area of
  * size @sizeof_priv.  A 32-byte (not bit) alignment is enforced for
diff -u --recursive --new-file v2.4.4/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in
--- v2.4.4/linux/drivers/net/pcmcia/Config.in	Sun Mar 25 18:24:31 2001
+++ linux/drivers/net/pcmcia/Config.in	Mon May  7 19:42:14 2001
@@ -26,7 +26,6 @@
    bool '  Pcmcia Wireless LAN' CONFIG_NET_PCMCIA_RADIO
    if [ "$CONFIG_NET_PCMCIA_RADIO" = "y" ]; then
       dep_tristate '    Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA
-      dep_tristate '    Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)' CONFIG_PCMCIA_HERMES $CONFIG_PCMCIA
       dep_tristate '    Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA
       dep_tristate '    AT&T/Lucent Wavelan wireless support' CONFIG_PCMCIA_WAVELAN $CONFIG_PCMCIA
       dep_tristate '    Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA
diff -u --recursive --new-file v2.4.4/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile
--- v2.4.4/linux/drivers/net/pcmcia/Makefile	Sun Mar 25 18:24:31 2001
+++ linux/drivers/net/pcmcia/Makefile	Mon May  7 19:42:14 2001
@@ -12,7 +12,7 @@
 obj-		:=
 
 # Things that need to export symbols
-export-objs	:= ray_cs.o hermes.o
+export-objs	:= ray_cs.o
 
 # 16-bit client drivers
 obj-$(CONFIG_PCMCIA_3C589)	+= 3c589_cs.o
@@ -25,7 +25,6 @@
 obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
 
 # 16-bit wireless client drivers
-obj-$(CONFIG_PCMCIA_HERMES)	+= orinoco_cs.o hermes.o
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
 obj-$(CONFIG_PCMCIA_NETWAVE)	+= netwave_cs.o
 obj-$(CONFIG_PCMCIA_WAVELAN)	+= wavelan_cs.o
diff -u --recursive --new-file v2.4.4/linux/drivers/net/pcmcia/hermes.c linux/drivers/net/pcmcia/hermes.c
--- v2.4.4/linux/drivers/net/pcmcia/hermes.c	Wed Apr 25 14:45:48 2001
+++ linux/drivers/net/pcmcia/hermes.c	Wed Dec 31 16:00:00 1969
@@ -1,502 +0,0 @@
-/* hermes.c
- *
- * Driver core for the "Hermes" wireless MAC controller, as used in
- * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
- * work on the hfa3841 and hfa3842 MAC controller chips used in the
- * Prism I & II chipsets.
- *
- * This is not a complete driver, just low-level access routines for
- * the MAC controller itself.
- *
- * Based on the prism2 driver from Absolute Value Systems' linux-wlan
- * project, the Linux wvlan_cs driver, Lucent's HCF-Light
- * (wvlan_hcf.c) library, and the NetBSD wireless driver.
- *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
- * 
- * This file distributed under the GPL, version 2.
- */
-
-static const char *version = "hermes.c: 12 Dec 2000 David Gibson <hermes@gibson.dropbear.id.au>";
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include <linux/ptrace.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/errno.h>
-
-#include "hermes.h"
-
-#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
-#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
-#define CMD_COMPL_TIMEOUT (10000) /* in iterations of ~10us */
-#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
-#define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
-#define BAP_ERROR_RETRY (10) /* How many times to retry a BAP seek when there is an error */
-
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
-
-/*
- * Debugging helpers
- */
-
-#undef HERMES_DEBUG
-#ifdef HERMES_DEBUG
-
-#include <stdarg.h>
-
-#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ 0x%x: " , hw->iobase); \
-			printk(#stuff);} while (0)
-
-#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(#stuff)
-
-#else /* ! HERMES_DEBUG */
-
-#define DEBUG(lvl, stuff...) do { } while (0)
-
-#endif /* ! HERMES_DEBUG */
-
-/*
- * Prototypes
- */
-
-static int hermes_issue_cmd(hermes_t *hw, uint16_t cmd, uint16_t param0);
-
-/*
- * Internal inline functions
- */
-
-/*
- * Internal functions
- */
-
-/* Issue a command to the chip. Waiting for it to complete is the caller's
-   problem.
-
-   Returns -EBUSY if the command register is busy, 0 on success.
-
-   Callable from any context.
-*/
-static int hermes_issue_cmd(hermes_t *hw, uint16_t cmd, uint16_t param0)
-{
-	uint16_t reg;
-/*  	unsigned long k = CMD_BUSY_TIMEOUT; */
-
-	/* First check that the command register is not busy */
-	reg = hermes_read_regn(hw, CMD);
-	if (reg & HERMES_CMD_BUSY) {
-		return -EBUSY;
-	}
-
-	hermes_write_regn(hw, PARAM2, 0);
-	hermes_write_regn(hw, PARAM1, 0);
-	hermes_write_regn(hw, PARAM0, param0);
-	hermes_write_regn(hw, CMD, cmd);
-	
-	return 0;
-}
-
-/*
- * Function definitions
- */
-
-void hermes_struct_init(hermes_t *hw, ushort io)
-{
-	hw->iobase = io;
-	hw->inten = 0x0;
-}
-
-int hermes_reset(hermes_t *hw)
-{
-	uint16_t status, reg;
-	int err = 0;
-	int k;
-
-	/* We don't want to be interrupted while resetting the chipset */
-	hw->inten = 0x0;
-	hermes_write_regn(hw, INTEN, 0);
-	hermes_write_regn(hw, EVACK, 0xffff);
-
-	/* Because we hope we can reset the card even if it gets into
-	   a stupid state, we actually wait to see if the command
-	   register will unbusy itself */
-	k = CMD_BUSY_TIMEOUT;
-	reg = hermes_read_regn(hw, CMD);
-	while (k && (reg & HERMES_CMD_BUSY)) {
-		if (reg == 0xffff) /* Special case - the card has probably been removed,
-				      so don't wait for the timeout */
-			return -ENODEV;
-
-		k--;
-		udelay(1);
-		reg = hermes_read_regn(hw, CMD);
-	}
-	
-	/* No need to explicitly handle the timeout - hermes_issue_cmd() will
-	   probably return -EBUSY */
-
-	/* We don't use hermes_docmd_wait here, because the reset wipes
-	   the magic constant in SWSUPPORT0 away, and it gets confused */
-	err = hermes_issue_cmd(hw, HERMES_CMD_INIT, 0);
-	if (err)
-		return err;
-
-	reg = hermes_read_regn(hw, EVSTAT);
-	k = CMD_INIT_TIMEOUT;
-	while ( (! (reg & HERMES_EV_CMD)) && k) {
-		k--;
-		udelay(10);
-		reg = hermes_read_regn(hw, EVSTAT);
-	}
-
-	DEBUG(0, "Reset completed in %d iterations\n", CMD_INIT_TIMEOUT - k);
-
-	hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
-
-	if (! hermes_present(hw)) {
-		DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
-		       hw->iobase);
-		err = -ENODEV;
-		goto out;
-	}
-		
-	if (! (reg & HERMES_EV_CMD)) {
-		printk(KERN_ERR "hermes @ 0x%x: Timeout waiting for card to reset (reg=0x%04x)!\n",
-		       hw->iobase, reg);
-		err = -ETIMEDOUT;
-		goto out;
-	}
-
-	status = hermes_read_regn(hw, STATUS);
-
-	hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
-
-	err = status & HERMES_STATUS_RESULT;
-
- out:
-	return err;
-}
-
-/* Issue a command to the chip, and (busy!) wait for it to
- * complete.
- *
- * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware
- *
- * Callable from any context, but locking is your problem. */
-int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp)
-{
-	int err;
-	int k;
-	uint16_t reg;
-
-	err = hermes_issue_cmd(hw, cmd, parm0);
-	if (err) {
-		if (! hermes_present(hw)) {
-			printk(KERN_WARNING "hermes @ 0x%x: Card removed while issuing command.\n",
-			       hw->iobase);
-			err = -ENODEV;
-		} else 
-			printk(KERN_ERR "hermes @ 0x%x: CMD register busy in hermes_issue_command().\n",
-			       hw->iobase);
-		goto out;
-	}
-
-	reg = hermes_read_regn(hw, EVSTAT);
-	k = CMD_COMPL_TIMEOUT;
-	while ( (! (reg & HERMES_EV_CMD)) && k) {
-		k--;
-		udelay(10);
-		reg = hermes_read_regn(hw, EVSTAT);
-	}
-
-	if (! hermes_present(hw)) {
-		printk(KERN_WARNING "hermes @ 0x%x: Card removed while waiting for command completion.\n",
-		       hw->iobase);
-		err = -ENODEV;
-		goto out;
-	}
-		
-	if (! (reg & HERMES_EV_CMD)) {
-		printk(KERN_ERR "hermes @ 0x%x: Timeout waiting for command completion.\n",
-		       hw->iobase);
-		err = -ETIMEDOUT;
-		goto out;
-	}
-
-	resp->status = hermes_read_regn(hw, STATUS);
-	resp->resp0 = hermes_read_regn(hw, RESP0);
-	resp->resp1 = hermes_read_regn(hw, RESP1);
-	resp->resp2 = hermes_read_regn(hw, RESP2);
-
-	hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
-
-	err = resp->status & HERMES_STATUS_RESULT;
-
- out:
-	return err;
-}
-
-int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid)
-{
-	int err = 0;
-	hermes_response_t resp;
-	int k;
-	uint16_t reg;
-	
-	if ( (size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX) )
-		return -EINVAL;
-
-	err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, &resp);
-	if (err) {
-		printk(KERN_WARNING "hermes @ 0x%x: Frame allocation command failed (0x%X).\n",
-		       hw->iobase, err);
-		return err;
-	}
-
-	reg = hermes_read_regn(hw, EVSTAT);
-	k = ALLOC_COMPL_TIMEOUT;
-	while ( (! (reg & HERMES_EV_ALLOC)) && k) {
-		k--;
-		udelay(10);
-		reg = hermes_read_regn(hw, EVSTAT);
-	}
-	
-	if (! hermes_present(hw)) {
-		printk(KERN_WARNING "hermes @ 0x%x: Card removed waiting for frame allocation.\n",
-		       hw->iobase);
-		return -ENODEV;
-	}
-		
-	if (! (reg & HERMES_EV_ALLOC)) {
-		printk(KERN_ERR "hermes @ 0x%x: Timeout waiting for frame allocation\n",
-		       hw->iobase);
-		return -ETIMEDOUT;
-	}
-
-	*fid = hermes_read_regn(hw, ALLOCFID);
-	hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
-	
-	return 0;
-}
-
-/* Set up a BAP to read a particular chunk of data from card's internal buffer.
- *
- * Returns: < 0 on internal failure (errno), 0 on success, >0 on error
- * from firmware
- *
- * Callable from any context */
-static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
-{
-	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
-	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
-	int k;
-	int l = BAP_ERROR_RETRY;
-	uint16_t reg;
-
-	/* Paranoia.. */
-	if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) )
-		return -EINVAL;
-
-	k = BAP_BUSY_TIMEOUT;
-	reg = hermes_read_reg(hw, oreg);
-
-	if (reg & HERMES_OFFSET_BUSY)
-		return -EBUSY;
-
-	/* Now we actually set up the transfer */
- retry:
-	hermes_write_reg(hw, sreg, id);
-	hermes_write_reg(hw, oreg, offset);
-
-	/* Wait for the BAP to be ready */
-	k = BAP_BUSY_TIMEOUT;
-	reg = hermes_read_reg(hw, oreg);
-	while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
-		k--;
-		udelay(1);
-		reg = hermes_read_reg(hw, oreg);
-	}
-
-	if (reg & HERMES_OFFSET_BUSY)
-		return -ETIMEDOUT;
-
-	/* For some reason, seeking the BAP seems to randomly fail somewhere
-	   (firmware bug?). We retry a few times before giving up. */
-	if (reg & HERMES_OFFSET_ERR) {
-		if (l--) {
-			udelay(1);
-			goto retry;
-		} else
-			return -EIO;
-	}
-
-	return 0;
-}
-
-/* Read a block of data from the chip's buffer, via the
- * BAP. Synchronization/serialization is the caller's problem.  len
- * must be even.
- *
- * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
- */
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
-		     uint16_t id, uint16_t offset)
-{
-	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
-	int err = 0;
-
-	if (len % 2)
-		return -EINVAL;
-
-	err = hermes_bap_seek(hw, bap, id, offset);
-	if (err)
-		goto out;
-
-	/* Actually do the transfer */
-	hermes_read_data(hw, dreg, buf, len/2);
-
- out:
-	return err;
-}
-
-/* Write a block of data to the chip's buffer, via the
- * BAP. Synchronization/serialization is the caller's problem. len
- * must be even.
- *
- * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
- */
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
-		      uint16_t id, uint16_t offset)
-{
-	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
-	int err = 0;
-
-	if (len % 2)
-		return -EINVAL;
-
-	err = hermes_bap_seek(hw, bap, id, offset);
-	if (err)
-		goto out;
-	
-	/* Actually do the transfer */
-	hermes_write_data(hw, dreg, buf, len/2);
-
- out:	
-	return err;
-}
-
-/* Read a Length-Type-Value record from the card.
- *
- * If length is NULL, we ignore the length read from the card, and
- * read the entire buffer regardless. This is useful because some of
- * the configuration records appear to have incorrect lengths in
- * practice.
- *
- * Callable from user or bh context.  */
-int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
-		    uint16_t *length, void *buf)
-{
-	int err = 0;
-	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
-	uint16_t rlength, rtype;
-	hermes_response_t resp;
-	int count;
-
-	if (buflen % 2)
-		return -EINVAL;
-
-	err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, &resp);
-	if (err)
-		goto out;
-
-	err = hermes_bap_seek(hw, bap, rid, 0);
-	if (err)
-		goto out;
-
-	rlength = hermes_read_reg(hw, dreg);
-	rtype = hermes_read_reg(hw, dreg);
-
-	if (length)
-		*length = rlength;
-
-	if (rtype != rid)
-		printk(KERN_WARNING "hermes_read_ltv(): rid  (0x%04x) does "
-		       "not match type (0x%04x)\n", rid, rtype);
-	if (HERMES_RECLEN_TO_BYTES(rlength) > buflen)
-		printk(KERN_WARNING "hermes @ 0x%x: Truncating LTV record from %d to %d bytes. "
-		       "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
-		       HERMES_RECLEN_TO_BYTES(rlength), buflen, rid, rlength);
-	
-	/* For now we always read the whole buffer, the
-	   lengths in the records seem to be wrong, frequently */
-	count = buflen / 2;
-
-#if 0
-	if (length)
-		count = (MIN(buflen, rlength) + 1) / 2;
-	else {
-		count = buflen / 2;
-		if (rlength != buflen)
-			printk(KERN_WARNING "hermes_read_ltv(): Incorrect \
-record length %d instead of %d on RID 0x%04x\n", rlength, buflen, rid);
-	}
-#endif
-	hermes_read_data(hw, dreg, buf, count);
-
- out:
-	return err;
-}
-
-int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid, 
-		     uint16_t length, const void *value)
-{
-	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
-	int err = 0;
-	hermes_response_t resp;
-	int count;
-	
-	DEBUG(3, "write_ltv(): bap=%d rid=0x%04x length=%d (value=0x%04x)\n",
-	      bap, rid, length, * ((uint16_t *)value));
-
-	err = hermes_bap_seek(hw, bap, rid, 0);
-	if (err)
-		goto out;
-
-	hermes_write_reg(hw, dreg, length);
-	hermes_write_reg(hw, dreg, rid);
-
-	count = length - 1;
-
-	hermes_write_data(hw, dreg, value, count);
-
-	err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, 
-				rid, &resp);
-
- out:
-	return err;
-}
-
-EXPORT_SYMBOL(hermes_struct_init);
-EXPORT_SYMBOL(hermes_reset);
-EXPORT_SYMBOL(hermes_docmd_wait);
-EXPORT_SYMBOL(hermes_allocate);
-
-EXPORT_SYMBOL(hermes_bap_pread);
-EXPORT_SYMBOL(hermes_bap_pwrite);
-EXPORT_SYMBOL(hermes_read_ltv);
-EXPORT_SYMBOL(hermes_write_ltv);
-
-static int __init init_hermes(void)
-{
-	printk(KERN_INFO "%s\n", version);
-
-	return 0;
-}
-
-module_init(init_hermes);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/pcmcia/hermes.h linux/drivers/net/pcmcia/hermes.h
--- v2.4.4/linux/drivers/net/pcmcia/hermes.h	Wed Apr 25 14:45:48 2001
+++ linux/drivers/net/pcmcia/hermes.h	Wed Dec 31 16:00:00 1969
@@ -1,402 +0,0 @@
-/* hermes.h
- *
- * Driver core for the "Hermes" wireless MAC controller, as used in
- * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
- * work on the hfa3841 and hfa3842 MAC controller chips used in the
- * Prism I & II chipsets.
- *
- * This is not a complete driver, just low-level access routines for
- * the MAC controller itself.
- *
- * Based on the prism2 driver from Absolute Value Systems' linux-wlan
- * project, the Linux wvlan_cs driver, Lucent's HCF-Light
- * (wvlan_hcf.c) library, and the NetBSD wireless driver.
- *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
- *
- * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
- *
- * This file distributed under the GPL, version 2.
- */
-
-#ifndef _HERMES_H
-#define _HERMES_H
-
-/* Notes on locking:
- *
- * As a module of low level hardware access routines, there is no
- * locking. Users of this module should ensure that they serialize
- * access to the hermes_t structure, and to the hardware
-*/
-
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-
-/*
- * Limits and constants
- */
-#define		HERMES_ALLOC_LEN_MIN		(4)
-#define		HERMES_ALLOC_LEN_MAX		(2400)
-#define		HERMES_LTV_LEN_MAX		(34)
-#define		HERMES_BAP_DATALEN_MAX		(4096)
-#define		HERMES_BAP_OFFSET_MAX		(4096)
-#define		HERMES_PORTID_MAX		(7)
-#define		HERMES_NUMPORTS_MAX		(HERMES_PORTID_MAX+1)
-#define		HERMES_PDR_LEN_MAX		(260)	/* in bytes, from EK */
-#define		HERMES_PDA_RECS_MAX		(200)	/* a guess */
-#define		HERMES_PDA_LEN_MAX		(1024)	/* in bytes, from EK */
-#define		HERMES_SCANRESULT_MAX		(35)
-#define		HERMES_CHINFORESULT_MAX		(8)
-#define		HERMES_FRAME_LEN_MAX		(2304)
-#define		HERMES_MAX_MULTICAST		(16)
-#define		HERMES_MAGIC			(0x7d1f)
-
-/*
- * Hermes register offsets
- */
-#define		HERMES_CMD			(0x00)
-#define		HERMES_PARAM0			(0x02)
-#define		HERMES_PARAM1			(0x04)
-#define		HERMES_PARAM2			(0x06)
-#define		HERMES_STATUS			(0x08)
-#define		HERMES_RESP0			(0x0A)
-#define		HERMES_RESP1			(0x0C)
-#define		HERMES_RESP2			(0x0E)
-#define		HERMES_INFOFID			(0x10)
-#define		HERMES_RXFID			(0x20)
-#define		HERMES_ALLOCFID			(0x22)
-#define		HERMES_TXCOMPLFID		(0x24)
-#define		HERMES_SELECT0			(0x18)
-#define		HERMES_OFFSET0			(0x1C)
-#define		HERMES_DATA0			(0x36)
-#define		HERMES_SELECT1			(0x1A)
-#define		HERMES_OFFSET1			(0x1E)
-#define		HERMES_DATA1			(0x38)
-#define		HERMES_EVSTAT			(0x30)
-#define		HERMES_INTEN			(0x32)
-#define		HERMES_EVACK			(0x34)
-#define		HERMES_CONTROL			(0x14)
-#define		HERMES_SWSUPPORT0		(0x28)
-#define		HERMES_SWSUPPORT1		(0x2A)
-#define		HERMES_SWSUPPORT2		(0x2C)
-#define		HERMES_AUXPAGE			(0x3A)
-#define		HERMES_AUXOFFSET		(0x3C)
-#define		HERMES_AUXDATA			(0x3E)
-
-/*
- * CMD register bitmasks
- */
-#define		HERMES_CMD_BUSY			(0x8000)
-#define		HERMES_CMD_AINFO		(0x7f00)
-#define		HERMES_CMD_MACPORT		(0x0700)
-#define		HERMES_CMD_RECL			(0x0100)
-#define		HERMES_CMD_WRITE		(0x0100)
-#define		HERMES_CMD_PROGMODE		(0x0300)
-#define		HERMES_CMD_CMDCODE		(0x003f)
-
-/*
- * STATUS register bitmasks
- */
-#define		HERMES_STATUS_RESULT		(0x7f00)
-#define		HERMES_STATUS_CMDCODE		(0x003f)
-
-/*
- * OFFSET refister bitmasks
- */
-#define		HERMES_OFFSET_BUSY		(0x8000)
-#define		HERMES_OFFSET_ERR		(0x4000)
-#define		HERMES_OFFSET_DATAOFF		(0x0ffe)
-
-/*
- * Event register bitmasks (INTEN, EVSTAT, EVACK)
- */
-#define		HERMES_EV_TICK			(0x8000)
-#define		HERMES_EV_WTERR			(0x4000)
-#define		HERMES_EV_INFDROP		(0x2000)
-#define		HERMES_EV_INFO			(0x0080)
-#define		HERMES_EV_DTIM			(0x0020)
-#define		HERMES_EV_CMD			(0x0010)
-#define		HERMES_EV_ALLOC			(0x0008)
-#define		HERMES_EV_TXEXC			(0x0004)
-#define		HERMES_EV_TX			(0x0002)
-#define		HERMES_EV_RX			(0x0001)
-
-/*
- * Command codes
- */
-/*--- Controller Commands --------------------------*/
-#define		HERMES_CMD_INIT			(0x0000)
-#define		HERMES_CMD_ENABLE		(0x0001)
-#define		HERMES_CMD_DISABLE		(0x0002)
-#define		HERMES_CMD_DIAG			(0x0003)
-
-/*--- Buffer Mgmt Commands --------------------------*/
-#define		HERMES_CMD_ALLOC		(0x000A)
-#define		HERMES_CMD_TX			(0x000B)
-#define		HERMES_CMD_CLRPRST		(0x0012)
-
-/*--- Regulate Commands --------------------------*/
-#define		HERMES_CMD_NOTIFY		(0x0010)
-#define		HERMES_CMD_INQ			(0x0011)
-
-/*--- Configure Commands --------------------------*/
-#define		HERMES_CMD_ACCESS		(0x0021)
-#define		HERMES_CMD_DOWNLD		(0x0022)
-
-/*--- Debugging Commands -----------------------------*/
-#define 	HERMES_CMD_MONITOR		(0x0038)
-#define		HERMES_MONITOR_ENABLE		(0x000b)
-#define		HERMES_MONITOR_DISABLE		(0x000f)
-
-/*
- * Configuration RIDs
- */
-
-#define		HERMES_RID_CNF_PORTTYPE		(0xfc00)
-#define		HERMES_RID_CNF_MACADDR		(0xfc01)
-#define		HERMES_RID_CNF_DESIRED_SSID	(0xfc02)
-#define		HERMES_RID_CNF_CHANNEL		(0xfc03)
-#define		HERMES_RID_CNF_OWN_SSID		(0xfc04)
-#define		HERMES_RID_CNF_SYSTEM_SCALE	(0xfc06)
-#define		HERMES_RID_CNF_MAX_DATA_LEN	(0xfc07)
-#define		HERMES_RID_CNF_PM_ENABLE	(0xfc09)
-#define		HERMES_RID_CNF_PM_MCAST_RX	(0xfc0b)
-#define		HERMES_RID_CNF_PM_PERIOD	(0xfc0c)
-#define		HERMES_RID_CNF_PM_HOLDOVER	(0xfc0d)
-#define		HERMES_RID_CNF_NICKNAME		(0xfc0e)
-#define		HERMES_RID_CNF_WEP_ON		(0xfc20)
-#define		HERMES_RID_CNF_MWO_ROBUST	(0xfc25)
-#define		HERMES_RID_CNF_PRISM2_WEP_ON	(0xfc28)
-#define		HERMES_RID_CNF_MULTICAST_LIST	(0xfc80)
-#define		HERMES_RID_CNF_CREATEIBSS	(0xfc81)
-#define		HERMES_RID_CNF_FRAG_THRESH	(0xfc82)
-#define		HERMES_RID_CNF_RTS_THRESH	(0xfc83)
-#define		HERMES_RID_CNF_TX_RATE_CTRL	(0xfc84)
-#define		HERMES_RID_CNF_PROMISCUOUS	(0xfc85)
-#define		HERMES_RID_CNF_KEYS		(0xfcb0)
-#define		HERMES_RID_CNF_TX_KEY		(0xfcb1)
-#define		HERMES_RID_CNF_TICKTIME		(0xfce0)
-
-#define		HERMES_RID_CNF_PRISM2_TX_KEY	(0xfc23)
-#define		HERMES_RID_CNF_PRISM2_KEY0	(0xfc24)
-#define		HERMES_RID_CNF_PRISM2_KEY1	(0xfc25)
-#define		HERMES_RID_CNF_PRISM2_KEY2	(0xfc26)
-#define		HERMES_RID_CNF_PRISM2_KEY3	(0xfc27)
-#define		HERMES_RID_CNF_SYMBOL_MANDATORY_BSSID	(0xfc21)
-#define		HERMES_RID_CNF_SYMBOL_AUTH_TYPE		(0xfc2A)
-#define		HERMES_RID_CNF_SYMBOL_BASIC_RATES	(0xfc8A)
-#define		HERMES_RID_CNF_SYMBOL_PREAMBLE		(0xfc8C)
-
-/*
- * Information RIDs
- */
-#define		HERMES_RID_CHANNEL_LIST		(0xfd10)
-#define		HERMES_RID_STAIDENTITY		(0xfd20)
-#define		HERMES_RID_CURRENT_SSID		(0xfd41)
-#define		HERMES_RID_CURRENT_BSSID	(0xfd42)
-#define		HERMES_RID_COMMSQUALITY		(0xfd43)
-#define 	HERMES_RID_CURRENT_TX_RATE	(0xfd44)
-#define 	HERMES_RID_SHORT_RETRY_LIMIT	(0xfd48)
-#define 	HERMES_RID_LONG_RETRY_LIMIT	(0xfd49)
-#define 	HERMES_RID_MAX_TX_LIFETIME	(0xfd4A)
-#define		HERMES_RID_WEP_AVAIL		(0xfd4f)
-#define		HERMES_RID_CURRENT_CHANNEL	(0xfdc1)
-#define		HERMES_RID_DATARATES		(0xfdc6)
-#define		HERMES_RID_SYMBOL_PRIMARY_VER	(0xfd03)
-#define		HERMES_RID_SYMBOL_SECONDARY_VER	(0xfd21)
-#define		HERMES_RID_SYMBOL_KEY_LENGTH	(0xfc2B)
-
-/*
- * Frame structures and constants
- */
-
-typedef struct hermes_frame_desc {
-	/* Hermes - i.e. little-endian byte-order */
-	uint16_t status; /* 0x0 */
-	uint16_t res1, res2; /* 0x2, 0x4 */
-	uint16_t q_info; /* 0x6 */
-	uint16_t res3, res4; /* 0x8, 0xA */
-	uint16_t tx_ctl; /* 0xC */
-} __attribute__ ((packed)) hermes_frame_desc_t;
-
-#define		HERMES_RXSTAT_ERR		(0x0003)
-#define		HERMES_RXSTAT_MACPORT		(0x0700)
-#define		HERMES_RXSTAT_MSGTYPE		(0xE000)
-
-#define		HERMES_RXSTAT_BADCRC		(0x0001)
-#define		HERMES_RXSTAT_UNDECRYPTABLE	(0x0002)
-
-/* RFC-1042 encoded frame */
-#define		HERMES_RXSTAT_1042		(0x2000)
-/* Bridge-tunnel encoded frame */
-#define		HERMES_RXSTAT_TUNNEL		(0x4000)
-/* Wavelan-II Management Protocol frame */
-#define		HERMES_RXSTAT_WMP		(0x6000)
-
-#ifdef __KERNEL__
-
-/* Basic control structure */
-typedef struct hermes {
-	uint iobase;
-
-	uint16_t inten; /* Which interrupts should be enabled? */
-} hermes_t;
-
-typedef struct hermes_response {
-	uint16_t status, resp0, resp1, resp2;
-} hermes_response_t;
-
-/* Firmware information structure */
-typedef struct hermes_identity {
-	uint16_t id, vendor, major, minor;
-} __attribute__ ((packed)) hermes_identity_t;
-
-/* "ID" structure - used for ESSID and station nickname */
-typedef struct hermes_id {
-	uint16_t len;
-	uint16_t val[16];
-} __attribute__ ((packed)) hermes_id_t;
-
-typedef struct hermes_commsqual {
-	uint16_t qual, signal, noise;
-} __attribute__ ((packed)) hermes_commsqual_t;
-
-typedef struct hermes_multicast {
-	uint8_t addr[HERMES_MAX_MULTICAST][ETH_ALEN];
-} __attribute__ ((packed)) hermes_multicast_t;
-
-/* Register access convenience macros */
-#define hermes_read_reg(hw, off) (inw((hw)->iobase + (off)))
-#define hermes_write_reg(hw, off, val) (outw_p((val), (hw)->iobase + (off)))
-
-#define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
-#define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
-
-/* Note that for the next two, the count is in 16-bit words, not bytes */
-#define hermes_read_data(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
-#define hermes_write_data(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
-
-/* Function prototypes */
-void hermes_struct_init(hermes_t *hw, ushort io);
-int hermes_reset(hermes_t *hw);
-int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp);
-int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid);
-
-
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
-		       uint16_t id, uint16_t offset);
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
-			uint16_t id, uint16_t offset);
-int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
-		    uint16_t *length, void *buf);
-int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid,
-		      uint16_t length, const void *value);
-
-/* Inline functions */
-
-static inline int hermes_present(hermes_t *hw)
-{
-	return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
-}
-
-static inline void hermes_enable_interrupt(hermes_t *hw, uint16_t events)
-{
-	hw->inten |= events;
-	hermes_write_regn(hw, INTEN, hw->inten);
-}
-
-static inline void hermes_set_irqmask(hermes_t *hw, uint16_t events)
-{
-	hw->inten = events;
-	hermes_write_regn(hw, INTEN, events);
-}
-
-static inline int hermes_enable_port(hermes_t *hw, int port)
-{
-	hermes_response_t resp;
-
-	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
-				 0, &resp);
-}
-
-static inline int hermes_disable_port(hermes_t *hw, int port)
-{
-	hermes_response_t resp;
-
-	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), 
-				 0, &resp);
-}
-
-#define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
-#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
-
-#define HERMES_READ_RECORD(hw, bap, rid, buf) \
-	(hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
-#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
-	(hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf)))
-
-static inline int hermes_read_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t *word)
-{
-	uint16_t rec;
-	int err;
-
-	err = HERMES_READ_RECORD(hw, bap, rid, &rec);
-	*word = le16_to_cpu(rec);
-	return err;
-}
-
-static inline int hermes_write_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t word)
-{
-	uint16_t rec = cpu_to_le16(word);
-	return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
-}
-
-static inline int hermes_read_staidentity(hermes_t *hw, int bap, hermes_identity_t *buf)
-{
-	int err;
-
-	err = HERMES_READ_RECORD(hw, bap, HERMES_RID_STAIDENTITY, buf);
-	if (err)
-		return err;
-
-	le16_to_cpus(&buf->id);
-	le16_to_cpus(&buf->vendor);
-	le16_to_cpus(&buf->major);
-	le16_to_cpus(&buf->minor);
-	
-	return 0;
-}
-
-static inline int hermes_read_commsqual(hermes_t *hw, int bap, hermes_commsqual_t *buf)
-{
-	int err;
-
-	err = HERMES_READ_RECORD(hw, bap, HERMES_RID_COMMSQUALITY, buf);
-	if (err)
-		return err;
-
-	le16_to_cpus(&buf->qual);
-	le16_to_cpus(&buf->signal);
-	le16_to_cpus(&buf->noise);
-	
-	return 0;
-}
-
-#else /* ! __KERNEL__ */
-
-/* These are provided for the benefit of userspace drivers and testing programs
-   which use ioperm() or iopl() */
-
-#define hermes_read_reg(base, off) (inw((base) + (off)))
-#define hermes_write_reg(base, off, val) (outw((val), (base) + (off)))
-
-#define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name))
-#define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val)))
-
-/* Note that for the next two, the count is in 16-bit words, not bytes */
-#define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count)))
-#define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count)))
-
-#endif /* ! __KERNEL__ */
-
-#endif  /* _HERMES_H */
diff -u --recursive --new-file v2.4.4/linux/drivers/net/pcmcia/orinoco_cs.c linux/drivers/net/pcmcia/orinoco_cs.c
--- v2.4.4/linux/drivers/net/pcmcia/orinoco_cs.c	Wed Apr 25 14:45:48 2001
+++ linux/drivers/net/pcmcia/orinoco_cs.c	Wed Dec 31 16:00:00 1969
@@ -1,4327 +0,0 @@
-/* orinoco_cs.c 0.04	- (formerly known as dldwd_cs.c)
- *
- * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
- * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
- * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
- * It should also be usable on various Prism II based cards such as the
- * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
- * cards such as the 3Com AirConnect and Ericsson WLAN.
- *
- * Copyright (C) 2000 David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
- *	With some help from :
- * Copyright (C) 2001 Jean Tourrilhes, HP Labs <jt@hpl.hp.com>
- *
- * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
- *
- * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy@fasta.fh-dortmund.de>
- *      http://www.fasta.fh-dortmund.de/users/andy/wvlan/
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David
- * A. Hinds are Copyright (C) 1999 David A. Hinds.  All Rights
- * Reserved.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the above.
- * If you wish to allow the use of your version of this file only
- * under the terms of the GPL and not to allow others to use your
- * version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the MPL or the GPL.
- */
-
-/* Notes on locking:
- *
- * The basic principle of operation is that everything except the
- * interrupt handler is serialized through a single spinlock in the
- * dldwd_priv_t structure, using dldwd_lock() and
- * dldwd_unlock() (which in turn use spin_lock_bh() and spin_unlock_bh()).
- *
- * The kernel's IRQ handling stuff ensures that the interrupt handler
- * does not re-enter itself. The interrupt handler is written such
- * that everything it does is safe without a lock: chiefly this means
- * that the Rx path uses one of the Hermes chipset's BAPs while
- * everything else uses the other.
- *
- * For the moment access to the device statistics from the interrupt
- * handler is unsafe - we just put up with any resulting errors in the
- * statisics. FIXME: This should probably be changed to store the
- * stats in atomic types.
- *
- * EXCEPT that we don't want the irq handler running when we actually
- * reset or shut down the card, because strange things might happen
- * (probably the worst would be one packet of garbage, but you can't
- * be too careful). For this we use __dldwd_stop_irqs() which will set
- * a flag to disable the interrupt handler, and wait for any
- * outstanding instances of the handler to complete. THIS WILL LOSE
- * INTERRUPTS! so it shouldn't be used except for resets, when we
- * don't care about that.*/
-
-/*
- * Tentative changelog...
- *
- * v0.01 -> v0.02 - 21/3/2001 - Jean II
- *	o Allow to use regular ethX device name instead of dldwdX
- *	o Warning on IBSS with ESSID=any for firmware 6.06
- *	o Put proper range.throughput values (optimistic)
- *	o IWSPY support (IOCTL and stat gather in Rx path)
- *	o Allow setting frequency in Ad-Hoc mode
- *	o Disable WEP setting if !has_wep to work on old firmware
- *	o Fix txpower range
- *	o Start adding support for Samsung/Compaq firmware
- *
- * v0.02 -> v0.03 - 23/3/2001 - Jean II
- *	o Start adding Symbol support - need to check all that
- *	o Fix Prism2/Symbol WEP to accept 128 bits keys
- *	o Add Symbol WEP (add authentication type)
- *	o Add Prism2/Symbol rate
- *	o Add PM timeout (holdover duration)
- *	o Enable "iwconfig eth0 key off" and friends (toggle flags)
- *	o Enable "iwconfig eth0 power unicast/all" (toggle flags)
- *	o Try with an intel card. It report firmware 1.01, behave like
- *	  an antiquated firmware, however on windows it says 2.00. Yuck !
- *	o Workaround firmware bug in allocate buffer (Intel 1.01)
- *	o Finish external renaming to orinoco...
- *	o Testing with various Wavelan firmwares
- *
- * v0.03 -> v0.04 - 30/3/2001 - Jean II
- *	o Update to Wireless 11 -> add retry limit/lifetime support
- *	o Tested with a D-Link DWL 650 card, fill in firmware support
- *	o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot)
- *	o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-(
- *	  It work on D-Link *only* after a tcpdump. Weird...
- *	  And still doesn't work on Intel card. Grrrr...
- *	o Update the mode after a setport3
- *	o Add preamble setting for Symbol cards (not yet enabled)
- *	o Don't complain as much about Symbol cards...
- *
- * v0.04 -> v0.04b - 22/4/2001 - David Gibson
- *      o Removed the 'eth' parameter - always use ethXX as the
- *        interface name instead of dldwdXX.  The other was racy
- *        anyway.
- *	o Clean up RID definitions in hermes.h, other cleanups
- *
- * v0.04b -> v0.04c - 24/4/2001 - Jean II
- *	o Tim Hurley <timster@seiki.bliztech.com> reported a D-Link card
- *	  with vendor 02 and firmware 0.08. Added in the capabilities...
- *	o Tested Lucent firmware 7.28, everything works...
- *
- * TODO - Jean II
- *	o inline functions (lot's of candidate, need to reorder code)
- *	o Separate Pcmcia specific code to help Airport/Mini PCI driver
- *	o Test PrismII/Symbol cards & firmware versions
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <linux/proc_fs.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-
-#include <pcmcia/version.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/bus_ops.h>
-
-#include "hermes.h"
-
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
-static char *version = "orinoco_cs.c 0.04 (David Gibson <hermes@gibson.dropbear.id.au>)";
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-#define DEBUGMORE(n, args...) do { if (pc_debug>(n)) printk(args); } while (0)
-#else
-#define DEBUG(n, args...) do { } while (0)
-#define DEBUGMORE(n, args...) do { } while (0)
-#endif
-
-#define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
-#define TRACE_EXIT(devname)  DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
-
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
-
-#define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) )
-
-
-#if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
-#error "orinoco_cs requires Wireless extensions v10 or later."
-#endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */
-#define WIRELESS_SPY		// enable iwspy support
-
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-/* The old way: bit map of interrupts to choose from */
-/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
-static uint irq_mask = 0xdeb8;
-/* Newer, simpler way of listing specific interrupts */
-static int irq_list[4] = { -1 };
-/* Do a Pcmcia soft reset (may help some cards) */
-static int reset_cor = 0;
-
-MODULE_PARM(irq_mask, "i");
-MODULE_PARM(irq_list, "1-4i");
-MODULE_PARM(reset_cor, "i");
-
-/*====================================================================*/
-
-#define DLDWD_MIN_MTU		256
-#define DLDWD_MAX_MTU		(HERMES_FRAME_LEN_MAX - ENCAPS_OVERHEAD)
-
-#define LTV_BUF_SIZE		128
-#define USER_BAP		0
-#define IRQ_BAP			1
-#define DLDWD_MACPORT		0
-#define IRQ_LOOP_MAX		10
-#define TX_NICBUF_SIZE		2048
-#define TX_NICBUF_SIZE_BUG	1585		/* Bug in Intel firmware */
-#define MAX_KEYS		4
-#define MAX_KEY_SIZE		14
-#define LARGE_KEY_SIZE		13
-#define SMALL_KEY_SIZE		5
-#define MAX_FRAME_SIZE		2304
-
-const long channel_frequency[] = {
-	2412, 2417, 2422, 2427, 2432, 2437, 2442,
-	2447, 2452, 2457, 2462, 2467, 2472, 2484
-};
-
-#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
-
-/* This tables gives the actual meanings of the bitrate IDs returned by the firmware.
-   It gives the rate in halfMb/s, negative indicates auto mode */
-const int rate_list[] = { 0, 2, 4, -22, 11, 22, -4, -11, 0, 0, 0, 0};
-
-#define NUM_RATES (sizeof(rate_list) / sizeof(rate_list[0]))
-typedef struct dldwd_key {
-	uint16_t len;
-	char data[MAX_KEY_SIZE];
-} __attribute__ ((packed)) dldwd_key_t;
-
-typedef dldwd_key_t dldwd_keys_t[MAX_KEYS];
-
-typedef struct dldwd_priv {
-	dev_link_t link;
-	dev_node_t node;
-	int instance;
-
-	spinlock_t lock;
-	long state;
-#define DLDWD_STATE_INIRQ 0
-#define DLDWD_STATE_DOIRQ 1
-
-	/* Net device stuff */
-	struct net_device ndev;
-	struct net_device_stats stats;
-	struct iw_statistics wstats;
-
-
-	/* Hardware control variables */
-	hermes_t hw;
-	uint16_t txfid;
-
-	/* Capabilities of the hardware/firmware */
-	hermes_identity_t firmware_info;
-	int firmware_type;
-#define FIRMWARE_TYPE_LUCENT 1
-#define FIRMWARE_TYPE_PRISM2 2
-#define FIRMWARE_TYPE_SYMBOL 3
-	int has_ibss, has_port3, prefer_port3, has_ibss_any;
-	int has_wep, has_big_wep;
-	int has_mwo;
-	int has_pm;
-	int has_retry;
-	int has_preamble;
-	int broken_reset, broken_allocate;
-	uint16_t channel_mask;
-
-	/* Current configuration */
-	uint32_t iw_mode;
-	int port_type, allow_ibss;
-	uint16_t wep_on, wep_restrict, tx_key;
-	dldwd_keys_t keys;
- 	char nick[IW_ESSID_MAX_SIZE+1];
-	char desired_essid[IW_ESSID_MAX_SIZE+1];
-	uint16_t frag_thresh, mwo_robust;
-	uint16_t channel;
-	uint16_t ap_density, rts_thresh;
-	uint16_t tx_rate_ctrl;
-	uint16_t pm_on, pm_mcast, pm_period, pm_timeout;
-	uint16_t retry_short, retry_long, retry_time;
-	uint16_t preamble;
-
-	int promiscuous, allmulti, mc_count;
-
-#ifdef WIRELESS_SPY
-	int			spy_number;
-	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
-	struct iw_quality	spy_stat[IW_MAX_SPY];
-#endif
-
-	/* /proc based debugging stuff */
-	struct proc_dir_entry *dir_dev;
-	struct proc_dir_entry *dir_regs;
-	struct proc_dir_entry *dir_recs;
-} dldwd_priv_t;
-
-struct p80211_hdr {
-	uint16_t frame_ctl;
-	uint16_t duration_id;
-	uint8_t addr1[ETH_ALEN];
-	uint8_t addr2[ETH_ALEN];
-	uint8_t addr3[ETH_ALEN];
-	uint16_t seq_ctl;
-	uint8_t addr4[ETH_ALEN];
-	uint16_t data_len;
-} __attribute__ ((packed));
-
-/* Frame control field constants */
-#define DLDWD_FCTL_VERS			0x0002
-#define DLDWD_FCTL_FTYPE		0x000c
-#define DLDWD_FCTL_STYPE		0x00f0
-#define DLDWD_FCTL_TODS			0x0100
-#define DLDWD_FCTL_FROMDS		0x0200
-#define DLDWD_FCTL_MOREFRAGS		0x0400
-#define DLDWD_FCTL_RETRY		0x0800
-#define DLDWD_FCTL_PM			0x1000
-#define DLDWD_FCTL_MOREDATA		0x2000
-#define DLDWD_FCTL_WEP			0x4000
-#define DLDWD_FCTL_ORDER		0x8000
-
-#define DLDWD_FTYPE_MGMT		0x0000
-#define DLDWD_FTYPE_CTL			0x0004
-#define DLDWD_FTYPE_DATA		0x0008
-
-struct p8022_hdr {
-	uint8_t dsap;
-	uint8_t ssap;
-	uint8_t ctrl;
-	uint8_t oui[3];
-} __attribute__ ((packed));
-
-struct dldwd_frame_hdr {
-	hermes_frame_desc_t desc;
-	struct p80211_hdr p80211;
-	struct ethhdr p8023;
-	struct p8022_hdr p8022;
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-#define P8023_OFFSET		(sizeof(hermes_frame_desc_t) + \
-				sizeof(struct p80211_hdr))
-#define ENCAPS_OVERHEAD		(sizeof(struct p8022_hdr) + 2)
-
-/*
- * Function prototypes
- */
-
-/* PCMCIA gumpf */
-
-static void dldwd_config(dev_link_t * link);
-static void dldwd_release(u_long arg);
-static int dldwd_event(event_t event, int priority,
-		       event_callback_args_t * args);
-
-static dev_link_t *dldwd_attach(void);
-static void dldwd_detach(dev_link_t *);
-
-/* Hardware control routines */
-
-static int __dldwd_hw_reset(dldwd_priv_t *priv);
-static void dldwd_shutdown(dldwd_priv_t *dev);
-static int dldwd_reset(dldwd_priv_t *dev);
-static int __dldwd_hw_setup_wep(dldwd_priv_t *priv);
-static int dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN]);
-static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]);
-static long dldwd_hw_get_freq(dldwd_priv_t *priv);
-static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,
-				    int32_t *rates, int max);
-
-/* Interrupt handling routines */
-void dldwd_interrupt(int irq, void * dev_id, struct pt_regs *regs);
-static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_wterr(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw);
-static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw);
-
-/* struct net_device methods */
-static int dldwd_init(struct net_device *dev);
-static int dldwd_open(struct net_device *dev);
-static int dldwd_stop(struct net_device *dev);
-
-static int dldwd_xmit(struct sk_buff *skb, struct net_device *dev);
-static void dldwd_tx_timeout(struct net_device *dev);
-
-static struct net_device_stats *dldwd_get_stats(struct net_device *dev);
-static struct iw_statistics *dldwd_get_wireless_stats(struct net_device *dev);
-static void dldwd_stat_gather(struct net_device *dev,
-			      struct sk_buff *skb,
-			      struct dldwd_frame_hdr *hdr);
-
-static int dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq);
-static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);
-static int dldwd_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq);
-static int dldwd_ioctl_setessid(struct net_device *dev, struct iw_point *erq);
-static int dldwd_ioctl_getessid(struct net_device *dev, struct iw_point *erq);
-static int dldwd_ioctl_setnick(struct net_device *dev, struct iw_point *nrq);
-static int dldwd_ioctl_getnick(struct net_device *dev, struct iw_point *nrq);
-static int dldwd_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq);
-static int dldwd_ioctl_getsens(struct net_device *dev, struct iw_param *srq);
-static int dldwd_ioctl_setsens(struct net_device *dev, struct iw_param *srq);
-static int dldwd_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);
-static int dldwd_ioctl_setfrag(struct net_device *dev, struct iw_param *frq);
-static int dldwd_ioctl_getfrag(struct net_device *dev, struct iw_param *frq);
-static int dldwd_ioctl_setrate(struct net_device *dev, struct iw_param *frq);
-static int dldwd_ioctl_getrate(struct net_device *dev, struct iw_param *frq);
-static int dldwd_ioctl_setpower(struct net_device *dev, struct iw_param *prq);
-static int dldwd_ioctl_getpower(struct net_device *dev, struct iw_param *prq);
-static int dldwd_ioctl_setport3(struct net_device *dev, struct iwreq *wrq);
-static int dldwd_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);
-static int dldwd_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-
-static int dldwd_change_mtu(struct net_device *dev, int new_mtu);
-static void __dldwd_set_multicast_list(struct net_device *dev);
-
-/* /proc debugging stuff */
-static int dldwd_proc_init(void);
-static void dldwd_proc_cleanup(void);
-static int dldwd_proc_dev_init(dldwd_priv_t *dev);
-static void dldwd_proc_dev_cleanup(dldwd_priv_t *dev);
-
-/*
- * Inline functions
- */
-static inline void
-dldwd_lock(dldwd_priv_t *priv)
-{
-	spin_lock_bh(&priv->lock);
-}
-
-static inline void
-dldwd_unlock(dldwd_priv_t *priv)
-{
-	spin_unlock_bh(&priv->lock);
-}
-
-static inline int
-dldwd_irqs_allowed(dldwd_priv_t *priv)
-{
-	return test_bit(DLDWD_STATE_DOIRQ, &priv->state);
-}
-
-static inline void
-__dldwd_stop_irqs(dldwd_priv_t *priv)
-{
-	hermes_t *hw = &priv->hw;
-
-	hermes_set_irqmask(hw, 0);
-	clear_bit(DLDWD_STATE_DOIRQ, &priv->state);
-	while (test_bit(DLDWD_STATE_INIRQ, &priv->state))
-		;
-}
-
-static inline void
-__dldwd_start_irqs(dldwd_priv_t *priv, uint16_t irqmask)
-{
-	hermes_t *hw = &priv->hw;
-
-	TRACE_ENTER(priv->ndev.name);
-
-	__cli();
-	set_bit(DLDWD_STATE_DOIRQ, &priv->state);
-	hermes_set_irqmask(hw, irqmask);
-	__sti();
-
-	TRACE_EXIT(priv->ndev.name);
-}
-
-static inline void
-set_port_type(dldwd_priv_t *priv)
-{
-	switch (priv->iw_mode) {
-	case IW_MODE_INFRA:
-		priv->port_type = 1;
-		priv->allow_ibss = 0;
-		break;
-	case IW_MODE_ADHOC:
-		if (priv->prefer_port3) {
-			priv->port_type = 3;
-			priv->allow_ibss = 0;
-		} else {
-			priv->port_type = 1;
-			priv->allow_ibss = 1;
-		}
-		break;
-	default:
-		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
-		       priv->ndev.name);
-	}
-}
-
-static inline void
-dldwd_set_multicast_list(struct net_device *dev)
-{
-	dldwd_priv_t *priv = dev->priv;
-
-	dldwd_lock(priv);
-	__dldwd_set_multicast_list(dev);
-	dldwd_unlock(priv);
-}
-
-/*
- * Hardware control routines
- */
-
-static int
-__dldwd_hw_reset(dldwd_priv_t *priv)
-{
-	hermes_t *hw = &priv->hw;
-	int err;
-
-	if (! priv->broken_reset)
-		return hermes_reset(hw);
-	else {
-		hw->inten = 0;
-		hermes_write_regn(hw, INTEN, 0);
-		err = hermes_disable_port(hw, 0);
-		hermes_write_regn(hw, EVACK, 0xffff);
-		return err;
-	}
-}
-
-static void
-dldwd_shutdown(dldwd_priv_t *priv)
-{
-/* 	hermes_t *hw = &priv->hw; */
-	int err = 0;
-
-	TRACE_ENTER(priv->ndev.name);
-
-	dldwd_lock(priv);
-	__dldwd_stop_irqs(priv);
-
-	err = __dldwd_hw_reset(priv);
-	if (err && err != -ENODEV) /* If the card is gone, we don't care about shutting it down */
-		printk(KERN_ERR "%s: Error %d shutting down Hermes chipset\n", priv->ndev.name, err);
-
-	dldwd_unlock(priv);
-
-	TRACE_EXIT(priv->ndev.name);
-}
-
-static int
-dldwd_reset(dldwd_priv_t *priv)
-{
-	struct net_device *dev = &priv->ndev;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	hermes_id_t idbuf;
-	int frame_size;
-
-	TRACE_ENTER(priv->ndev.name);
-
-	dldwd_lock(priv);
-
-	__dldwd_stop_irqs(priv);
-
-	err = __dldwd_hw_reset(priv);
-	if (err)
-		goto out;
-
-	frame_size = TX_NICBUF_SIZE;
-	/* This stupid bug is present in Intel firmware 1.10, and
-	 * may be fixed in later firmwares - Jean II */
-	if(priv->broken_allocate)
-		frame_size = TX_NICBUF_SIZE_BUG;
-	err = hermes_allocate(hw, frame_size, &priv->txfid);
-	if (err)
-		goto out;
-
-	/* Now set up all the parameters on the card */
-	
-	/* Set up the link mode */
-	
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PORTTYPE, priv->port_type);
-	if (err)
-		goto out;
-	if (priv->has_ibss) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CREATEIBSS,
-					   priv->allow_ibss);
-		if (err)
-			goto out;
-		if((strlen(priv->desired_essid) == 0) && (priv->allow_ibss)
-		   && (!priv->has_ibss_any)) {
-			printk(KERN_WARNING "%s: This firmware requires an \
-ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
-			/* With wvlan_cs, in this case, we would crash.
-			 * hopefully, this driver will behave better...
-			 * Jean II */
-		}
-	}
-
-	/* Set up encryption */
-	if (priv->has_wep) {
-		err = __dldwd_hw_setup_wep(priv);
-		if (err)
-			goto out;
-	}
-
-	/* Set the desired ESSID */
-	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
-	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
-	err = hermes_write_ltv(hw, USER_BAP, (priv->port_type == 3) ?
-			       HERMES_RID_CNF_OWN_SSID : HERMES_RID_CNF_DESIRED_SSID,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
-			       &idbuf);
-	if (err)
-		goto out;
-
-	/* Set the station name */
-	idbuf.len = cpu_to_le16(strlen(priv->nick));
-	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNF_NICKNAME,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
-			       &idbuf);
-	if (err)
-		goto out;
-
-	/* Set the channel/frequency */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CHANNEL, priv->channel);
-	if (err)
-		goto out;
-
-	/* Set AP density */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, priv->ap_density);
-	if (err)
-		goto out;
-
-	/* Set RTS threshold */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, priv->rts_thresh);
-	if (err)
-		goto out;
-
-	/* Set fragmentation threshold or MWO robustness */
-	if (priv->has_mwo)
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNF_MWO_ROBUST, priv->mwo_robust);
-	else
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNF_FRAG_THRESH, priv->frag_thresh);
-	if (err)
-		goto out;
-
-	/* Set bitrate */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_RATE_CTRL,
-				   priv->tx_rate_ctrl);
-	if (err)
-		goto out;
-
-	/* Set power management */
-	if (priv->has_pm) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_ENABLE,
-					   priv->pm_on);
-		if (err)
-			goto out;
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_MCAST_RX,
-					   priv->pm_mcast);
-		if (err)
-			goto out;
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD,
-					   priv->pm_period);
-		if (err)
-			goto out;
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER,
-					   priv->pm_timeout);
-		if (err)
-			goto out;
-	}
-
-	/* Set retry settings - will fail on lot's of firmwares */
-	if (priv->has_retry) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT,
-					   priv->retry_short);
-		if (err) {
-			printk(KERN_WARNING "%s: Can't set retry limit!\n", dev->name);
-			goto out;
-		}
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT,
-					   priv->retry_long);
-		if (err)
-			goto out;
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME,
-					   priv->retry_time);
-		if (err)
-			goto out;
-	}
-
-	/* Set preamble - only for Symbol so far... */
-	if (priv->has_preamble) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE,
-					   priv->preamble);
-		if (err) {
-			printk(KERN_WARNING "%s: Can't set preamble!\n", dev->name);
-			goto out;
-		}
-	}
-
-	/* Set promiscuity / multicast*/
-	priv->promiscuous = 0;
-	priv->allmulti = 0;
-	priv->mc_count = 0;
-	__dldwd_set_multicast_list(dev);
-	
-	err = hermes_enable_port(hw, DLDWD_MACPORT);
-	if (err)
-		goto out;
-	
-	__dldwd_start_irqs(priv, HERMES_EV_RX | HERMES_EV_ALLOC |
-			   HERMES_EV_TX | HERMES_EV_TXEXC |
-			   HERMES_EV_WTERR | HERMES_EV_INFO |
-			   HERMES_EV_INFDROP);
-
- out:
-	dldwd_unlock(priv);
-
-	TRACE_EXIT(priv->ndev.name);
-
-	return err;
-}
-
-static int __dldwd_hw_setup_wep(dldwd_priv_t *priv)
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	int	extra_wep_flag = 0;
-
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_LUCENT: /* Lucent style WEP */
-		if (priv->wep_on) {
-			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_KEY, priv->tx_key);
-			if (err)
-				return err;
-			
-			err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNF_KEYS, &priv->keys);
-			if (err)
-				return err;
-		}
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_WEP_ON, priv->wep_on);
-		if (err)
-			return err;
-		break;
-
-	case FIRMWARE_TYPE_PRISM2: /* Prism II style WEP */
-	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
-		if (priv->wep_on) {
-			char keybuf[LARGE_KEY_SIZE+1];
-			int keylen;
-			int i;
-			
-			/* Write all 4 keys */
-			for(i = 0; i < MAX_KEYS; i++) {
-				keylen = priv->keys[i].len;
-				keybuf[keylen] = '\0';
-				memcpy(keybuf, priv->keys[i].data, keylen);
-				err = hermes_write_ltv(hw, USER_BAP,
-						       HERMES_RID_CNF_PRISM2_KEY0 + i,
-						       HERMES_BYTES_TO_RECLEN(keylen + 1),
-						       &keybuf);
-				if (err)
-					return err;
-			}
-
-			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_TX_KEY,
-						   priv->tx_key);
-			if (err)
-				return err;
-
-			/* Authentication is where Prism2 and Symbol
-			 * firmware differ... */
-			if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) {
-				/* Symbol cards : set the authentication :
-				 * 0 -> no encryption, 1 -> open,
-				 * 2 -> shared key, 3 -> shared key 128bit */
-				if(priv->wep_restrict) {
-					if(priv->keys[priv->tx_key].len >
-					   SMALL_KEY_SIZE)
-						extra_wep_flag = 3;
-					else
-						extra_wep_flag = 2;
-				} else
-					extra_wep_flag = 1;
-				err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, priv->wep_restrict);
-				if (err)
-					return err;
-			} else {
-				/* Prism2 card : we need to modify master
-				 * WEP setting */
-				if(priv->wep_restrict)
-					extra_wep_flag = 2;
-				else
-					extra_wep_flag = 0;
-			}
-		}
-		
-		/* Master WEP setting : on/off */
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, (priv->wep_on | extra_wep_flag));
-		if (err)
-			return err;	
-		break;
-
-	default:
-		if (priv->wep_on) {
-			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
-			       priv->ndev.name);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN])
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-
-	dldwd_lock(priv);
-
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_BSSID,
-			      ETH_ALEN, NULL, buf);
-
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active,
-			      char buf[IW_ESSID_MAX_SIZE+1])
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	hermes_id_t essidbuf;
-	char *p = (char *)(&essidbuf.val);
-	int len;
-
-	TRACE_ENTER(priv->ndev.name);
-
-	dldwd_lock(priv);
-
-	if (strlen(priv->desired_essid) > 0) {
-		/* We read the desired SSID from the hardware rather
-		   than from priv->desired_essid, just in case the
-		   firmware is allowed to change it on us. I'm not
-		   sure about this */
-		/* My guess is that the OWN_SSID should always be whatever
-		 * we set to the card, whereas CURRENT_SSID is the one that
-		 * may change... - Jean II */
-		uint16_t rid;
-
-		*active = 1;
-
-		rid = (priv->port_type == 3) ? HERMES_RID_CNF_OWN_SSID :
-			HERMES_RID_CNF_DESIRED_SSID;
-		
-		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
-				      NULL, &essidbuf);
-		if (err)
-			goto fail_unlock;
-	} else {
-		*active = 0;
-
-		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_SSID,
-				      sizeof(essidbuf), NULL, &essidbuf);
-		if (err)
-			goto fail_unlock;
-	}
-
-	len = le16_to_cpu(essidbuf.len);
-
-	memset(buf, 0, sizeof(buf));
-	memcpy(buf, p, len);
-	buf[len] = '\0';
-
- fail_unlock:
-	dldwd_unlock(priv);
-
-	TRACE_EXIT(priv->ndev.name);
-
-	return err;       
-}
-
-static long dldwd_hw_get_freq(dldwd_priv_t *priv)
-{
-	
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	uint16_t channel;
-	long freq = 0;
-
-	dldwd_lock(priv);
-	
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_CHANNEL, &channel);
-	if (err)
-		goto out;
-
-	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
-		struct net_device *dev = &priv->ndev;
-
-		printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel);
-		err = -EBUSY;
-		goto out;
-
-	}
-	freq = channel_frequency[channel-1] * 100000;
-
- out:
-	dldwd_unlock(priv);
-
-	if (err > 0)
-		err = -EBUSY;
-	return err ? err : freq;
-}
-
-static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,
-				    int32_t *rates, int max)
-{
-	hermes_t *hw = &priv->hw;
-	hermes_id_t list;
-	unsigned char *p = (unsigned char *)&list.val;
-	int err = 0;
-	int num;
-	int i;
-
-	dldwd_lock(priv);
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_DATARATES, sizeof(list),
-			      NULL, &list);
-	dldwd_unlock(priv);
-
-	if (err)
-		return err;
-	
-	num = le16_to_cpu(list.len);
-	*numrates = num;
-	num = MIN(num, max);
-
-	for (i = 0; i < num; i++) {
-		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
-	}
-
-	return 0;
-}
-
-#ifndef PCMCIA_DEBUG
-static inline void show_rx_frame(struct dldwd_frame_hdr *frame) {}
-#else
-static void show_rx_frame(struct dldwd_frame_hdr *frame)
-{
-	printk(KERN_DEBUG "RX descriptor:\n");
-	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
-	printk(KERN_DEBUG "  res1        = 0x%04x\n", frame->desc.res1);
-	printk(KERN_DEBUG "  res2        = 0x%04x\n", frame->desc.res2);
-	printk(KERN_DEBUG "  q_info      = 0x%04x\n", frame->desc.q_info);
-	printk(KERN_DEBUG "  res3        = 0x%04x\n", frame->desc.res3);
-	printk(KERN_DEBUG "  res4        = 0x%04x\n", frame->desc.res4);
-	printk(KERN_DEBUG "  tx_ctl      = 0x%04x\n", frame->desc.tx_ctl);
-
-	printk(KERN_DEBUG "IEEE 802.11 header:\n");
-	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
-	       frame->p80211.frame_ctl);
-	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
-	       frame->p80211.duration_id);
-	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr1[0], frame->p80211.addr1[1],
-	       frame->p80211.addr1[2], frame->p80211.addr1[3],
-	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
-	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr2[0], frame->p80211.addr2[1],
-	       frame->p80211.addr2[2], frame->p80211.addr2[3],
-	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
-	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr3[0], frame->p80211.addr3[1],
-	       frame->p80211.addr3[2], frame->p80211.addr3[3],
-	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
-	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
-	       frame->p80211.seq_ctl);
-	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr4[0], frame->p80211.addr4[1],
-	       frame->p80211.addr4[2], frame->p80211.addr4[3],
-	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
-	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
-	       frame->p80211.data_len);
-
-	printk(KERN_DEBUG "IEEE 802.3 header:\n");
-	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
-	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
-	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
-	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_source[0], frame->p8023.h_source[1],
-	       frame->p8023.h_source[2], frame->p8023.h_source[3],
-	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
-	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
-
-	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
-	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
-	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
-	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
-	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
-	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
-	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
-}
-#endif
-
-/*
- * Interrupt handler
- */
-void dldwd_interrupt(int irq, void * dev_id, struct pt_regs *regs)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *) dev_id;
-	hermes_t *hw = &priv->hw;
-	struct net_device *dev = &priv->ndev;
-	int count = IRQ_LOOP_MAX;
-	uint16_t evstat, events;
-	static int old_time = 0, timecount = 0; /* Eugh, revolting hack for now */
-
-	if (test_and_set_bit(DLDWD_STATE_INIRQ, &priv->state))
-		BUG();
-
-	if (! dldwd_irqs_allowed(priv)) {
-		clear_bit(DLDWD_STATE_INIRQ, &priv->state);
-		return;
-	}
-
-	DEBUG(3, "%s: dldwd_interrupt()  irq %d\n", priv->ndev.name, irq);
-
-	while (1) {
-		if (jiffies != old_time)
-			timecount = 0;
-		if ( (++timecount > 50) || (! count--) ) {
-			printk(KERN_CRIT "%s: IRQ handler is looping too \
-much! Shutting down.\n",
-			       dev->name);
-			/* Perform an emergency shutdown */
-			clear_bit(DLDWD_STATE_DOIRQ, &priv->state);
-			hermes_set_irqmask(hw, 0);
-			break;
-		}
-
-		evstat = hermes_read_regn(hw, EVSTAT);
-		DEBUG(3, "__dldwd_interrupt(): count=%d EVSTAT=0x%04x inten=0x%04x\n",
-		      count, evstat, hw->inten);
-
-		events = evstat & hw->inten;
-
-		if (! events) {
-			if (netif_queue_stopped(dev)) {
-				/* There seems to be a firmware bug which
-				   sometimes causes the card to give an
-				   interrupt with no event set, when there
-				   sould be a Tx completed event. */
-				DEBUG(3, "%s: Interrupt with no event (ALLOCFID=0x%04x)\n",
-				      dev->name, (int)hermes_read_regn(hw, ALLOCFID));
-				events = HERMES_EV_TX | HERMES_EV_ALLOC;
-			} else /* Nothing's happening, we're done */
-				break;
-		}
-
-		/* Check the card hasn't been removed */
-		if (! hermes_present(hw)) {
-			DEBUG(0, "dldwd_interrupt(): card removed\n");
-			break;
-		}
-
-		if (events & HERMES_EV_TICK)
-			__dldwd_ev_tick(priv, hw);
-		if (events & HERMES_EV_WTERR)
-			__dldwd_ev_wterr(priv, hw);
-		if (events & HERMES_EV_INFDROP)
-			__dldwd_ev_infdrop(priv, hw);
-		if (events & HERMES_EV_INFO)
-			__dldwd_ev_info(priv, hw);
-		if (events & HERMES_EV_RX)
-			__dldwd_ev_rx(priv, hw);
-		if (events & HERMES_EV_TXEXC)
-			__dldwd_ev_txexc(priv, hw);
-		if (events & HERMES_EV_TX)
-			__dldwd_ev_tx(priv, hw);
-		if (events & HERMES_EV_ALLOC)
-			__dldwd_ev_alloc(priv, hw);
-		
-		hermes_write_regn(hw, EVACK, events);
-	}
-
-	clear_bit(DLDWD_STATE_INIRQ, &priv->state);
-}
-
-static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw)
-{
-	printk(KERN_DEBUG "%s: TICK\n", priv->ndev.name);
-}
-
-static void __dldwd_ev_wterr(dldwd_priv_t *priv, hermes_t *hw)
-{
-	/* This seems to happen a fair bit under load, but ignoring it
-	   seems to work fine...*/
-	DEBUG(1, "%s: MAC controller error (WTERR). Ignoring.\n",
-	      priv->ndev.name);
-}
-
-static void __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw)
-{
-	printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev.name);
-}
-
-static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw)
-{
-	DEBUG(3, "%s: Information frame received.\n", priv->ndev.name);
-	/* We don't actually do anything about it - we assume the MAC
-	   controller can deal with it */
-}
-
-static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw)
-{
-	struct net_device *dev = &priv->ndev;
-	struct net_device_stats *stats = &priv->stats;
-	struct iw_statistics *wstats = &priv->wstats;
-	struct sk_buff *skb = NULL;
-	uint16_t rxfid, status;
-	int length, data_len, data_off;
-	char *p;
-	struct dldwd_frame_hdr hdr;
-	struct ethhdr *eh;
-	int err;
-
-	rxfid = hermes_read_regn(hw, RXFID);
-	DEBUG(3, "__dldwd_ev_rx(): RXFID=0x%04x\n", rxfid);
-
-	/* We read in the entire frame header here. This isn't really
-	   necessary, since we ignore most of it, but it's
-	   conceptually simpler. We can tune this later if
-	   necessary. */
-	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 0);
-	if (err) {
-		printk(KERN_ERR "%s: error %d reading frame header. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	status = le16_to_cpu(hdr.desc.status);
-	
-	if (status & HERMES_RXSTAT_ERR) {
-		if ((status & HERMES_RXSTAT_ERR) == HERMES_RXSTAT_BADCRC) {
-			stats->rx_crc_errors++;
-			printk(KERN_WARNING "%s: Bad CRC on Rx. Frame dropped.\n",
-			       dev->name);
-			show_rx_frame(&hdr);
-		} else if ((status & HERMES_RXSTAT_ERR)
-			   == HERMES_RXSTAT_UNDECRYPTABLE) {
-			wstats->discard.code++;
-			printk(KERN_WARNING "%s: Undecryptable frame on Rx. Frame dropped.\n",
-			       dev->name);
-		} else {
-			wstats->discard.misc++;
-			printk("%s: Unknown Rx error (0x%x). Frame dropped.\n",
-			       dev->name, status & HERMES_RXSTAT_ERR);
-		}
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	length = le16_to_cpu(hdr.p80211.data_len);
-	/* Yes, you heard right, that's le16. 802.2 and 802.3 are
-	   big-endian, but 802.11 is little-endian believe it or
-	   not. */
-	/* Correct. 802.3 is big-endian byte order and little endian bit
-	 * order, whereas 802.11 is little endian for both byte and bit
-	 * order. That's specified in the 802.11 spec. - Jean II */
-	
-	/* Sanity check */
-	if (length > MAX_FRAME_SIZE) {
-		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
-		       dev->name, length);
-		stats->rx_length_errors++;
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	/* We need space for the packet data itself, plus an ethernet
-	   header, plus 2 bytes so we can align the IP header on a
-	   32bit boundary, plus 1 byte so we can read in odd length
-	   packets from the card, which has an IO granularity of 16
-	   bits */  
-	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
-	if (!skb) {
-		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
-		       dev->name);
-		stats->rx_dropped++;
-		goto drop;
-	}
-
-	skb_reserve(skb, 2); /* This way the IP header is aligned */
-
-	/* Handle decapsulation */
-	switch (status & HERMES_RXSTAT_MSGTYPE) {
-		/* These both indicate a SNAP within 802.2 LLC within
-		   802.3 within 802.11 frame which we'll need to
-		   de-encapsulate. IEEE and ISO OSI have a lot to
-		   answer for.  */
-	case HERMES_RXSTAT_1042:
-	case HERMES_RXSTAT_TUNNEL:
-		data_len = length - ENCAPS_OVERHEAD;
-		data_off = sizeof(hdr);
-
-		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
-
-		memcpy(eh, &hdr.p8023, sizeof(hdr.p8023));
-		eh->h_proto = hdr.ethertype;
-
-		break;
-
-		/* Otherwise, we just throw the whole thing in, and hope
-		   the protocol layer can deal with it as 802.3 */
-	default:
-		data_len = length;
-		data_off = P8023_OFFSET;
-		break;
-	}
-
-	p = skb_put(skb, data_len);
-	if (hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
-			     rxfid, data_off) != 0) {
-		printk(KERN_WARNING "%s: Error reading packet data\n",
-		       dev->name);
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	dev->last_rx = jiffies;
-	skb->dev = dev;
-	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_NONE;
-	
-	/* Process the wireless stats if needed */
-	dldwd_stat_gather(dev, skb, &hdr);
-
-	/* Pass the packet to the networking stack */
-	netif_rx(skb);
-	stats->rx_packets++;
-	stats->rx_bytes += length;
-
-	return;
-
- drop:	
-	if (skb)
-		dev_kfree_skb_irq(skb);
-	return;
-}
-
-static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw)
-{
-	struct net_device *dev = &priv->ndev;
-	struct net_device_stats *stats = &priv->stats;
-
-	printk(KERN_WARNING "%s: Tx error!\n", dev->name);
-
-	netif_wake_queue(dev);
-	stats->tx_errors++;
-}
-
-static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw)
-{
-	struct net_device *dev = &priv->ndev;
-	struct net_device_stats *stats = &priv->stats;
-
-	DEBUG(3, "%s: Transmit completed\n", dev->name);
-
-	stats->tx_packets++;
-	netif_wake_queue(dev);
-}
-
-static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw)
-{
-	uint16_t allocfid;
-
-	allocfid = hermes_read_regn(hw, ALLOCFID);
-	DEBUG(3, "%s: Allocation complete FID=0x%04x\n", priv->ndev.name, allocfid);
-
-	/* For some reason we don't seem to get transmit completed events properly */
-	if (allocfid == priv->txfid)
-		__dldwd_ev_tx(priv, hw);
-
-/* 	hermes_write_regn(hw, ALLOCFID, 0); */
-}
-
-/*
- * struct net_device methods
- */
-
-static int dldwd_init(struct net_device *dev)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	hermes_id_t nickbuf;
-	uint16_t reclen;
-	int len;
-	char *vendor_str;
-	uint32_t firmver;
-
-	TRACE_ENTER("dldwd");
-	
-	dldwd_lock(priv);
-
-	err = hermes_reset(hw);
-	if (err != 0) {
-		printk(KERN_ERR "%s: failed to reset hardware\n", dev->name);
-		goto out;
-	}
-	
-	/* Get the firmware version */
-	err = hermes_read_staidentity(hw, USER_BAP, &priv->firmware_info);
-	if (err) {
-		printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",
-		       dev->name, err);
-		memset(&priv->firmware_info, 0, sizeof(priv->firmware_info));
-	}
-
-	firmver = ((uint32_t)priv->firmware_info.major << 16) | priv->firmware_info.minor;
-	DEBUG(2, "%s: firmver = 0x%X\n", dev->name, firmver);
-
-	/* Determine capabilities from the firmware version */
-
-	switch (priv->firmware_info.vendor) {
-	case 0x1:
-		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
-		 * ELSA, Melco, HP, IBM, Dell 1150 cards */
-		vendor_str = "Lucent";
-		/* Lucent MAC : 00:60:1D:* & 00:02:2D:* */
-
-		priv->firmware_type = FIRMWARE_TYPE_LUCENT;
-		priv->broken_reset = 0;
-		priv->broken_allocate = 0;
-		priv->has_port3 = 1;		/* Still works in 7.28 */
-		priv->has_ibss = (firmver >= 0x60006);
-		priv->has_ibss_any = (firmver >= 0x60010);
-		priv->has_wep = (firmver >= 0x40020);
-		priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
-					  Gold cards from the others? */
-		priv->has_mwo = (firmver >= 0x60000);
-		priv->has_pm = (firmver >= 0x40020);
-		priv->has_retry = 0;
-		priv->has_preamble = 0;
-		/* Tested with Lucent firmware :
-		 *	1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
-		 * Tested CableTron firmware : 4.32 => Anton */
-		break;
-	case 0x2:
-		vendor_str = "Generic Prism II";
-		/* Some D-Link cards report vendor 0x02... */
-
-		priv->firmware_type = FIRMWARE_TYPE_PRISM2;
-		priv->broken_reset = 0;
-		priv->broken_allocate = 0;
-		priv->has_port3 = 1;
-		priv->has_ibss = (firmver >= 0x00007); /* FIXME */
-		priv->has_wep = (firmver >= 0x00007); /* FIXME */
-		priv->has_big_wep = 0;
-		priv->has_mwo = 0;
-		priv->has_pm = (firmver >= 0x00007); /* FIXME */
-		priv->has_retry = 0;
-		priv->has_preamble = 0;
-
-		/* Tim Hurley -> D-Link card, vendor 02, firmware 0.08 */
-
-		/* Special case for Symbol cards */
-		if(firmver == 0x10001) {
-			/* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
-			vendor_str = "Symbol";
-			/* Intel MAC : 00:02:B3:* */
-			/* 3Com MAC : 00:50:DA:* */
-
-			/* FIXME : probably need to use SYMBOL_***ARY_VER
-			 * to get proper firmware version */
-			priv->firmware_type = FIRMWARE_TYPE_SYMBOL;
-			priv->broken_reset = 0;
-			priv->broken_allocate = 1;
-			priv->has_port3 = 1;
-			priv->has_ibss = 1; /* FIXME */
-			priv->has_wep = 1; /* FIXME */
-			priv->has_big_wep = 1;	/* RID_SYMBOL_KEY_LENGTH */
-			priv->has_mwo = 0;
-			priv->has_pm = 1; /* FIXME */
-			priv->has_retry = 0;
-			priv->has_preamble = 0; /* FIXME */
-			/* Tested with Intel firmware : v15 => Jean II */
-		}
-		break;
-	case 0x3:
-		vendor_str = "Samsung";
-		/* To check - Should cover Samsung & Compaq */
-
-		priv->firmware_type = FIRMWARE_TYPE_PRISM2;
-		priv->broken_reset = 0;
-		priv->broken_allocate = 0;
-		priv->has_port3 = 1;
-		priv->has_ibss = 0; /* FIXME: available in later firmwares */
-		priv->has_wep = (firmver >= 0x20000); /* FIXME */
-		priv->has_big_wep = 0; /* FIXME */
-		priv->has_mwo = 0;
-		priv->has_pm = (firmver >= 0x20000); /* FIXME */
-		priv->has_retry = 0;
-		priv->has_preamble = 0;
-		break;
-	case 0x6:
-		/* D-Link DWL 650, ... */
-		vendor_str = "LinkSys/D-Link";
-		/* D-Link MAC : 00:40:05:* */
-
-		priv->firmware_type = FIRMWARE_TYPE_PRISM2;
-		priv->broken_reset = 0;
-		priv->broken_allocate = 0;
-		priv->has_port3 = 1;
-		priv->has_ibss = (firmver >= 0x00007); /* FIXME */
-		priv->has_wep = (firmver >= 0x00007); /* FIXME */
-		priv->has_big_wep = 0;
-		priv->has_mwo = 0;
-		priv->has_pm = (firmver >= 0x00007); /* FIXME */
-		priv->has_retry = 0;
-		priv->has_preamble = 0;
-		/* Tested with D-Link firmware 0.07 => Jean II */
-		/* Note : with 0.07, IBSS to a Lucent card seem flaky */
-		break;
-	default:
-		vendor_str = "UNKNOWN";
-
-		priv->firmware_type = 0;
-		priv->broken_reset = 0;
-		priv->broken_allocate = 0;
-		priv->has_port3 = 0;
-		priv->has_ibss = 0;
-		priv->has_wep = 0;
-		priv->has_big_wep = 0;
-		priv->has_mwo = 0;
-		priv->has_pm = 0;
-		priv->has_retry = 0;
-		priv->has_preamble = 0;
-	}
-
-	printk(KERN_INFO "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n",
-	       dev->name, priv->firmware_info.id, priv->firmware_info.vendor,
-	       vendor_str, priv->firmware_info.major, priv->firmware_info.minor);
-	
-	if (priv->has_port3)
-		printk(KERN_INFO "%s: Ad-hoc demo mode supported.\n", dev->name);
-	if (priv->has_ibss)
-		printk(KERN_INFO "%s: IEEE standard IBSS ad-hoc mode supported.\n",
-		       dev->name);
-	if (priv->has_wep) {
-		printk(KERN_INFO "%s: WEP supported, ", dev->name);
-		if (priv->has_big_wep)
-			printk("\"128\"-bit key.\n");
-		else
-			printk("40-bit key.\n");
-	}
-
-	/* Get the MAC address */
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNF_MACADDR,
-			      ETH_ALEN, NULL, dev->dev_addr);
-	if (err) {
-		printk(KERN_WARNING "%s: failed to read MAC address!\n",
-		       dev->name);
-		goto out;
-	}
-
-	printk(KERN_INFO "%s: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
-	       dev->name, dev->dev_addr[0], dev->dev_addr[1],
-	       dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4],
-	       dev->dev_addr[5]);
-
-	/* Get the station name */
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNF_NICKNAME,
-			      sizeof(nickbuf), &reclen, &nickbuf);
-	if (err) {
-		printk(KERN_ERR "%s: failed to read station name!n",
-		       dev->name);
-		goto out;
-	}
-	if ( nickbuf.len )
-		len = MIN(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));
-	else
-		len = MIN(IW_ESSID_MAX_SIZE, 2 * reclen);
-	memcpy(priv->nick, &nickbuf.val, len);
-	priv->nick[len] = '\0';
-
-	printk(KERN_INFO "%s: Station name \"%s\"\n", dev->name, priv->nick);
-
-	/* Get allowed channels */
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNEL_LIST, &priv->channel_mask);
-	if (err) {
-		printk(KERN_ERR "%s: failed to read channel list!\n",
-		       dev->name);
-		goto out;
-	}
-
-	/* Get initial AP density */
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, &priv->ap_density);
-	if (err) {
-		printk(KERN_ERR "%s: failed to read AP density!\n", dev->name);
-		goto out;
-	}
-
-	/* Get initial RTS threshold */
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, &priv->rts_thresh);
-	if (err) {
-		printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name);
-		goto out;
-	}
-
-	/* Get initial fragmentation settings */
-	if (priv->has_mwo)
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_MWO_ROBUST,
-					  &priv->mwo_robust);
-	else
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH,
-					  &priv->frag_thresh);
-	if (err) {
-		printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name);
-		goto out;
-	}
-
-	/* Set initial bitrate control*/
-	priv->tx_rate_ctrl = 3;
-
-	/* Power management setup */
-	if (priv->has_pm) {
-		priv->pm_on = 0;
-		priv->pm_mcast = 1;
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD,
-					  &priv->pm_period);
-		if (err) {
-			printk(KERN_ERR "%s: failed to read power management period!\n",
-			       dev->name);
-			goto out;
-		}
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER,
-					  &priv->pm_timeout);
-		if (err) {
-			printk(KERN_ERR "%s: failed to read power management timeout!\n",
-			       dev->name);
-			goto out;
-		}
-	}
-
-	/* Retry setup */
-	if (priv->has_retry) {
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, &priv->retry_short);
-		if (err)
-			goto out;
-
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT, &priv->retry_long);
-		if (err)
-			goto out;
-
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME, &priv->retry_time);
-		if (err)
-			goto out;
-	}
-		
-	/* Preamble setup */
-	if (priv->has_preamble) {
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE, &priv->preamble);
-		if (err)
-			goto out;
-	}
-		
-	/* Set up the default configuration */
-	priv->iw_mode = IW_MODE_INFRA;
-	/* By default use IEEE/IBSS ad-hoc mode if we have it */
-	priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
-	set_port_type(priv);
-
-	priv->promiscuous = 0;
-	priv->allmulti = 0;
-	priv->wep_on = 0;
-	priv->tx_key = 0;
-
-	printk(KERN_INFO "%s: ready\n", dev->name);
-
- out:
-	dldwd_unlock(priv);
-
-	TRACE_EXIT("dldwd");
-
-	return err;
-}
-
-static int dldwd_open(struct net_device *dev)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	dev_link_t *link = &priv->link;
-	int err = 0;
-	
-	TRACE_ENTER(dev->name);
-
-	link->open++;
-	MOD_INC_USE_COUNT;
-	netif_device_attach(dev);
-	
-	err = dldwd_reset(priv);
-	if (err)
-		dldwd_stop(dev);
-	else
-		netif_start_queue(dev);
-
-	TRACE_EXIT(dev->name);
-
-	return err;
-}
-
-static int dldwd_stop(struct net_device *dev)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	dev_link_t *link = &priv->link;
-
-	TRACE_ENTER(dev->name);
-
-	netif_stop_queue(dev);
-
-	dldwd_shutdown(priv);
-	
-	link->open--;
-
-	if (link->state & DEV_STALE_CONFIG)
-		mod_timer(&link->release, jiffies + HZ/20);
-	
-	MOD_DEC_USE_COUNT;
-
-	TRACE_EXIT(dev->name);
-	
-	return 0;
-}
-
-static struct net_device_stats *dldwd_get_stats(struct net_device *dev)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	
-	return &priv->stats;
-}
-
-static struct iw_statistics *dldwd_get_wireless_stats(struct net_device *dev)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	hermes_t *hw = &priv->hw;
-	struct iw_statistics *wstats = &priv->wstats;
-	int err = 0;
-	hermes_commsqual_t cq;
-
-	dldwd_lock(priv);
-
-	if (priv->port_type == 3) {
-		memset(&wstats->qual, 0, sizeof(wstats->qual));
-#ifdef WIRELESS_SPY
-		/* If a spy address is defined, we report stats of the
-		 * first spy address - Jean II */
-		if (priv->spy_number > 0) {
-			wstats->qual.qual = priv->spy_stat[0].qual;
-			wstats->qual.level = priv->spy_stat[0].level;
-			wstats->qual.noise = priv->spy_stat[0].noise;
-			wstats->qual.updated = priv->spy_stat[0].updated;
-		}
-#endif /* WIRELESS_SPY */
-	} else {
-		err = hermes_read_commsqual(hw, USER_BAP, &cq);
-		
-		DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name,
-		      cq.qual, cq.signal, cq.noise);
-
-		/* Why are we using MIN/MAX ? We don't really care
-		 * if the value goes above max, because we export the
-		 * raw dBm values anyway. The normalisation should be done
-		 * in user space - Jean II */
-		wstats->qual.qual = MAX(MIN(cq.qual, 0x8b-0x2f), 0);
-		wstats->qual.level = MAX(MIN(cq.signal, 0x8a), 0x2f) - 0x95;
-		wstats->qual.noise = MAX(MIN(cq.noise, 0x8a), 0x2f) - 0x95;
-		wstats->qual.updated = 7;
-	}
-
-	dldwd_unlock(priv);
-
-	if (err)
-		return NULL;
-		
-	return wstats;
-}
-
-#ifdef WIRELESS_SPY
-static inline void dldwd_spy_gather(struct net_device *dev,
-				    u_char *mac,
-				    hermes_commsqual_t *cq)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	int i;
-
-	/* Gather wireless spy statistics: for each packet, compare the
-	 * source address with out list, and if match, get the stats... */
-	for (i = 0; i < priv->spy_number; i++)
-		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
-			priv->spy_stat[i].qual = MAX(MIN(cq->qual, 0x8b-0x2f), 0);
-			priv->spy_stat[i].level = MAX(MIN(cq->signal, 0x8a), 0x2f) - 0x95;
-			priv->spy_stat[i].noise = MAX(MIN(cq->noise, 0x8a), 0x2f) - 0x95;
-			priv->spy_stat[i].updated = 7;
-		}
-}
-#endif /* WIRELESS_SPY */
-
-static void dldwd_stat_gather(struct net_device *dev,
-			      struct sk_buff *skb,
-			      struct dldwd_frame_hdr *hdr)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	hermes_commsqual_t cq;
-
-	/* Using spy support with lots of Rx packets, like in an
-	 * infrastructure (AP), will really slow down everything, because
-	 * the MAC address must be compared to each entry of the spy list.
-	 * If the user really asks for it (set some address in the
-	 * spy list), we do it, but he will pay the price.
-	 * Note that to get here, you need both WIRELESS_SPY
-	 * compiled in AND some addresses in the list !!!
-	 */
-#ifdef WIRELESS_EXT
-	/* Note : gcc will optimise the whole section away if
-	 * WIRELESS_SPY is not defined... - Jean II */
-	if (
-#ifdef WIRELESS_SPY
-		(priv->spy_number > 0) ||
-#endif
-		0 )
-	{
-		u_char *stats = (u_char *) &(hdr->desc.q_info);
-		/* This code may look strange. Everywhere we are using 16 bit
-		 * ints except here. I've verified that these are are the
-		 * correct values. Please check on PPC - Jean II */
-		cq.signal = stats[1];	/* High order byte */
-		cq.noise = stats[0];	/* Low order byte */
-		cq.qual = stats[0] - stats[1];	/* Better than nothing */
-
-		DEBUG(3, "%s: Packet stats = %X-%X-%X\n", dev->name,
-		      cq.qual, cq.signal, cq.noise);
-
-#ifdef WIRELESS_SPY
-		dldwd_spy_gather(dev, skb->mac.raw + ETH_ALEN, &cq);  
-#endif
-	}
-#endif /* WIRELESS_EXT */
-}
-
-struct p8022_hdr encaps_hdr = {
-	0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}
-};
-
-static int dldwd_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	struct net_device_stats *stats = &priv->stats;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	uint16_t txfid = priv->txfid;
-	char *p;
-	struct ethhdr *eh;
-	int len, data_len, data_off;
-	struct dldwd_frame_hdr hdr;
-	hermes_response_t resp;
-
-	if (! netif_running(dev)) {
-		printk(KERN_ERR "%s: Tx on stopped device!\n",
-		       dev->name);
-		return 1;
-
-	}
-	
-	if (netif_queue_stopped(dev)) {
-		printk(KERN_ERR "%s: Tx while transmitter busy!\n", 
-		       dev->name);
-		return 1;
-	}
-	
-	dldwd_lock(priv);
-
-	/* Length of the packet body */
-	len = MAX(skb->len - ETH_HLEN, ETH_ZLEN);
-
-	eh = (struct ethhdr *)skb->data;
-
-	/* Build the IEEE 802.11 header */
-	memset(&hdr, 0, sizeof(hdr));
-	memcpy(hdr.p80211.addr1, eh->h_dest, ETH_ALEN);
-	memcpy(hdr.p80211.addr2, eh->h_source, ETH_ALEN);
-	hdr.p80211.frame_ctl = DLDWD_FTYPE_DATA;
-
-	/* Encapsulate Ethernet-II frames */
-	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
-		data_len = len;
-		data_off = sizeof(hdr);
-		p = skb->data + ETH_HLEN;
-
-		/* 802.11 header */
-		hdr.p80211.data_len = cpu_to_le16(data_len + ENCAPS_OVERHEAD);
-
-		/* 802.3 header */
-		memcpy(hdr.p8023.h_dest, eh->h_dest, ETH_ALEN);
-		memcpy(hdr.p8023.h_source, eh->h_source, ETH_ALEN);
-		hdr.p8023.h_proto = htons(data_len + ENCAPS_OVERHEAD);
-		
-		/* 802.2 header */
-		memcpy(&hdr.p8022, &encaps_hdr, sizeof(encaps_hdr));
-
-		hdr.ethertype = eh->h_proto;
-		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
-					 txfid, 0);
-		if (err) {
-			printk(KERN_ERR
-			       "%s: Error %d writing packet header to BAP\n",
-			       dev->name, err);
-			stats->tx_errors++;
-			goto fail;
-		}
-	} else { /* IEEE 802.3 frame */
-		data_len = len + ETH_HLEN;
-		data_off = P8023_OFFSET;
-		p = skb->data;
-		
-		/* 802.11 header */
-		hdr.p80211.data_len = cpu_to_le16(len);
-		err = hermes_bap_pwrite(hw, USER_BAP, &hdr, P8023_OFFSET,
-					txfid, 0);
-		if (err) {
-			printk(KERN_ERR
-			       "%s: Error %d writing packet header to BAP\n",
-			       dev->name, err);
-			stats->tx_errors++;
-			goto fail;
-		}
-	}
-
-	/* Round up for odd length packets */
-	err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d writing packet data to BAP\n",
-		       dev->name, err);
-		stats->tx_errors++;
-		goto fail;
-	}
-	
-
-	/* Finally, we actually initiate the send */
-	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, &resp);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);
-		stats->tx_errors++;
-		goto fail;
-	}
-
-	dev->trans_start = jiffies;
-	stats->tx_bytes += data_off + data_len;
-
-	netif_stop_queue(dev);
-
-	dldwd_unlock(priv);
-
-	dev_kfree_skb(skb);
-
-	return 0;
- fail:
-
-	dldwd_unlock(priv);
-	return err;
-}
-
-static void dldwd_tx_timeout(struct net_device *dev)
-{
-	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
-	struct net_device_stats *stats = &priv->stats;
-	int err = 0;
-
-	printk(KERN_WARNING "%s: Tx timeout! Resetting card.\n", dev->name);
-
-	stats->tx_errors++;
-
-	err = dldwd_reset(priv);
-	if (err)
-		printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",
-		       dev->name, err);
-	else {
-		dev->trans_start = jiffies;
-		netif_wake_queue(dev);
-	}
-}
-
-static int dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int err = 0;
-	int ptype;
-	struct iw_range range;
-	int numrates;
-	int i, k;
-
-	TRACE_ENTER(dev->name);
-
-	err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range));
-	if (err)
-		return err;
-
-	rrq->length = sizeof(range);
-
-	dldwd_lock(priv);
-	ptype = priv->port_type;
-	dldwd_unlock(priv);
-
-	memset(&range, 0, sizeof(range));
-
-	/* Much of this shamelessly taken from wvlan_cs.c. No idea
-	 * what it all means -dgibson */
-#if WIRELESS_EXT > 10
-	range.we_version_compiled = WIRELESS_EXT;
-	range.we_version_source = 11;
-#endif /* WIRELESS_EXT > 10 */
-
-	range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
-
-	/* Set available channels/frequencies */
-	range.num_channels = NUM_CHANNELS;
-	k = 0;
-	for (i = 0; i < NUM_CHANNELS; i++) {
-		if (priv->channel_mask & (1 << i)) {
-			range.freq[k].i = i + 1;
-			range.freq[k].m = channel_frequency[i] * 100000;
-			range.freq[k].e = 1;
-			k++;
-		}
-		
-		if (k >= IW_MAX_FREQUENCIES)
-			break;
-	}
-	range.num_frequency = k;
-
-	range.sensitivity = 3;
-
-	if ((ptype == 3) && (priv->spy_number == 0)){
-		/* Quality stats meaningless in ad-hoc mode */
-		range.max_qual.qual = 0;
-		range.max_qual.level = 0;
-		range.max_qual.noise = 0;
-	} else {
-		range.max_qual.qual = 0x8b - 0x2f;
-		range.max_qual.level = 0x2f - 0x95 - 1;
-		range.max_qual.noise = 0x2f - 0x95 - 1;
-	}
-
-	err = dldwd_hw_get_bitratelist(priv, &numrates,
-				       range.bitrate, IW_MAX_BITRATES);
-	if (err)
-		return err;
-	range.num_bitrates = numrates;
-	
-	/* Set an indication of the max TCP throughput in bit/s that we can
-	 * expect using this interface. May be use for QoS stuff...
-	 * Jean II */
-	if(numrates > 2)
-		range.throughput = 5 * 1000 * 1000;	/* ~5 Mb/s */
-	else
-		range.throughput = 1.5 * 1000 * 1000;	/* ~1.5 Mb/s */
-
-	range.min_rts = 0;
-	range.max_rts = 2347;
-	range.min_frag = 256;
-	range.max_frag = 2346;
-
-	dldwd_lock(priv);
-	if (priv->has_wep) {
-		range.max_encoding_tokens = MAX_KEYS;
-
-		range.encoding_size[0] = SMALL_KEY_SIZE;
-		range.num_encoding_sizes = 1;
-
-		if (priv->has_big_wep) {
-			range.encoding_size[1] = LARGE_KEY_SIZE;
-			range.num_encoding_sizes = 2;
-		}
-	} else {
-		range.num_encoding_sizes = 0;
-		range.max_encoding_tokens = 0;
-	}
-	dldwd_unlock(priv);
-		
-	range.min_pmp = 0;
-	range.max_pmp = 65535000;
-	range.min_pmt = 0;
-	range.max_pmt = 65535 * 1000;	/* ??? */
-	range.pmp_flags = IW_POWER_PERIOD;
-	range.pmt_flags = IW_POWER_TIMEOUT;
-	range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
-
-	range.num_txpower = 1;
-	range.txpower[0] = 15; /* 15dBm */
-	range.txpower_capa = IW_TXPOW_DBM;
-
-#if WIRELESS_EXT > 10
-	range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
-	range.retry_flags = IW_RETRY_LIMIT;
-	range.r_time_flags = IW_RETRY_LIFETIME;
-	range.min_retry = 0;
-	range.max_retry = 65535;	/* ??? */
-	range.min_r_time = 0;
-	range.max_r_time = 65535 * 1000;	/* ??? */
-#endif /* WIRELESS_EXT > 10 */
-
-	if (copy_to_user(rrq->pointer, &range, sizeof(range)))
-		return -EFAULT;
-
-	TRACE_EXIT(dev->name);
-
-	return 0;
-}
-
-static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
-	int setindex = priv->tx_key;
-	int enable = priv->wep_on;
-	int restricted = priv->wep_restrict;
-	uint16_t xlen = 0;
-	int err = 0;
-	char keybuf[MAX_KEY_SIZE];
-
-	if (erq->pointer) {
-		/* We actually have a key to set */
-		
-		if (copy_from_user(keybuf, erq->pointer, erq->length))
-			return -EFAULT;
-	}
-	
-	dldwd_lock(priv);
-	
-	if (erq->pointer) {
-		if (erq->length > MAX_KEY_SIZE) {
-			err = -E2BIG;
-			goto out;
-		}
-		
-		if ( (erq->length > LARGE_KEY_SIZE)
-		     || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE))  ) {
-			err = -EINVAL;
-			goto out;
-		}
-		
-		if ((index < 0) || (index >= MAX_KEYS))
-			index = priv->tx_key;
-		
-		if (erq->length > SMALL_KEY_SIZE) {
-			xlen = LARGE_KEY_SIZE;
-		} else if (erq->length > 0) {
-			xlen = SMALL_KEY_SIZE;
-		} else
-			xlen = 0;
-		
-		/* Switch on WEP if off */
-		if ((!enable) && (xlen > 0)) {
-			setindex = index;
-			enable = 1;
-		}
-	} else {
-		/* Important note : if the user do "iwconfig eth0 enc off",
-		 * we will arrive there with an index of -1. This is valid
-		 * but need to be taken care off... Jean II */
-		if ((index < 0) || (index >= MAX_KEYS)) {
-			if((index != -1) || (erq->flags == 0)) {
-				err = -EINVAL;
-				goto out;
-			}
-		} else {
-			/* Set the index : Check that the key is valid */
-			if(priv->keys[index].len == 0) {
-				err = -EINVAL;
-				goto out;
-			}
-			setindex = index;
-		}
-	}
-	
-	if (erq->flags & IW_ENCODE_DISABLED)
-		enable = 0;
-	/* Only for Prism2 & Symbol cards (so far) - Jean II */
-	if (erq->flags & IW_ENCODE_OPEN)
-		restricted = 0;
-	if (erq->flags & IW_ENCODE_RESTRICTED)
-		restricted = 1;
-
-	if (erq->pointer) {
-		priv->keys[index].len = cpu_to_le16(xlen);
-		memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data));
-		memcpy(priv->keys[index].data, keybuf, erq->length);
-	}
-	priv->tx_key = setindex;
-	priv->wep_on = enable;
-	priv->wep_restrict = restricted;
-	
- out:
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-static int dldwd_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
-	uint16_t xlen = 0;
-	char keybuf[MAX_KEY_SIZE];
-
-	
-	dldwd_lock(priv);
-
-	if ((index < 0) || (index >= MAX_KEYS))
-		index = priv->tx_key;
-
-	erq->flags = 0;
-	if (! priv->wep_on)
-		erq->flags |= IW_ENCODE_DISABLED;
-	erq->flags |= index + 1;
-	
-	/* Only for symbol cards - Jean II */
-	if (priv->firmware_type != FIRMWARE_TYPE_LUCENT) {
-		if(priv->wep_restrict)
-			erq->flags |= IW_ENCODE_RESTRICTED;
-		else
-			erq->flags |= IW_ENCODE_OPEN;
-	}
-
-	xlen = le16_to_cpu(priv->keys[index].len);
-
-	erq->length = xlen;
-
-	if (erq->pointer) {
-		memcpy(keybuf, priv->keys[index].data, MAX_KEY_SIZE);
-	}
-	
-	dldwd_unlock(priv);
-
-	if (erq->pointer) {
-		if (copy_to_user(erq->pointer, keybuf, xlen))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int dldwd_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	char essidbuf[IW_ESSID_MAX_SIZE+1];
-
-	/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
-	 * anyway... - Jean II */
-
-	memset(&essidbuf, 0, sizeof(essidbuf));
-
-	if (erq->flags) { 
-		if (erq->length > IW_ESSID_MAX_SIZE)
-			return -E2BIG;
-		
-		if (copy_from_user(&essidbuf, erq->pointer, erq->length))
-			return -EFAULT;
-
-		essidbuf[erq->length] = '\0';
-	}
-
-	dldwd_lock(priv);
-
-	memcpy(priv->desired_essid, essidbuf, IW_ESSID_MAX_SIZE+1);
-
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-static int dldwd_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	char essidbuf[IW_ESSID_MAX_SIZE+1];
-	int active;
-	int err = 0;
-
-	TRACE_ENTER(dev->name);
-
-	err = dldwd_hw_get_essid(priv, &active, essidbuf);
-	if (err)
-		return err;
-
-	erq->flags = 1;
-	erq->length = strlen(essidbuf) + 1;
-	if (erq->pointer)
-		if ( copy_to_user(erq->pointer, essidbuf, erq->length) )
-			return -EFAULT;
-
-	TRACE_EXIT(dev->name);
-	
-	return 0;
-}
-
-static int dldwd_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	char nickbuf[IW_ESSID_MAX_SIZE+1];
-
-	if (nrq->length > IW_ESSID_MAX_SIZE)
-		return -E2BIG;
-
-	memset(nickbuf, 0, sizeof(nickbuf));
-
-	if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
-		return -EFAULT;
-
-	nickbuf[nrq->length] = '\0';
-	
-	dldwd_lock(priv);
-
-	memcpy(priv->nick, nickbuf, sizeof(priv->nick));
-
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-static int dldwd_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	char nickbuf[IW_ESSID_MAX_SIZE+1];
-
-	dldwd_lock(priv);
-	memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
-	dldwd_unlock(priv);
-
-	nrq->length = strlen(nickbuf)+1;
-
-	if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int dldwd_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int chan = -1;
-
-	/* We can only use this in Ad-Hoc demo mode to set the operating
-	 * frequency, or in IBSS mode to set the frequency where the IBSS
-	 * will be created - Jean II */
-	if (priv->iw_mode != IW_MODE_ADHOC)
-		return -EOPNOTSUPP;
-
-	if ( (frq->e == 0) && (frq->m <= 1000) ) {
-		/* Setting by channel number */
-		chan = frq->m;
-	} else {
-		/* Setting by frequency - search the table */
-		int mult = 1;
-		int i;
-
-		for (i = 0; i < (6 - frq->e); i++)
-			mult *= 10;
-
-		for (i = 0; i < NUM_CHANNELS; i++)
-			if (frq->m == (channel_frequency[i] * mult))
-				chan = i+1;
-	}
-
-	if ( (chan < 1) || (chan > NUM_CHANNELS) ||
-	     ! (priv->channel_mask & (1 << (chan-1)) ) )
-		return -EINVAL;
-
-	dldwd_lock(priv);
-	priv->channel = chan;
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-static int dldwd_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	uint16_t val;
-	int err;
-
-	dldwd_lock(priv);
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, &val);
-	dldwd_unlock(priv);
-
-	if (err)
-		return err;
-
-	srq->value = val;
-	srq->fixed = 0; /* auto */
-
-	return 0;
-}
-
-static int dldwd_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int val = srq->value;
-
-	if ((val < 1) || (val > 3))
-		return -EINVAL;
-	
-	dldwd_lock(priv);
-	priv->ap_density = val;
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-static int dldwd_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int val = rrq->value;
-
-	if (rrq->disabled)
-		val = 2347;
-
-	if ( (val < 0) || (val > 2347) )
-		return -EINVAL;
-
-	dldwd_lock(priv);
-	priv->rts_thresh = val;
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-static int dldwd_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int err = 0;
-
-	dldwd_lock(priv);
-
-	if (priv->has_mwo) {
-		if (frq->disabled)
-			priv->mwo_robust = 0;
-		else {
-			if (frq->fixed)
-				printk(KERN_WARNING "%s: Fixed fragmentation not \
-supported on this firmware. Using MWO robust instead.\n", dev->name);
-			priv->mwo_robust = 1;
-		}
-	} else {
-		if (frq->disabled)
-			priv->frag_thresh = 2346;
-		else {
-			if ( (frq->value < 256) || (frq->value > 2346) )
-				err = -EINVAL;
-			else
-				priv->frag_thresh = frq->value & ~0x1; /* must be even */
-		}
-	}
-
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	uint16_t val;
-
-	dldwd_lock(priv);
-	
-	if (priv->has_mwo) {
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_MWO_ROBUST, &val);
-		if (err)
-			val = 0;
-
-		frq->value = val ? 2347 : 0;
-		frq->disabled = ! val;
-		frq->fixed = 0;
-	} else {
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH, &val);
-		if (err)
-			val = 0;
-
-		frq->value = val;
-		frq->disabled = (val >= 2346);
-		frq->fixed = 1;
-	}
-
-	dldwd_unlock(priv);
-	
-	return err;
-}
-
-static int dldwd_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int err = 0;
-	int rate_ctrl = -1;
-	int fixed, upto;
-	int brate;
-	int i;
-
-	dldwd_lock(priv);
-
-	/* Normalise value */
-	brate = rrq->value / 500000;
-
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_LUCENT: /* Lucent style rate */
-		if (! rrq->fixed) {
-			if (brate > 0)
-				brate = -brate;
-			else
-				brate = -22;
-		}
-	
-		for (i = 0; i < NUM_RATES; i++)
-			if (rate_list[i] == brate) {
-				rate_ctrl = i;
-				break;
-			}
-	
-		if ( (rate_ctrl < 1) || (rate_ctrl >= NUM_RATES) )
-			err = -EINVAL;
-		else
-			priv->tx_rate_ctrl = rate_ctrl;
-		break;
-	case FIRMWARE_TYPE_PRISM2: /* Prism II style rate */
-	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
-		switch(brate) {
-		case 0:
-			fixed = 0x0;
-			upto = 0x15;
-			break;
-		case 2:
-			fixed = 0x1;
-			upto = 0x1;
-			break;
-		case 4:
-			fixed = 0x2;
-			upto = 0x3;
-			break;
-		case 11:
-			fixed = 0x4;
-			upto = 0x7;
-			break;
-		case 22:
-			fixed = 0x8;
-			upto = 0x15;
-			break;
-		default:
-			fixed = 0x0;
-			upto = 0x0;
-		}
-		if (rrq->fixed)
-			rate_ctrl = fixed;
-		else
-			rate_ctrl = upto;
-		if (rate_ctrl == 0)
-			err = -EINVAL;
-		else
-			priv->tx_rate_ctrl = rate_ctrl;
-		break;
-	}
-
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	uint16_t val;
-	int brate = 0;
-
-	dldwd_lock(priv);
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_RATE_CTRL, &val);
-	if (err)
-		goto out;
-	
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_LUCENT: /* Lucent style rate */
-		brate = rate_list[val];
-	
-		if (brate < 0) {
-			rrq->fixed = 0;
-
-			err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_TX_RATE, &val);
-			if (err)
-				goto out;
-
-			if (val == 6)
-				brate = 11;
-			else
-				brate = 2*val;
-		} else
-			rrq->fixed = 1;
-		break;
-	case FIRMWARE_TYPE_PRISM2: /* Prism II style rate */
-	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
-		/* Check if auto or fixed (crude approximation) */
-		if((val & 0x1) && (val > 1)) {
-			rrq->fixed = 0;
-
-			err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_TX_RATE, &val);
-			if (err)
-				goto out;
-		} else
-			rrq->fixed = 1;
-
-		if(val >= 8)
-			brate = 22;
-		else if(val >= 4)
-			brate = 11;
-		else if(val >= 2)
-			brate = 4;
-		else
-			brate = 2;
-		break;
-	}
-
-	rrq->value = brate * 500000;
-	rrq->disabled = 0;
-
- out:
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int err = 0;
-
-
-	dldwd_lock(priv);
-
-	if (prq->disabled) {
-		priv->pm_on = 0;
-	} else {
-		switch (prq->flags & IW_POWER_MODE) {
-		case IW_POWER_UNICAST_R:
-			priv->pm_mcast = 0;
-			priv->pm_on = 1;
-			break;
-		case IW_POWER_ALL_R:
-			priv->pm_mcast = 1;
-			priv->pm_on = 1;
-			break;
-		case IW_POWER_ON:
-			/* No flags : but we may have a value - Jean II */
-			break;
-		default:
-			err = -EINVAL;
-		}
-		if (err)
-			goto out;
-		
-		if (prq->flags & IW_POWER_TIMEOUT) {
-			priv->pm_on = 1;
-			priv->pm_timeout = prq->value / 1000;
-		}
-		if (prq->flags & IW_POWER_PERIOD) {
-			priv->pm_on = 1;
-			priv->pm_period = prq->value / 1000;
-		}
-		/* It's valid to not have a value if we are just toggling
-		 * the flags... Jean II */
-		if(!priv->pm_on) {
-			err = -EINVAL;
-			goto out;
-		}			
-	}
-
- out:
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	uint16_t enable, period, timeout, mcast;
-
-	dldwd_lock(priv);
-	
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_ENABLE, &enable);
-	if (err)
-		goto out;
-
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD, &period);
-	if (err)
-		goto out;
-
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER, &timeout);
-	if (err)
-		goto out;
-
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_MCAST_RX, &mcast);
-	if (err)
-		goto out;
-
-	prq->disabled = !enable;
-	/* Note : by default, display the period */
-	if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-		prq->flags = IW_POWER_TIMEOUT;
-		prq->value = timeout * 1000;
-	} else {
-		prq->flags = IW_POWER_PERIOD;
-		prq->value = period * 1000;
-	}
-	if (mcast)
-		prq->flags |= IW_POWER_ALL_R;
-	else
-		prq->flags |= IW_POWER_UNICAST_R;
-
- out:
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-#if WIRELESS_EXT > 10
-static int dldwd_ioctl_setretry(struct net_device *dev, struct iw_param *rrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int err = 0;
-
-
-	dldwd_lock(priv);
-
-	if ((rrq->disabled) || (!priv->has_retry)){
-		err = -EOPNOTSUPP;
-		goto out;
-	} else {
-		if (rrq->flags & IW_RETRY_LIMIT) {
-			if (rrq->flags & IW_RETRY_MAX)
-				priv->retry_long = rrq->value;
-			else if (rrq->flags & IW_RETRY_MIN)
-				priv->retry_short = rrq->value;
-			else {
-				/* No modifier : set both */
-				priv->retry_long = rrq->value;
-				priv->retry_short = rrq->value;
-			}
-		}
-		if (rrq->flags & IW_RETRY_LIFETIME) {
-			priv->retry_time = rrq->value / 1000;
-		}
-		if ((rrq->flags & IW_RETRY_TYPE) == 0) {
-			err = -EINVAL;
-			goto out;
-		}			
-	}
-
- out:
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	uint16_t short_limit, long_limit, lifetime;
-
-	dldwd_lock(priv);
-	
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, &short_limit);
-	if (err)
-		goto out;
-
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT, &long_limit);
-	if (err)
-		goto out;
-
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME, &lifetime);
-	if (err)
-		goto out;
-
-	rrq->disabled = 0;		/* Can't be disabled */
-
-	/* Note : by default, display the retry number */
-	if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
-		rrq->flags = IW_RETRY_LIFETIME;
-		rrq->value = lifetime * 1000;	/* ??? */
-	} else {
-		/* By default, display the min number */
-		if ((rrq->flags & IW_RETRY_MAX)) {
-			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-			rrq->value = long_limit;
-		} else {
-			rrq->flags = IW_RETRY_LIMIT;
-			rrq->value = short_limit;
-			if(short_limit != long_limit)
-				rrq->flags |= IW_RETRY_MIN;
-		}
-	}
-
- out:
-	dldwd_unlock(priv);
-
-	return err;
-}
-#endif /* WIRELESS_EXT > 10 */
-
-static int dldwd_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int val = *( (int *) wrq->u.name );
-	int err = 0;
-
-	dldwd_lock(priv);
-	switch (val) {
-	case 0: /* Try to do IEEE ad-hoc mode */
-		if (! priv->has_ibss) {
-			err = -EINVAL;
-			break;
-		}
-		priv->prefer_port3 = 0;
-			
-		break;
-
-	case 1: /* Try to do Lucent proprietary ad-hoc mode */
-		if (! priv->has_port3) {
-			err = -EINVAL;
-			break;
-		}
-		priv->prefer_port3 = 1;
-		break;
-
-	default:
-		err = -EINVAL;
-	}
-
-	if (! err)
-		/* Actually update the mode we are using */
-		set_port_type(priv);
-
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	int *val = (int *)wrq->u.name;
-
-	dldwd_lock(priv);
-	*val = priv->prefer_port3;
-	dldwd_unlock(priv);
-
-	return 0;
-}
-
-/* Spy is used for link quality/strength measurements in Ad-Hoc mode
- * Jean II */
-static int dldwd_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	struct sockaddr address[IW_MAX_SPY];
-	int number = srq->length;
-	int i;
-	int err = 0;
-
-	/* Check the number of addresses */
-	if (number > IW_MAX_SPY)
-		return -E2BIG;
-
-	/* Get the data in the driver */
-	if (srq->pointer) {
-		if (copy_from_user(address, srq->pointer,
-				   sizeof(struct sockaddr) * number))
-			return -EFAULT;
-	}
-
-	/* Make sure nobody mess with the structure while we do */
-	dldwd_lock(priv);
-
-	/* dldwd_lock() doesn't disable interrupts, so make sure the
-	 * interrupt rx path don't get confused while we copy */
-	priv->spy_number = 0;
-
-	if (number > 0) {
-		/* Extract the addresses */
-		for (i = 0; i < number; i++)
-			memcpy(priv->spy_address[i], address[i].sa_data,
-			       ETH_ALEN);
-		/* Reset stats */
-		memset(priv->spy_stat, 0,
-		       sizeof(struct iw_quality) * IW_MAX_SPY);
-		/* Set number of addresses */
-		priv->spy_number = number;
-	}
-
-	/* Time to show what we have done... */
-	DEBUG(0, "%s: New spy list:\n", dev->name);
-	for (i = 0; i < number; i++) {
-		DEBUG(0, "%s: %d - %02x:%02x:%02x:%02x:%02x:%02x\n",
-		      dev->name, i+1,
-		      priv->spy_address[i][0], priv->spy_address[i][1],
-		      priv->spy_address[i][2], priv->spy_address[i][3],
-		      priv->spy_address[i][4], priv->spy_address[i][5]);
-	}
-
-	/* Now, let the others play */
-	dldwd_unlock(priv);
-
-	return err;
-}
-
-static int dldwd_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
-{
-	dldwd_priv_t *priv = dev->priv;
-	struct sockaddr address[IW_MAX_SPY];
-	struct iw_quality spy_stat[IW_MAX_SPY];
-	int number;
-	int i;
-
-	dldwd_lock(priv);
-
-	number = priv->spy_number;
-	if ((number > 0) && (srq->pointer)) {
-		/* Create address struct */
-		for (i = 0; i < number; i++) {
-			memcpy(address[i].sa_data, priv->spy_address[i],
-			       ETH_ALEN);
-			address[i].sa_family = AF_UNIX;
-		}
-		/* Copy stats */
-		/* In theory, we should disable irqs while copying the stats
-		 * because the rx path migh update it in the middle...
-		 * Bah, who care ? - Jean II */
-		memcpy(&spy_stat, priv->spy_stat,
-		       sizeof(struct iw_quality) * IW_MAX_SPY);
-		for (i=0; i < number; i++)
-			priv->spy_stat[i].updated = 0;
-	}
-
-	dldwd_unlock(priv);
-
-	/* Push stuff to user space */
-	srq->length = number;
-	if(copy_to_user(srq->pointer, address,
-			 sizeof(struct sockaddr) * number))
-		return -EFAULT;
-	if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
-			&spy_stat, sizeof(struct iw_quality) * number))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int dldwd_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	dldwd_priv_t *priv = dev->priv;
-	struct iwreq *wrq = (struct iwreq *)rq;
-	int err = 0;
-	int changed = 0;
-
-	TRACE_ENTER(dev->name);
-
-	switch (cmd) {
-	case SIOCGIWNAME:
-		DEBUG(1, "%s: SIOCGIWNAME\n", dev->name);
-		strcpy(wrq->u.name, "IEEE 802.11-DS");
-		break;
-		
-	case SIOCGIWAP:
-		DEBUG(1, "%s: SIOCGIWAP\n", dev->name);
-		wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
-		err = dldwd_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
-		break;
-
-	case SIOCGIWRANGE:
-		DEBUG(1, "%s: SIOCGIWRANGE\n", dev->name);
-		err = dldwd_ioctl_getiwrange(dev, &wrq->u.data);
-		break;
-
-	case SIOCSIWMODE:
-		DEBUG(1, "%s: SIOCSIWMODE\n", dev->name);
-		dldwd_lock(priv);
-		switch (wrq->u.mode) {
-		case IW_MODE_ADHOC:
-			if (! (priv->has_ibss || priv->has_port3) )
-				err = -EINVAL;
-			else {
-				priv->iw_mode = IW_MODE_ADHOC;
-				changed = 1;
-			}
-			break;
-
-		case IW_MODE_INFRA:
-			priv->iw_mode = IW_MODE_INFRA;
-			changed = 1;
-			break;
-
-		default:
-			err = -EINVAL;
-			break;
-		}
-		set_port_type(priv);
-		dldwd_unlock(priv);
-		break;
-
-	case SIOCGIWMODE:
-		DEBUG(1, "%s: SIOCGIWMODE\n", dev->name);
-		dldwd_lock(priv);
-		wrq->u.mode = priv->iw_mode;
-		dldwd_unlock(priv);
-		break;
-
-	case SIOCSIWENCODE:
-		DEBUG(1, "%s: SIOCSIWENCODE\n", dev->name);
-		if (! priv->has_wep) {
-			err = -EOPNOTSUPP;
-			break;
-		}
-
-		err = dldwd_ioctl_setiwencode(dev, &wrq->u.encoding);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWENCODE:
-		DEBUG(1, "%s: SIOCGIWENCODE\n", dev->name);
-		if (! priv->has_wep) {
-			err = -EOPNOTSUPP;
-			break;
-		}
-
-		if (! capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
-		}
-
-		err = dldwd_ioctl_getiwencode(dev, &wrq->u.encoding);
-		break;
-
-	case SIOCSIWESSID:
-		DEBUG(1, "%s: SIOCSIWESSID\n", dev->name);
-		err = dldwd_ioctl_setessid(dev, &wrq->u.essid);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWESSID:
-		DEBUG(1, "%s: SIOCGIWESSID\n", dev->name);
-		err = dldwd_ioctl_getessid(dev, &wrq->u.essid);
-		break;
-
-	case SIOCSIWNICKN:
-		DEBUG(1, "%s: SIOCSIWNICKN\n", dev->name);
-		err = dldwd_ioctl_setnick(dev, &wrq->u.data);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWNICKN:
-		DEBUG(1, "%s: SIOCGIWNICKN\n", dev->name);
-		err = dldwd_ioctl_getnick(dev, &wrq->u.data);
-		break;
-
-	case SIOCGIWFREQ:
-		DEBUG(1, "%s: SIOCGIWFREQ\n", dev->name);
-		wrq->u.freq.m = dldwd_hw_get_freq(priv);
-		wrq->u.freq.e = 1;
-		break;
-
-	case SIOCSIWFREQ:
-		DEBUG(1, "%s: SIOCSIWFREQ\n", dev->name);
-		err = dldwd_ioctl_setfreq(dev, &wrq->u.freq);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWSENS:
-		DEBUG(1, "%s: SIOCGIWSENS\n", dev->name);
-		err = dldwd_ioctl_getsens(dev, &wrq->u.sens);
-		break;
-
-	case SIOCSIWSENS:
-		DEBUG(1, "%s: SIOCSIWSENS\n", dev->name);
-		err = dldwd_ioctl_setsens(dev, &wrq->u.sens);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWRTS:
-		DEBUG(1, "%s: SIOCGIWRTS\n", dev->name);
-		wrq->u.rts.value = priv->rts_thresh;
-		wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
-		wrq->u.rts.fixed = 1;
-		break;
-
-	case SIOCSIWRTS:
-		DEBUG(1, "%s: SIOCSIWRTS\n", dev->name);
-		err = dldwd_ioctl_setrts(dev, &wrq->u.rts);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCSIWFRAG:
-		DEBUG(1, "%s: SIOCSIWFRAG\n", dev->name);
-		err = dldwd_ioctl_setfrag(dev, &wrq->u.frag);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWFRAG:
-		DEBUG(1, "%s: SIOCGIWFRAG\n", dev->name);
-		err = dldwd_ioctl_getfrag(dev, &wrq->u.frag);
-		break;
-
-	case SIOCSIWRATE:
-		DEBUG(1, "%s: SIOCSIWRATE\n", dev->name);
-		err = dldwd_ioctl_setrate(dev, &wrq->u.bitrate);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWRATE:
-		DEBUG(1, "%s: SIOCGIWRATE\n", dev->name);
-		err = dldwd_ioctl_getrate(dev, &wrq->u.bitrate);
-		break;
-
-	case SIOCSIWPOWER:
-		DEBUG(1, "%s: SIOCSIWPOWER\n", dev->name);
-		err = dldwd_ioctl_setpower(dev, &wrq->u.power);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWPOWER:
-		DEBUG(1, "%s: SIOCGIWPOWER\n", dev->name);
-		err = dldwd_ioctl_getpower(dev, &wrq->u.power);
-		break;
-
-	case SIOCGIWTXPOW:
-		DEBUG(1, "%s: SIOCGIWTXPOW\n", dev->name);
-		/* The card only supports one tx power, so this is easy */
-		wrq->u.txpower.value = 15; /* dBm */
-		wrq->u.txpower.fixed = 1;
-		wrq->u.txpower.disabled = 0;
-		wrq->u.txpower.flags = IW_TXPOW_DBM;
-		break;
-
-#if WIRELESS_EXT > 10
-	case SIOCSIWRETRY:
-		DEBUG(1, "%s: SIOCSIWRETRY\n", dev->name);
-		err = dldwd_ioctl_setretry(dev, &wrq->u.retry);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCGIWRETRY:
-		DEBUG(1, "%s: SIOCGIWRETRY\n", dev->name);
-		err = dldwd_ioctl_getretry(dev, &wrq->u.retry);
-		break;
-#endif /* WIRELESS_EXT > 10 */
-
-	case SIOCSIWSPY:
-		DEBUG(1, "%s: SIOCSIWSPY\n", dev->name);
-
-		err = dldwd_ioctl_setspy(dev, &wrq->u.data);
-		break;
-
-	case SIOCGIWSPY:
-		DEBUG(1, "%s: SIOCGIWSPY\n", dev->name);
-
-		err = dldwd_ioctl_getspy(dev, &wrq->u.data);
-		break;
-
-	case SIOCGIWPRIV:
-		DEBUG(1, "%s: SIOCGIWPRIV\n", dev->name);
-		if (wrq->u.data.pointer) {
-			struct iw_priv_args privtab[] = {
-				{ SIOCDEVPRIVATE + 0x0, 0, 0, "force_reset" },
-				{ SIOCDEVPRIVATE + 0x2,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  0, "set_port3" },
-				{ SIOCDEVPRIVATE + 0x3, 0,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  "get_port3" },
-				{ SIOCDEVPRIVATE + 0x4,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  0, "set_preamble" },
-				{ SIOCDEVPRIVATE + 0x5, 0,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  "get_preamble" }
-			};
-
-			err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab));
-			if (err)
-				break;
-			
-			wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
-			if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
-				err = -EFAULT;
-		}
-		break;
-	       
-	case SIOCDEVPRIVATE + 0x0: /* force_reset */
-		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x0 (force_reset)\n",
-		      dev->name);
-		if (! capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
-		}
-		
-		printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
-		dldwd_reset(priv);
-		break;
-
-	case SIOCDEVPRIVATE + 0x2: /* set_port3 */
-		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x2 (set_port3)\n",
-		      dev->name);
-		if (! capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
-		}
-
-		err = dldwd_ioctl_setport3(dev, wrq);
-		if (! err)
-			changed = 1;
-		break;
-
-	case SIOCDEVPRIVATE + 0x3: /* get_port3 */
-		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x3 (get_port3)\n",
-		      dev->name);
-		err = dldwd_ioctl_getport3(dev, wrq);
-		break;
-
-	case SIOCDEVPRIVATE + 0x4: /* set_preamble */
-		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x4 (set_preamble)\n",
-		      dev->name);
-		if (! capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
-		}
-
-		/* 802.11b has recently defined some short preamble.
-		 * Basically, the Phy header has been reduced in size.
-		 * This increase performance, especially at high rates
-		 * (the preamble is transmitted at 1Mb/s), unfortunately
-		 * this give compatibility troubles... - Jean II */
-		if(priv->has_preamble) {
-			int val = *( (int *) wrq->u.name );
-
-			dldwd_lock(priv);
-			if(val)
-				priv->preamble = 1;
-			else
-				priv->preamble = 0;
-			dldwd_unlock(priv);
-			changed = 1;
-		} else
-			err = -EOPNOTSUPP;
-		break;
-
-	case SIOCDEVPRIVATE + 0x5: /* get_preamble */
-		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x5 (get_preamble)\n",
-		      dev->name);
-		if(priv->has_preamble) {
-			int *val = (int *)wrq->u.name;
-
-			dldwd_lock(priv);
-			*val = priv->preamble;
-			dldwd_unlock(priv);
-		} else
-			err = -EOPNOTSUPP;
-		break;
-
-	default:
-		err = -EOPNOTSUPP;
-	}
-	
-	if (! err && changed && netif_running(dev)) {
-		err = dldwd_reset(priv);
-		if (err)
-			dldwd_stop(dev);
-	}		
-
-	TRACE_EXIT(dev->name);
-		
-	return err;
-}
-
-static int dldwd_change_mtu(struct net_device *dev, int new_mtu)
-{
-	TRACE_ENTER(dev->name);
-
-	if ( (new_mtu < DLDWD_MIN_MTU) || (new_mtu > DLDWD_MAX_MTU) )
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-
-	TRACE_EXIT(dev->name);
-
-	return 0;
-}
-
-static void __dldwd_set_multicast_list(struct net_device *dev)
-{
-	dldwd_priv_t *priv = dev->priv;
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	int promisc, allmulti, mc_count;
-
-	TRACE_ENTER(dev->name);
-
-	DEBUG(3, "dev->flags=0x%x, priv->promiscuous=%d, dev->mc_count=%d priv->mc_count=%d\n",
-	      dev->flags, priv->promiscuous, dev->mc_count, priv->mc_count);
-
-	/* The Hermes doesn't seem to have an allmulti mode, so we go
-	 * into promiscuous mode and let the upper levels deal. */
-	if ( (dev->flags & IFF_PROMISC) ) {
-		promisc = 1;
-		allmulti = 0;
-		mc_count = 0;
-	} else if ( (dev->flags & IFF_ALLMULTI) ||
-		    (dev->mc_count > HERMES_MAX_MULTICAST) ) {
-		promisc = 0;
-		allmulti = 1;
-		mc_count = HERMES_MAX_MULTICAST;
-	} else {
-		promisc = 0;
-		allmulti = 0;
-		mc_count = dev->mc_count;
-	}
-
-	DEBUG(3, "promisc=%d mc_count=%d\n",
-	      promisc, mc_count);
-
-	if (promisc != priv->promiscuous) { /* Don't touch the hardware if we don't have to */
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PROMISCUOUS,
-					   promisc);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting promiscuity to %d.\n",
-			       dev->name, err, promisc);
-		} else 
-			priv->promiscuous = promisc;
-	}
-
-	if (allmulti) {
-		/* FIXME: This method of doing allmulticast reception
-		   comes from the NetBSD driver. Haven't actually
-		   tested whether it works or not. */
-		hermes_multicast_t mclist;
-
-		memset(&mclist, 0, sizeof(mclist));
-		err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNF_MULTICAST_LIST, &mclist);
-		if (err)
-			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
-			       dev->name, err);
-		else
-			priv->allmulti = 1;
-		       
-	} else if (mc_count || (! mc_count && priv->mc_count) ) {
-		struct dev_mc_list *p = dev->mc_list;
-		hermes_multicast_t mclist;
-		int i;
-
-		for (i = 0; i < mc_count; i++) {
-			/* First some paranoid checks */
-			if (! p) {
-				printk(KERN_ERR "%s: Multicast list shorter than mc_count.\n",
-				       dev->name);
-				break;
-			}
-			if (p->dmi_addrlen != ETH_ALEN) {
-
-				printk(KERN_ERR "%s: Bad address size (%d) in multicast list.\n",
-				       dev->name, p->dmi_addrlen);
-				break;
-			}
-
-			memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
-			p = p->next;
-		}
-
-		/* More paranoia */
-		if (p)
-			printk(KERN_ERR "%s: Multicast list longer than mc_count.\n",
-			       dev->name);
-
-		priv->mc_count = i;			
-
-		DEBUG(3, "priv->mc_count = %d\n", priv->mc_count);
-
-		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNF_MULTICAST_LIST,
-				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
-				       &mclist);
-		if (err)
-			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
-			       dev->name, err);
-		else
-			priv->allmulti = 0;
-	}
-
-	/* Since we can set the promiscuous flag when it wasn't asked
-	   for, make sure the net_device knows about it. */
-	if (priv->promiscuous)
-		dev->flags |= IFF_PROMISC;
-	else
-		dev->flags &= ~IFF_PROMISC;
-
-	if (priv->allmulti)
-		dev->flags |= IFF_ALLMULTI;
-	else
-		dev->flags &= ~IFF_ALLMULTI;
-
-	TRACE_EXIT(dev->name);
-}
-
-/*
- * procfs stuff
- */
-
-static struct proc_dir_entry *dir_base = NULL;
-
-/*
- * This function updates the total amount of data printed so far. It then
- * determines if the amount of data printed into a buffer  has reached the
- * offset requested. If it hasn't, then the buffer is shifted over so that
- * the next bit of data can be printed over the old bit. If the total
- * amount printed so far exceeds the total amount requested, then this
- * function returns 1, otherwise 0.
- */
-static int 
-
-shift_buffer(char *buffer, int requested_offset, int requested_len,
-	     int *total, int *slop, char **buf)
-{
-	int printed;
-	
-	printed = *buf - buffer;
-	if (*total + printed <= requested_offset) {
-		*total += printed;
-		*buf = buffer;
-	}
-	else {
-		if (*total < requested_offset) {
-			*slop = requested_offset - *total;
-		}
-		*total = requested_offset + printed - *slop;
-	}
-	if (*total > requested_offset + requested_len) {
-		return 1;
-	}
-	else {
-		return 0;
-	}
-}
-
-/*
- * This function calculates the actual start of the requested data
- * in the buffer. It also calculates actual length of data returned,
- * which could be less that the amount of data requested.
- */
-#define PROC_BUFFER_SIZE 4096
-#define PROC_SAFE_SIZE 3072
-
-static int
-calc_start_len(char *buffer, char **start, int requested_offset,
-	       int requested_len, int total, char *buf)
-{
-	int return_len, buffer_len;
-	
-	buffer_len = buf - buffer;
-	if (buffer_len >= PROC_BUFFER_SIZE - 1) {
-		printk(KERN_ERR "calc_start_len: exceeded /proc buffer size\n");
-	}
-	
-	/*
-	 * There may be bytes before and after the
-	 * chunk that was actually requested.
-	 */
-	return_len = total - requested_offset;
-	if (return_len < 0) {
-		return_len = 0;
-	}
-	*start = buf - return_len;
-	if (return_len > requested_len) {
-		return_len = requested_len;
-	}
-	return return_len;
-}
-
-static int
-dldwd_proc_get_hermes_regs(char *page, char **start, off_t requested_offset,
-			   int requested_len, int *eof, void *data)
-{
-	dldwd_priv_t *dev = (dldwd_priv_t *)data;
-	hermes_t *hw = &dev->hw;
-	char *buf;
-	int total = 0, slop = 0;
-
-	buf = page;
-
-#define DHERMESREG(name) buf += sprintf(buf, "%-16s: %04x\n", #name, hermes_read_regn(hw, name))
-
-	DHERMESREG(CMD);
-	DHERMESREG(PARAM0);
-	DHERMESREG(PARAM1);
-	DHERMESREG(PARAM2);
-	DHERMESREG(STATUS);
-	DHERMESREG(RESP0);
-	DHERMESREG(RESP1);
-	DHERMESREG(RESP2);
-	DHERMESREG(INFOFID);
-	DHERMESREG(RXFID);
-	DHERMESREG(ALLOCFID);
-	DHERMESREG(TXCOMPLFID);
-	DHERMESREG(SELECT0);
-	DHERMESREG(OFFSET0);
-	DHERMESREG(SELECT1);
-	DHERMESREG(OFFSET1);
-	DHERMESREG(EVSTAT);
-	DHERMESREG(INTEN);
-	DHERMESREG(EVACK);
-	DHERMESREG(CONTROL);
-	DHERMESREG(SWSUPPORT0);
-	DHERMESREG(SWSUPPORT1);
-	DHERMESREG(SWSUPPORT2);
-	DHERMESREG(AUXPAGE);
-	DHERMESREG(AUXOFFSET);
-	DHERMESREG(AUXDATA);
-#undef DHERMESREG
-
-	shift_buffer(page, requested_offset, requested_len, &total,
-		     &slop, &buf);
-	return calc_start_len(page, start, requested_offset, requested_len,
-			      total, buf);
-}
-
-struct {
-	uint16_t rid;
-	char *name;
-	int minlen, maxlen;
-	int displaytype;
-#define DISPLAY_WORDS	0
-#define DISPLAY_BYTES	1
-#define DISPLAY_STRING	2
-} record_table[] = {
-#define RTCNFENTRY(name, type) { HERMES_RID_CNF_##name, #name, 0, LTV_BUF_SIZE, type }
-	RTCNFENTRY(PORTTYPE, DISPLAY_WORDS),
-	RTCNFENTRY(MACADDR, DISPLAY_BYTES),
-	RTCNFENTRY(DESIRED_SSID, DISPLAY_STRING),
-	RTCNFENTRY(CHANNEL, DISPLAY_WORDS),
-	RTCNFENTRY(OWN_SSID, DISPLAY_STRING),
-	RTCNFENTRY(SYSTEM_SCALE, DISPLAY_WORDS),
-	RTCNFENTRY(MAX_DATA_LEN, DISPLAY_WORDS),
-	RTCNFENTRY(PM_ENABLE, DISPLAY_WORDS),
-	RTCNFENTRY(PM_MCAST_RX, DISPLAY_WORDS),
-	RTCNFENTRY(PM_PERIOD, DISPLAY_WORDS),
-	RTCNFENTRY(NICKNAME, DISPLAY_STRING),
-	RTCNFENTRY(WEP_ON, DISPLAY_WORDS),
-	RTCNFENTRY(MWO_ROBUST, DISPLAY_WORDS),
-	RTCNFENTRY(MULTICAST_LIST, DISPLAY_BYTES),
-	RTCNFENTRY(CREATEIBSS, DISPLAY_WORDS),
-	RTCNFENTRY(FRAG_THRESH, DISPLAY_WORDS),
-	RTCNFENTRY(RTS_THRESH, DISPLAY_WORDS),
-	RTCNFENTRY(TX_RATE_CTRL, DISPLAY_WORDS),
-	RTCNFENTRY(PROMISCUOUS, DISPLAY_WORDS),
-	RTCNFENTRY(KEYS, DISPLAY_BYTES),
-	RTCNFENTRY(TX_KEY, DISPLAY_WORDS),
-	RTCNFENTRY(TICKTIME, DISPLAY_WORDS),
-	RTCNFENTRY(PRISM2_TX_KEY, DISPLAY_WORDS),
-	RTCNFENTRY(PRISM2_KEY0, DISPLAY_BYTES),
-	RTCNFENTRY(PRISM2_KEY1, DISPLAY_BYTES),
-	RTCNFENTRY(PRISM2_KEY2, DISPLAY_BYTES),
-	RTCNFENTRY(PRISM2_KEY3, DISPLAY_BYTES),
-	RTCNFENTRY(PRISM2_WEP_ON, DISPLAY_WORDS),
-#undef RTCNFENTRY
-#define RTINFENTRY(name,type) { HERMES_RID_##name, #name, 0, LTV_BUF_SIZE, type }
-	RTINFENTRY(CHANNEL_LIST, DISPLAY_WORDS),
-	RTINFENTRY(STAIDENTITY, DISPLAY_WORDS),
-	RTINFENTRY(CURRENT_SSID, DISPLAY_STRING),
-	RTINFENTRY(CURRENT_BSSID, DISPLAY_BYTES),
-	RTINFENTRY(COMMSQUALITY, DISPLAY_WORDS),
-	RTINFENTRY(CURRENT_TX_RATE, DISPLAY_WORDS),
-	RTINFENTRY(WEP_AVAIL, DISPLAY_WORDS),
-	RTINFENTRY(CURRENT_CHANNEL, DISPLAY_WORDS),
-	RTINFENTRY(DATARATES, DISPLAY_BYTES),
-#undef RTINFENTRY
-};
-#define NUM_RIDS ( sizeof(record_table) / sizeof(record_table[0]) )
-
-static int
-dldwd_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
-			   int requested_len, int *eof, void *data)
-{
-	dldwd_priv_t *dev = (dldwd_priv_t *)data;
-	hermes_t *hw = &dev->hw;
-	char *buf;
-	int total = 0, slop = 0;
-	int i;
-	uint16_t length;
-	int err;
-
-	buf = page;
-
-	/* print out all the config RIDs */
-	for (i = 0; i < NUM_RIDS; i++) {
-		uint16_t rid = record_table[i].rid;
-		int minlen = record_table[i].minlen;
-		int maxlen = record_table[i].maxlen;
-		int len;
-		uint8_t *val8;
-		uint16_t *val16;
-		int j;
-
-		val8 = kmalloc(maxlen + 2, GFP_KERNEL);
-		if (! val8)
-			return -ENOMEM;
-
-		err = hermes_read_ltv(hw, USER_BAP, rid, maxlen,
-				      &length, val8);
-		if (err) {
-			DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid);
-			continue;
-		}
-		val16 = (uint16_t *)val8;
-
-		buf += sprintf(buf, "%-15s (0x%04x): length=%d (%d bytes)\tvalue=", record_table[i].name,
-			       rid, length, (length-1)*2);
-		len = MIN( MAX(minlen, (length-1)*2), maxlen);
-
-		switch (record_table[i].displaytype) {
-		case DISPLAY_WORDS:
-			for (j = 0; j < len / 2; j++) {
-				buf += sprintf(buf, "%04X-", le16_to_cpu(val16[j]));
-			}
-			buf--;
-			break;
-
-		case DISPLAY_BYTES:
-		default:
-			for (j = 0; j < len; j++) {
-				buf += sprintf(buf, "%02X:", val8[j]);
-			}
-			buf--;
-			break;
-
-		case DISPLAY_STRING:
-			len = MIN(len, le16_to_cpu(val16[0])+2);
-			val8[len] = '\0';
-			buf += sprintf(buf, "\"%s\"", (char *)&val16[1]);
-			break;
-		}
-
-		buf += sprintf(buf, "\n");
-
-		kfree(val8);
-
-		if (shift_buffer(page, requested_offset, requested_len,
-				 &total, &slop, &buf))
-			break;
-
-		if ( (buf - page) > PROC_SAFE_SIZE )
-			break;
-	}
-
-	return calc_start_len(page, start, requested_offset, requested_len,
-			      total, buf);
-}
-
-/* initialise the /proc subsystem for the hermes driver, creating the
- * separate entries */
-static int
-dldwd_proc_init(void)
-{
-	int err = 0;
-
-	TRACE_ENTER("dldwd");
-
-	/* create the directory for it to sit in */
-	dir_base = create_proc_entry("hermes", S_IFDIR, &proc_root);
-	if (dir_base == NULL) {
-		printk(KERN_ERR "Unable to initialise /proc/hermes.\n");
-		dldwd_proc_cleanup();
-		err = -ENOMEM;
-	}
-
-	TRACE_EXIT("dldwd");
-
-	return err;
-}
-
-static int
-dldwd_proc_dev_init(dldwd_priv_t *dev)
-{
-	dev->dir_dev = NULL;
-	/* create the directory for it to sit in */
-	dev->dir_dev = create_proc_entry(dev->node.dev_name, S_IFDIR | S_IRUGO | S_IXUGO,
-					 dir_base);
-	if (dev->dir_dev == NULL) {
-		printk(KERN_ERR "Unable to initialise /proc/hermes/%s.\n",  dev->node.dev_name);
-		goto fail;
-	}
-
-	dev->dir_regs = NULL;
-	dev->dir_regs = create_proc_read_entry("regs", S_IFREG | S_IRUGO,
-					       dev->dir_dev, dldwd_proc_get_hermes_regs, dev);
-	if (dev->dir_regs == NULL) {
-		printk(KERN_ERR "Unable to initialise /proc/hermes/%s/regs.\n",  dev->node.dev_name);
-		goto fail;
-	}
-
-	dev->dir_recs = NULL;
-	dev->dir_recs = create_proc_read_entry("recs", S_IFREG | S_IRUGO,
-					       dev->dir_dev, dldwd_proc_get_hermes_recs, dev);
-	if (dev->dir_recs == NULL) {
-		printk(KERN_ERR "Unable to initialise /proc/hermes/%s/recs.\n",  dev->node.dev_name);
-		goto fail;
-	}
-
-	return 0;
- fail:
-	dldwd_proc_dev_cleanup(dev);
-	return -ENOMEM;
-}
-
-static void
-dldwd_proc_dev_cleanup(dldwd_priv_t *priv)
-{
-	if (priv->dir_regs) {
-		remove_proc_entry("regs", priv->dir_dev);
-		priv->dir_regs = NULL;
-	}		
-	if (priv->dir_recs) {
-		remove_proc_entry("recs", priv->dir_dev);
-		priv->dir_recs = NULL;
-	}		
-	if (priv->dir_dev) {
-		remove_proc_entry(priv->node.dev_name, dir_base);
-		priv->dir_dev = NULL;
-	}
-}
-
-static void
-dldwd_proc_cleanup(void)
-{
-	TRACE_ENTER("dldwd");
-
-	if (dir_base) {
-		remove_proc_entry("hermes", &proc_root);
-		dir_base = NULL;
-	}
-	
-	TRACE_EXIT("dldwd");
-}
-
-/*====================================================================*/
-
-/*
- * From here on in, it's all PCMCIA junk, taken almost directly from
- * dummy_cs.c
- */
-
-/*
-   The dev_info variable is the "key" that is used to match up this
-   device driver with appropriate cards, through the card configuration
-   database.
-*/
-
-static dev_info_t dev_info = "orinoco_cs";
-
-/*
-   A linked list of "instances" of the dummy device.  Each actual
-   PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
-
-   You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
-   device numbers are used to derive the corresponding array index.
-*/
-
-static dev_link_t *dev_list = NULL;
-static int num_instances = 0;
-
-/*====================================================================*/
-
-static void cs_error(client_handle_t handle, int func, int ret)
-{
-	error_info_t err = { func, ret };
-	CardServices(ReportError, handle, &err);
-}
-
-/*======================================================================
-  dldwd_attach() creates an "instance" of the driver, allocating
-  local data structures for one device.  The device is registered
-  with Card Services.
-  
-  The dev_link structure is initialized, but we don't actually
-  configure the card at this point -- we wait until we receive a
-  card insertion event.
-  ======================================================================*/
-
-static dev_link_t *dldwd_attach(void)
-{
-	dldwd_priv_t *priv;
-	dev_link_t *link;
-	struct net_device *ndev;
-	client_reg_t client_reg;
-	int ret, i;
-
-	TRACE_ENTER("dldwd");
-
-	/* Allocate space for private device-specific data */
-	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
-	if (! priv) {
-		link = NULL;
-		goto out;
-	}
-
-	memset(priv, 0, sizeof(*priv));
-	priv->instance = num_instances++; /* FIXME: Racy? */
-	spin_lock_init(&priv->lock);
-
-	link = &priv->link;
-	ndev = &priv->ndev;
-	link->priv = ndev->priv = priv;
-
-	/* Initialize the dev_link_t structure */
-	link->release.function = &dldwd_release;
-	link->release.data = (u_long) link;
-
-	/* Interrupt setup */
-	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-	link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
-	if (irq_list[0] == -1)
-		link->irq.IRQInfo2 = irq_mask;
-	else
-		for (i = 0; i < 4; i++)
-			link->irq.IRQInfo2 |= 1 << irq_list[i];
-	link->irq.Handler = NULL;
-
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
-	/* Set up the net_device */
-	ether_setup(ndev);
-	ndev->init = dldwd_init;
-	ndev->open = dldwd_open;
-	ndev->stop = dldwd_stop;
-	ndev->hard_start_xmit = dldwd_xmit;
-	ndev->tx_timeout = dldwd_tx_timeout;
-	ndev->watchdog_timeo = 4*HZ; /* 4 second timeout */
-
-	ndev->get_stats = dldwd_get_stats;
-	ndev->get_wireless_stats = dldwd_get_wireless_stats;
-
-	ndev->do_ioctl = dldwd_ioctl;
-	
-	ndev->change_mtu = dldwd_change_mtu;
-	ndev->set_multicast_list = dldwd_set_multicast_list;
-
-	netif_stop_queue(ndev);
-
-	/* Register with Card Services */
-	link->next = dev_list;
-	dev_list = link;
-	client_reg.dev_info = &dev_info;
-	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
-	client_reg.EventMask =
-	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-	client_reg.event_handler = &dldwd_event;
-	client_reg.Version = 0x0210;
-	client_reg.event_callback_args.client_data = link;
-	ret = CardServices(RegisterClient, &link->handle, &client_reg);
-	if (ret != CS_SUCCESS) {
-		cs_error(link->handle, RegisterClient, ret);
-		dldwd_detach(link);
-		link = NULL;
-		goto out;
-	}
-
- out:
-	TRACE_EXIT("dldwd");
-	return link;
-}				/* dldwd_attach */
-
-/*======================================================================
-  This deletes a driver "instance".  The device is de-registered
-  with Card Services.  If it has been released, all local data
-  structures are freed.  Otherwise, the structures will be freed
-  when the device is released.
-  ======================================================================*/
-
-static void dldwd_detach(dev_link_t * link)
-{
-	dev_link_t **linkp;
-	dldwd_priv_t *priv = link->priv;
-
-	TRACE_ENTER("dldwd");
-
-	/* Locate device structure */
-	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (*linkp == NULL)
-		goto out;
-
-	/*
-	   If the device is currently configured and active, we won't
-	   actually delete it yet.  Instead, it is marked so that when
-	   the release() function is called, that will trigger a proper
-	   detach().
-	 */
-	if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-		printk(KERN_DEBUG "orinoco_cs: detach postponed, '%s' "
-		       "still locked\n", link->dev->dev_name);
-#endif
-		link->state |= DEV_STALE_LINK;
-		goto out;
-	}
-
-	/* Break the link with Card Services */
-	if (link->handle)
-		CardServices(DeregisterClient, link->handle);
-
-	/* Unlink device structure, and free it */
-	*linkp = link->next;
-	DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev);
-	if (link->dev) {
-		DEBUG(0, "orinoco_cs: About to unregister net device %p\n",
-		      &priv->ndev);
-		unregister_netdev(&priv->ndev);
-	}
-	kfree(priv);
-
-	num_instances--; /* FIXME: Racy? */
-
- out:
-	TRACE_EXIT("dldwd");
-}				/* dldwd_detach */
-
-/*
- * Do a soft reset of the Pcmcia card using the Configuration Option Register
- * Can't do any harm, and actually may do some good on some cards...
- */
-static int dldwd_cor_reset(dev_link_t *link)
-{
-	conf_reg_t reg;
-	u_long default_cor; 
-
-	/* Save original COR value */
-	reg.Function = 0;
-	reg.Action = CS_READ;
-	reg.Offset = CISREG_COR;
-	reg.Value = 0;
-	CardServices(AccessConfigurationRegister, link->handle, &reg);
-	default_cor = reg.Value;
-
-	DEBUG(2, "dldwd : dldwd_cor_reset() : cor=0x%lX\n", default_cor);
-
-	/* Soft-Reset card */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = (default_cor | COR_SOFT_RESET);
-	CardServices(AccessConfigurationRegister, link->handle, &reg);
-
-	/* Wait until the card has acknowledged our reset */
-	mdelay(1);
-
-	/* Restore original COR configuration index */
-	reg.Value = (default_cor & COR_CONFIG_MASK);
-	CardServices(AccessConfigurationRegister, link->handle, &reg);
-
-	/* Wait until the card has finished restarting */
-	mdelay(1);
-
-	return(0);
-}
-
-/*======================================================================
-  dldwd_config() is scheduled to run after a CARD_INSERTION event
-  is received, to configure the PCMCIA socket, and to make the
-  device available to the system.
-  ======================================================================*/
-
-#define CS_CHECK(fn, args...) \
-while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
-
-#define CFG_CHECK(fn, args...) \
-if (CardServices(fn, args) != 0) goto next_entry
-
-static void dldwd_config(dev_link_t * link)
-{
-	client_handle_t handle = link->handle;
-	dldwd_priv_t *priv = link->priv;
-	hermes_t *hw = &priv->hw;
-	struct net_device *ndev = &priv->ndev;
-	tuple_t tuple;
-	cisparse_t parse;
-	int last_fn, last_ret;
-	u_char buf[64];
-	config_info_t conf;
-	cistpl_cftable_entry_t dflt = { 0 };
-	cisinfo_t info;
-
-	TRACE_ENTER("dldwd");
-
-	CS_CHECK(ValidateCIS, handle, &info);
-
-	/*
-	   This reads the card's CONFIG tuple to find its configuration
-	   registers.
-	 */
-	tuple.DesiredTuple = CISTPL_CONFIG;
-	tuple.Attributes = 0;
-	tuple.TupleData = buf;
-	tuple.TupleDataMax = sizeof(buf);
-	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, handle, &tuple);
-	CS_CHECK(GetTupleData, handle, &tuple);
-	CS_CHECK(ParseTuple, handle, &tuple, &parse);
-	link->conf.ConfigBase = parse.config.base;
-	link->conf.Present = parse.config.rmask[0];
-
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
-	/* Look up the current Vcc */
-	CS_CHECK(GetConfigurationInfo, handle, &conf);
-	link->conf.Vcc = conf.Vcc;
-
-	DEBUG(0, "dldwd_config: ConfigBase = 0x%x link->conf.Vcc = %d\n", 
-	      link->conf.ConfigBase, link->conf.Vcc);
-
-	/*
-	   In this loop, we scan the CIS for configuration table entries,
-	   each of which describes a valid card configuration, including
-	   voltage, IO window, memory window, and interrupt settings.
-
-	   We make no assumptions about the card to be configured: we use
-	   just the information available in the CIS.  In an ideal world,
-	   this would work for any PCMCIA card, but it requires a complete
-	   and accurate CIS.  In practice, a driver usually "knows" most of
-	   these things without consulting the CIS, and most client drivers
-	   will only use the CIS to fill in implementation-defined details.
-	 */
-	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, handle, &tuple);
-	while (1) {
-		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-		CFG_CHECK(GetTupleData, handle, &tuple);
-		CFG_CHECK(ParseTuple, handle, &tuple, &parse);
-
-		DEBUG(0, "dldwd_config: index = 0x%x, flags = 0x%x\n",
-		      cfg->index, cfg->flags);
-
-		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-			dflt = *cfg;
-		if (cfg->index == 0)
-			goto next_entry;
-		link->conf.ConfigIndex = cfg->index;
-
-		/* Does this card need audio output? */
-		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-			link->conf.Attributes |= CONF_ENABLE_SPKR;
-			link->conf.Status = CCSR_AUDIO_ENA;
-		}
-
-		/* Use power settings for Vcc and Vpp if present */
-		/*  Note that the CIS values need to be rescaled */
-		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (conf.Vcc !=
-			    cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-				DEBUG(2, "dldwd_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-				goto next_entry;
-			}
-		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (conf.Vcc !=
-			    dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
-				DEBUG(2, "dldwd_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
-				goto next_entry;
-			}
-		}
-
-		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
-			    cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
-			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-		
-		DEBUG(0, "dldwd_config: We seem to have configured Vcc and Vpp\n");
-
-		/* Do we need to allocate an interrupt? */
-		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-			link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-		/* IO window settings */
-		link->io.NumPorts1 = link->io.NumPorts2 = 0;
-		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-			cistpl_io_t *io =
-			    (cfg->io.nwin) ? &cfg->io : &dflt.io;
-			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-			if (!(io->flags & CISTPL_IO_8BIT))
-				link->io.Attributes1 =
-				    IO_DATA_PATH_WIDTH_16;
-			if (!(io->flags & CISTPL_IO_16BIT))
-				link->io.Attributes1 =
-				    IO_DATA_PATH_WIDTH_8;
-			link->io.IOAddrLines =
-			    io->flags & CISTPL_IO_LINES_MASK;
-			link->io.BasePort1 = io->win[0].base;
-			link->io.NumPorts1 = io->win[0].len;
-			if (io->nwin > 1) {
-				link->io.Attributes2 =
-				    link->io.Attributes1;
-				link->io.BasePort2 = io->win[1].base;
-				link->io.NumPorts2 = io->win[1].len;
-			}
-
-			/* This reserves IO space but doesn't actually enable it */
-			CFG_CHECK(RequestIO, link->handle, &link->io);
-		}
-
-
-		/* If we got this far, we're cool! */
-
-		break;
-		
-	next_entry:
-		if (link->io.NumPorts1)
-			CardServices(ReleaseIO, link->handle, &link->io);
-		CS_CHECK(GetNextTuple, handle, &tuple);
-	}
-
-	/*
-	   Allocate an interrupt line.  Note that this does not assign a
-	   handler to the interrupt, unless the 'Handler' member of the
-	   irq structure is initialized.
-	 */
-	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-		int i;
-
-		link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-		link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
-		if (irq_list[0] == -1)
-			link->irq.IRQInfo2 = irq_mask;
-		else
-			for (i=0; i<4; i++)
-				link->irq.IRQInfo2 |= 1 << irq_list[i];
-		
-  		link->irq.Handler = dldwd_interrupt; 
-  		link->irq.Instance = priv; 
-		
-		CS_CHECK(RequestIRQ, link->handle, &link->irq);
-	}
-
-	/* We initialize the hermes structure before completing PCMCIA
-	   configuration just in case the interrupt handler gets
-	   called. */
-	hermes_struct_init(hw, link->io.BasePort1);
-
-	/*
-	   This actually configures the PCMCIA socket -- setting up
-	   the I/O windows and the interrupt mapping, and putting the
-	   card and host interface into "Memory and IO" mode.
-	 */
-	CS_CHECK(RequestConfiguration, link->handle, &link->conf);
-
-	ndev->base_addr = link->io.BasePort1;
-	ndev->irq = link->irq.AssignedIRQ;
-
-	/* Do a Pcmcia soft reset of the card (optional) */
-	if(reset_cor)
-		dldwd_cor_reset(link);
-
-	/* register_netdev will give us an ethX name */
-	ndev->name[0] = '\0';
-	/* Tell the stack we exist */
-	if (register_netdev(ndev) != 0) {
-		printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");
-		goto failed;
-	}
-	strcpy(priv->node.dev_name, ndev->name);
-	
-	/* Finally, report what we've done */
-	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-	       priv->node.dev_name, link->conf.ConfigIndex,
-	       link->conf.Vcc / 10, link->conf.Vcc % 10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-		       link->conf.Vpp1 % 10);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq.AssignedIRQ);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
-	printk("\n");
-	
-	/* And give us the proc nodes for debugging */
-	if (dldwd_proc_dev_init(priv) != 0) {
-		printk(KERN_ERR "orinoco_cs: Failed to create /proc node for %s\n",
-		       priv->node.dev_name);
-		goto failed;
-	}
-	
-	/*
-	   At this point, the dev_node_t structure(s) need to be
-	   initialized and arranged in a linked list at link->dev.
-	 */
-	priv->node.major = priv->node.minor = 0;
-	link->dev = &priv->node;
-	link->state &= ~DEV_CONFIG_PENDING;
-
-	TRACE_EXIT("dldwd");
-
-	return;
-
- cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
- failed:
-	dldwd_release((u_long) link);
-
-	TRACE_EXIT("dldwd");
-}				/* dldwd_config */
-
-/*======================================================================
-  After a card is removed, dldwd_release() will unregister the
-  device, and release the PCMCIA configuration.  If the device is
-  still open, this will be postponed until it is closed.
-  ======================================================================*/
-
-static void dldwd_release(u_long arg)
-{
-	dev_link_t *link = (dev_link_t *) arg;
-	dldwd_priv_t *priv = link->priv;
-
-	TRACE_ENTER(link->dev->dev_name);
-
-	/*
-	   If the device is currently in use, we won't release until it
-	   is actually closed, because until then, we can't be sure that
-	   no one will try to access the device or its data structures.
-	 */
-	if (link->open) {
-		DEBUG(0, "orinoco_cs: release postponed, '%s' still open\n",
-		      link->dev->dev_name);
-		link->state |= DEV_STALE_CONFIG;
-		return;
-	}
-
-	/*
-	   In a normal driver, additional code may be needed to release
-	   other kernel data structures associated with this device. 
-	 */
-
-	dldwd_proc_dev_cleanup(priv);
-
-	/* Don't bother checking to see if these succeed or not */
-	CardServices(ReleaseConfiguration, link->handle);
-	if (link->io.NumPorts1)
-		CardServices(ReleaseIO, link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		CardServices(ReleaseIRQ, link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
-
-	TRACE_EXIT(link->dev->dev_name);
-}				/* dldwd_release */
-
-/*======================================================================
-  The card status event handler.  Mostly, this schedules other
-  stuff to run after an event is received.
-
-  When a CARD_REMOVAL event is received, we immediately set a
-  private flag to block future accesses to this device.  All the
-  functions that actually access the device should check this flag
-  to make sure the card is still present.
-  ======================================================================*/
-
-static int dldwd_event(event_t event, int priority,
-		       event_callback_args_t * args)
-{
-	dev_link_t *link = args->client_data;
-	dldwd_priv_t *priv = (dldwd_priv_t *)link->priv;
-	struct net_device *dev = &priv->ndev;
-
-	TRACE_ENTER("dldwd");
-
-	switch (event) {
-	case CS_EVENT_CARD_REMOVAL:
-		dldwd_shutdown(priv);
-		link->state &= ~DEV_PRESENT;
-		if (link->state & DEV_CONFIG) {
-			netif_stop_queue(dev);
-			netif_device_detach(dev);
-			mod_timer(&link->release, jiffies + HZ / 20);
-		}
-		break;
-	case CS_EVENT_CARD_INSERTION:
-		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-		dldwd_config(link);
-		break;
-	case CS_EVENT_PM_SUSPEND:
-
-		link->state |= DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_RESET_PHYSICAL:
-		dldwd_shutdown(priv);
-		/* Mark the device as stopped, to block IO until later */
-
-		if (link->state & DEV_CONFIG) {
-			if (link->open) {
-				netif_stop_queue(dev);
-				netif_device_detach(dev);
-			}
-			CardServices(ReleaseConfiguration, link->handle);
-		}
-		break;
-	case CS_EVENT_PM_RESUME:
-		link->state &= ~DEV_SUSPEND;
-		/* Fall through... */
-	case CS_EVENT_CARD_RESET:
-		if (link->state & DEV_CONFIG) {
-			CardServices(RequestConfiguration, link->handle,
-				     &link->conf);
-
-			if (link->open) {
-				if (dldwd_reset(priv) == 0) {
-					netif_device_attach(dev);
-					netif_start_queue(dev);
-				} else {
-					printk(KERN_ERR "%s: Error resetting device on PCMCIA event\n",
-					       dev->name);
-					dldwd_stop(dev);
-				}
-			}
-		}
-		/*
-		   In a normal driver, additional code may go here to restore
-		   the device state and restart IO. 
-		 */
-		break;
-	}
-
-	TRACE_EXIT("dldwd");
-
-	return 0;
-}				/* dldwd_event */
-
-static int __init init_dldwd_cs(void)
-{
-	servinfo_t serv;
-	int err;
-	
-	TRACE_ENTER("dldwd");
-
-	printk(KERN_INFO "dldwd: David's Less Dodgy WaveLAN/IEEE Driver\n");
-
-	DEBUG(0, "%s\n", version);
-	CardServices(GetCardServicesInfo, &serv);
-	if (serv.Revision != CS_RELEASE_CODE) {
-		printk(KERN_NOTICE "orinoco_cs: Card Services release "
-		       "does not match!\n");
-		return -1;
-	}
-	register_pccard_driver(&dev_info, &dldwd_attach, &dldwd_detach);
-
-	
-	err = dldwd_proc_init();
-
-	TRACE_EXIT("dldwd");
-	return err;
-}
-
-static void __exit exit_dldwd_cs(void)
-{
-	TRACE_ENTER("dldwd");
-
-	dldwd_proc_cleanup();
-
-	unregister_pccard_driver(&dev_info);
-
-	if (dev_list)
-		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
-	while (dev_list != NULL) {
-		del_timer(&dev_list->release);
-		if (dev_list->state & DEV_CONFIG)
-			dldwd_release((u_long) dev_list);
-		dldwd_detach(dev_list);
-	}
-
-	TRACE_EXIT("dldwd");
-}
-
-module_init(init_dldwd_cs);
-module_exit(exit_dldwd_cs);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c
--- v2.4.4/linux/drivers/net/pppoe.c	Tue Mar  6 19:44:35 2001
+++ linux/drivers/net/pppoe.c	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
  * PPPoE --- PPP over Ethernet (RFC 2516)
  *
  *
- * Version:    0.6.5
+ * Version:    0.6.6
  *
  * 030700 :     Fixed connect logic to allow for disconnect.
  * 270700 :	Fixed potential SMP problems; we must protect against
@@ -19,6 +19,7 @@
  * 051000 :	Initialization cleanup.
  * 111100 :	Fix recvmsg.
  * 050101 :	Fix PADT procesing.
+ * 140501 :	Use pppoe_rcv_core to handle all backlog. (Alexey)
  *
  * Author:	Michal Ostrowski <mostrows@styx.uwaterloo.ca>
  * Contributors:
@@ -376,22 +377,6 @@
 	return ret;
 }
 
-
-/************************************************************************
- *
- * Receive wrapper called in process context.
- *
- ***********************************************************************/
-int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb)
-{
-	lock_sock(sk);
-	pppoe_rcv_core(sk, skb);
-	release_sock(sk);
-	return 0;
-}
-
-
-
 /************************************************************************
  *
  * Receive a PPPoE Discovery frame.
@@ -481,7 +466,7 @@
 	sk->protocol = PX_PROTO_OE;
 	sk->family = PF_PPPOX;
 
-	sk->backlog_rcv = pppoe_backlog_rcv;
+	sk->backlog_rcv = pppoe_rcv_core;
 	sk->next = NULL;
 	sk->pprev = NULL;
 	sk->state = PPPOX_NONE;
diff -u --recursive --new-file v2.4.4/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.4.4/linux/drivers/net/sunhme.c	Thu Apr 26 22:17:26 2001
+++ linux/drivers/net/sunhme.c	Sun May 20 11:32:07 2001
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.117 2001/04/19 22:32:41 davem Exp $
+/* $Id: sunhme.c,v 1.119 2001/05/17 04:12:16 davem Exp $
  * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -2206,6 +2206,7 @@
 static int happy_meal_open(struct net_device *dev)
 {
 	struct happy_meal *hp = dev->priv;
+	int res;
 
 	HMD(("happy_meal_open: "));
 
@@ -2229,7 +2230,10 @@
 	}
 
 	HMD(("to happy_meal_init\n"));
-	return happy_meal_init(hp, 0);
+	res = happy_meal_init(hp, 0);
+	if (res && ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO))
+		free_irq(dev->irq, dev);
+	return res;
 }
 
 static int happy_meal_close(struct net_device *dev)
@@ -2441,7 +2445,7 @@
 	if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
 		return -EFAULT;
 
-	if (ecmd.cmd == SPARC_ETH_GSET) {
+	if (ecmd.cmd == ETHTOOL_GSET) {
 		ecmd.supported =
 			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
 			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2480,7 +2484,7 @@
 		if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
 			return -EFAULT;
 		return 0;
-	} else if (ecmd.cmd == SPARC_ETH_SSET) {
+	} else if (ecmd.cmd == ETHTOOL_SSET) {
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
@@ -2864,7 +2868,7 @@
 	
 	prom_getstring(node, "name", prom_name, sizeof(prom_name));
 #else
-#warning This needs to be corrected... -DaveM
+/* This needs to be corrected... -DaveM */
 	strcpy(prom_name, "qfe");
 #endif
 
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tokenring/ibmtr.h linux/drivers/net/tokenring/ibmtr.h
--- v2.4.4/linux/drivers/net/tokenring/ibmtr.h	Thu Mar  2 10:15:30 2000
+++ linux/drivers/net/tokenring/ibmtr.h	Wed Dec 31 16:00:00 1969
@@ -1,454 +0,0 @@
-/* Definitions for an IBM Token Ring card. */
-/* This file is distributed under the GNU GPL   */
-
-/* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */
-
-#define TR_RETRY_INTERVAL (5*HZ) /* 500 on PC = 5 s */
-#define TR_RESET_INTERVAL (HZ/20) /* 5 on PC = 50 ms */
-#define TR_BUSY_INTERVAL (HZ/5) /* 5 on PC = 200 ms */
-#define TR_SPIN_INTERVAL (3*HZ) /* 3 seconds before init timeout */
-#define TR_RETRIES 6            /* number of open retries */ 
-
-#define TR_ISA 1
-#define TR_MCA 2
-#define TR_ISAPNP 3
-#define NOTOK 0
-#define TOKDEBUG 1
-
-#define IBMTR_SHARED_RAM_SIZE 0x10000
-#define IBMTR_IO_EXTENT 4
-#define IBMTR_MAX_ADAPTERS 2
-
-#define CHANNEL_ID      0X1F30
-#define AIP             0X1F00
-#define AIPCHKSUM1      0X1F60
-#define AIPCHKSUM2      0X1FF0
-#define AIPADAPTYPE     0X1FA0
-#define AIPDATARATE     0X1FA2
-#define AIPEARLYTOKEN   0X1FA4
-#define AIPAVAILSHRAM   0X1FA6
-#define AIPSHRAMPAGE    0X1FA8
-#define AIP4MBDHB       0X1FAA
-#define AIP16MBDHB      0X1FAC
-#define AIPFID		0X1FBA
-
-/* Note, 0xA20 == 0x220 since motherboard decodes 10 bits.  I left everything
-   the way my documentation had it, ie: 0x0A20.     */
-#define ADAPTINTCNTRL   0x02f0  /* Adapter interrupt control */
-#define ADAPTRESET      0x1     /* Control Adapter reset (add to base) */
-#define ADAPTRESETREL   0x2     /* Release Adapter from reset ( """)  */
-#define ADAPTINTREL	0x3 	/* Adapter interrupt release */
-
-#define MMIOStartLocP   0x0a20  /* Primary adapter's starting MMIO area */
-#define MMIOStartLocA   0x0a24  /* Alternate adapter's starting MMIO area */
-
-#define GLOBAL_INT_ENABLE 0x02f0
-
-/* MMIO bits 0-4 select register */
-#define RRR_EVEN        0x00    /* Shared RAM relocation registers - even and odd */
-/* Used to set the starting address of shared RAM  */
-/* Bits 1 through 7 of this register map to bits 13 through 19 of the shared RAM address.*/
-/* ie: 0x02 sets RAM address to ...ato!  issy su wazzoo !! GODZILLA!!! */
-#define RRR_ODD         0x01
-/* Bits 2 and 3 of this register can be read to determine shared RAM size */
-/* 00 for 8k, 01 for 16k, 10 for 32k, 11 for 64k  */
-#define WRBR_EVEN       0x02    /* Write region base registers - even and odd */
-#define WRBR_ODD        0x03
-#define WWOR_EVEN       0x04    /* Write window open registers - even and odd */
-#define WWOR_ODD        0x05
-#define WWCR_EVEN       0x06    /* Write window close registers - even and odd */
-#define WWCR_ODD        0x07
-
-/* Interrupt status registers - PC system  - even and odd */
-#define ISRP_EVEN       0x08
-
-#define TCR_INT 0x10    /* Bit 4 - Timer interrupt.  The TVR_EVEN timer has
-                                                                   expired. */
-#define ERR_INT 0x08    /* Bit 3 - Error interrupt.  The adapter has had an
-                                                                   internal error. */
-#define ACCESS_INT 0x04    /* Bit 2 - Access interrupt.  You have attempted to
-                                                           write to an invalid area of shared RAM or an invalid
-                                                                   register within the MMIO. */
-/*      In addition, the following bits within ISRP_EVEN can be turned on or off by you */
-/*      to control the interrupt processing:   */
-#define INT_IRQ 0x80    /* Bit 7 - If 0 the adapter will issue a CHCK, if 1 and
-                                                              IRQ.  This should normally be set (by you) to 1.  */
-#define INT_ENABLE 0x40 /* Bit 6 - Interrupt enable.  If 0, no interrupts will
-                                                                   occur.  If 1, interrupts will occur normally.
-                                                                   Normally set to 1.  */
-/* Bit 0 - Primary or alternate adapter.  Set to zero if this adapter is the primary adapter,*/
-/*         1 if this adapter is the alternate adapter. */
-
-
-#define ISRP_ODD        0x09
-
-#define ADAP_CHK_INT 0x40 /* Bit 6 - Adapter check.  the adapter has
-                             encountered a serious problem and has closed
-                             itself.  Whoa.  */
-#define SRB_RESP_INT 0x20 /* Bit 5 - SRB response.  The adapter has accepted
-                             an SRB request and set the return code within
-                             the SRB. */
-#define ASB_FREE_INT 0x10 /* Bit 4 - ASB free.  The adapter has read the ASB
-                                                                          and this area can be safely reused. This interrupt
-                                                                          is only used if your application has set the ASB
-                                                                          free request bit in ISRA_ODD or if an error was
-                                                                detected in your response. */
-#define ARB_CMD_INT  0x08 /* Bit 3 - ARB command.  The adapter has given you a
-                                                                          command for action.  The command is located in the
-                                                                          ARB area of shared memory. */
-#define SSB_RESP_INT 0x04 /* Bit 2 - SSB response.  The adapter has posted a
-                                                                          response to your SRB (the response is located in
-                                                                          the SSB area of shared memory). */
-/* Bit 1 - Bridge frame forward complete. */
-
-
-
-#define ISRA_EVEN       0x0A    /* Interrupt status registers - adapter  - even and odd */
-/* Bit 7 - Internal parity error (on adapter's internal bus) */
-/* Bit 6 - Timer interrupt pending */
-/* Bit 5 - Access interrupt (attempt by adapter to access illegal address) */
-/* Bit 4 - Adapter microcode problem (microcode dead-man timer expired) */
-/* Bit 3 - Adapter processor check status */
-/* Bit 2 - Reserved */
-/* Bit 1 - Adapter hardware interrupt mask (prevents internal interrupts) */
-/* Bit 0 - Adapter software interrupt mask (prevents internal software interrupts) */
-
-#define ISRA_ODD        0x0B
-#define CMD_IN_SRB 0x20 /* Bit 5  - Indicates that you have placed a new
-                           command in the SRB and are ready for the adapter to
-                           process the command. */
-#define RESP_IN_ASB 0x10 /* Bit 4 - Indicates that you have placed a response
-                                                                    (an ASB) in the shared RAM which is available for
-                                                                         the adapter's use. */
-/* Bit 3 - Indicates that you are ready to put an SRB in the shared RAM, but that a previous */
-/*         command is still pending.  The adapter will then interrupt you when the previous */
-/*         command is completed */
-/* Bit 2 - Indicates that you are ready to put an ASB in the shared RAM, but that a previous */
-/*         ASB is still pending.  The adapter will then interrupt you when the previous ASB */
-/*         is copied.  */
-#define ARB_FREE 0x2
-#define SSB_FREE 0x1
-
-#define TCR_EVEN        0x0C    /* Timer control registers - even and odd */
-#define TCR_ODD         0x0D
-#define TVR_EVEN        0x0E    /* Timer value registers - even and odd */
-#define TVR_ODD         0x0F
-#define SRPR_EVEN       0x18    /* Shared RAM paging registers - even and odd */
-#define SRPR_ENABLE_PAGING 0xc0
-#define SRPR_ODD        0x19 /* Not used. */
-#define TOKREAD         0x60
-#define TOKOR           0x40
-#define TOKAND          0x20
-#define TOKWRITE        0x00
-
-/* MMIO bits 5-6 select operation */
-/* 00 is used to write to a register */
-/* 01 is used to bitwise AND a byte with a register */
-/* 10 is used to bitwise OR a byte with a register  */
-/* 11 is used to read from a register */
-
-/* MMIO bits 7-8 select area of interest.. see below */
-/* 00 selects attachment control area. */
-/* 01 is reserved. */
-/* 10 selects adapter identification area A containing the adapter encoded address. */
-/* 11 selects the adapter identification area B containing test patterns. */
-
-#define PCCHANNELID 5049434F3631313039393020
-#define MCCHANNELID 4D4152533633583435313820
-
-#define ACA_OFFSET 0x1e00
-#define ACA_SET 0x40
-#define ACA_RESET 0x20
-#define ACA_RW 0x00
-
-#ifdef ENABLE_PAGING
-#define SET_PAGE(x) (isa_writeb((x), \
-  ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN))
-#else
-#define SET_PAGE(x)
-#endif
-
-typedef enum { IN_PROGRESS, SUCCESS, FAILURE, CLOSED } open_state;
-
-/* do_tok_int possible values */
-#define FIRST_INT 1
-#define NOT_FIRST 2
-
-struct tok_info {
-	unsigned char irq;
-	__u32 mmio;
-	unsigned char hw_address[32];
-	unsigned char adapter_type;
-	unsigned char data_rate;
-	unsigned char token_release;
-	unsigned char avail_shared_ram;
-	unsigned char shared_ram_paging;
-	unsigned short dhb_size4mb;
-	unsigned short rbuf_len4;
-	unsigned short rbuf_cnt4;
-	unsigned short maxmtu4;
-	unsigned short dhb_size16mb;
-	unsigned short rbuf_len16;
-	unsigned short rbuf_cnt16;
-	unsigned short maxmtu16;
-	/* Additions by David Morris       */
-	unsigned char do_tok_int;
-	wait_queue_head_t wait_for_tok_int;
-	wait_queue_head_t wait_for_reset;
-	unsigned char sram_base;
-	/* Additions by Peter De Schrijver */
-	unsigned char page_mask;          /* mask to select RAM page to Map*/
-	unsigned char mapped_ram_size;    /* size of RAM page */
-	__u32 sram;                       /* Shared memory base address */
-	__u32 init_srb;                   /* Initial System Request Block address */
-	__u32 srb;                        /* System Request Block address */
-	__u32 ssb;                        /* System Status Block address */
-	__u32 arb;                        /* Adapter Request Block address */
-	__u32 asb;                        /* Adapter Status Block address */
-        __u8  init_srb_page;
-        __u8  srb_page;
-        __u8  ssb_page;
-        __u8  arb_page;
-        __u8  asb_page;
-	unsigned short exsap_station_id;
-	unsigned short global_int_enable;
-	struct sk_buff *current_skb;
-	struct net_device_stats tr_stats;
-	unsigned char auto_ringspeedsave;
-	open_state open_status;
-	unsigned char readlog_pending;
-	unsigned short adapter_int_enable; /* Adapter-specific int enable */
-        struct timer_list tr_timer;
-	unsigned char ring_speed;
-	__u32 func_addr;
-	unsigned int retry_count;
-	spinlock_t lock;		/* SMP protection */
-};
-
-/* token ring adapter commands */
-#define DIR_INTERRUPT 		0x00 /* struct srb_interrupt */
-#define DIR_MOD_OPEN_PARAMS 	0x01
-#define DIR_OPEN_ADAPTER 	0x03 /* struct dir_open_adapter */
-#define DIR_CLOSE_ADAPTER   	0x04
-#define DIR_SET_GRP_ADDR    	0x06
-#define DIR_SET_FUNC_ADDR   	0x07 /* struct srb_set_funct_addr */
-#define DIR_READ_LOG 		0x08 /* struct srb_read_log */
-#define DLC_OPEN_SAP 		0x15 /* struct dlc_open_sap */
-#define DLC_CLOSE_SAP       	0x16
-#define DATA_LOST 		0x20 /* struct asb_rec */
-#define REC_DATA 		0x81 /* struct arb_rec_req */
-#define XMIT_DATA_REQ 		0x82 /* struct arb_xmit_req */
-#define DLC_STATUS 		0x83 /* struct arb_dlc_status */
-#define RING_STAT_CHANGE    	0x84 /* struct dlc_open_sap ??? */
-
-/* DIR_OPEN_ADAPTER options */
-#define OPEN_PASS_BCON_MAC 0x0100
-#define NUM_RCV_BUF 2
-#define RCV_BUF_LEN 1024
-#define DHB_LENGTH 2048
-#define NUM_DHB 2
-#define DLC_MAX_SAP 2
-#define DLC_MAX_STA 1
-
-/* DLC_OPEN_SAP options */
-#define MAX_I_FIELD 0x0088
-#define SAP_OPEN_IND_SAP 0x04
-#define SAP_OPEN_PRIORITY 0x20
-#define SAP_OPEN_STATION_CNT 0x1
-#define XMIT_DIR_FRAME 0x0A
-#define XMIT_UI_FRAME  0x0d
-#define XMIT_XID_CMD   0x0e
-#define XMIT_TEST_CMD  0x11
-
-/* srb close return code */
-#define SIGNAL_LOSS  0x8000
-#define HARD_ERROR   0x4000
-#define XMIT_BEACON  0x1000
-#define LOBE_FAULT   0x0800
-#define AUTO_REMOVAL 0x0400
-#define REMOVE_RECV  0x0100
-#define LOG_OVERFLOW 0x0080
-#define RING_RECOVER 0x0020
-
-struct srb_init_response {
-	unsigned char command;
-	unsigned char init_status;
-	unsigned char init_status_2;
-	unsigned char reserved[3];
-	__u16 bring_up_code;
-	__u16 encoded_address;
-	__u16 level_address;
-	__u16 adapter_address;
-	__u16 parms_address;
-	__u16 mac_address;
-};
-
-struct dir_open_adapter {
-	unsigned char command;
-	char reserved[7];
-	__u16 open_options;
-	unsigned char node_address[6];
-	unsigned char group_address[4];
-	unsigned char funct_address[4];
-	__u16 num_rcv_buf;
-	__u16 rcv_buf_len;
-	__u16 dhb_length;
-	unsigned char num_dhb;
-	char reserved2;
-	unsigned char dlc_max_sap;
-	unsigned char dlc_max_sta;
-	unsigned char dlc_max_gsap;
-	unsigned char dlc_max_gmem;
-	unsigned char dlc_t1_tick_1;
-	unsigned char dlc_t2_tick_1;
-	unsigned char dlc_ti_tick_1;
-	unsigned char dlc_t1_tick_2;
-	unsigned char dlc_t2_tick_2;
-	unsigned char dlc_ti_tick_2;
-	unsigned char product_id[18];
-};
-
-struct srb_open_response {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2[3];
-	__u16 error_code;
-	__u16 asb_addr;
-	__u16 srb_addr;
-	__u16 arb_addr;
-	__u16 ssb_addr;
-};
-
-struct dlc_open_sap {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2;
-	__u16 station_id;
-	unsigned char timer_t1;
-	unsigned char timer_t2;
-	unsigned char timer_ti;
-	unsigned char maxout;
-	unsigned char maxin;
-	unsigned char maxout_incr;
-	unsigned char max_retry_count;
-	unsigned char gsap_max_mem;
-	__u16 max_i_field;
-	unsigned char sap_value;
-	unsigned char sap_options;
-	unsigned char station_count;
-	unsigned char sap_gsap_mem;
-	unsigned char gsap[0];
-};
-
-struct srb_xmit {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char ret_code;
-	unsigned char reserved1;
-	__u16 station_id;
-};
-
-struct srb_interrupt {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char ret_code;
-};
-
-struct srb_read_log {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2;
-	unsigned char line_errors;
-	unsigned char internal_errors;
-	unsigned char burst_errors;
-	unsigned char A_C_errors;
-	unsigned char abort_delimiters;
-	unsigned char reserved3;
-	unsigned char lost_frames;
-	unsigned char recv_congest_count;
-	unsigned char frame_copied_errors;
-	unsigned char frequency_errors;
-	unsigned char token_errors;
-};
-
-struct asb_xmit_resp {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char ret_code;
-	unsigned char reserved;
-	__u16 station_id;
-	__u16 frame_length;
-	unsigned char hdr_length;
-	unsigned char rsap_value;
-};
-
-struct arb_xmit_req {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char reserved1[2];
-	__u16 station_id;
-	__u16 dhb_address;
-};
-
-struct arb_rec_req {
-	unsigned char command;
-	unsigned char reserved1[3];
-	__u16 station_id;
-	__u16 rec_buf_addr;
-	unsigned char lan_hdr_len;
-	unsigned char dlc_hdr_len;
-	__u16 frame_len;
-	unsigned char msg_type;
-};
-
-struct asb_rec {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2;
-	__u16 station_id;
-	__u16 rec_buf_addr;
-};
-
-struct rec_buf {
-  /*	unsigned char reserved1[2]; */
-	__u16 buf_ptr;
-	unsigned char reserved2;
-	__u16 buf_len;
-	unsigned char data[0];
-};
-
-struct arb_dlc_status {
-	unsigned char command;
-	unsigned char reserved1[3];
-	__u16 station_id;
-	__u16 status;
-	unsigned char frmr_data[5];
-	unsigned char access_prio;
-	unsigned char rem_addr[TR_ALEN];
-	unsigned char rsap_value;
-};
-
-struct arb_ring_stat_change {
-	unsigned char command;
-	unsigned char reserved1[5];
-	__u16 ring_status;
-};
-
-struct srb_close_adapter {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-};
-
-struct srb_set_funct_addr {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2[3];
-	unsigned char funct_address[4];
-};
-
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c
--- v2.4.4/linux/drivers/net/tokenring/olympic.c	Wed Apr 18 11:39:21 2001
+++ linux/drivers/net/tokenring/olympic.c	Sun May 20 12:11:38 2001
@@ -64,10 +64,7 @@
 
 #define OLYMPIC_DEBUG 0
 
-
-#include <linux/config.h>
 #include <linux/module.h>
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c
--- v2.4.4/linux/drivers/net/tokenring/smctr.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/tokenring/smctr.c	Wed May 16 10:31:27 2001
@@ -1,7 +1,7 @@
 /*
  *  smctr.c: A network driver for the SMC Token Ring Adapters.
  *
- *  Written by Jay Schulist <jschlst@turbolinux.com>
+ *  Written by Jay Schulist <jschlst@samba.org>
  *
  *  This software may be used and distributed according to the terms
  *  of the GNU General Public License, incorporated herein by reference.
@@ -14,7 +14,7 @@
  *  	- SMC TokenCard SDK.
  *
  *  Maintainer(s):
- *    JS        Jay Schulist <jschlst@turbolinux.com>
+ *    JS        Jay Schulist <jschlst@samba.org>
  *
  * Changes:
  *    07102000          JS      Fixed a timing problem in smctr_wait_cmd();
@@ -62,7 +62,7 @@
 #include "smctr.h"               /* Our Stuff */
 #include "smctr_firmware.h"      /* SMC adapter firmware */
 
-static char version[] __initdata = KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@turbolinux.com\n";
+static char version[] __initdata = KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@samba.org\n";
 static const char cardname[] = "smctr";
 
 
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tokenring/smctr.h linux/drivers/net/tokenring/smctr.h
--- v2.4.4/linux/drivers/net/tokenring/smctr.h	Wed May 10 16:56:42 2000
+++ linux/drivers/net/tokenring/smctr.h	Wed May 16 10:31:27 2001
@@ -1,7 +1,7 @@
 /* smctr.h: SMC Token Ring driver header for Linux
  *
  * Authors:
- *  - Jay Schulist <jschlst@turbolinux.com>
+ *  - Jay Schulist <jschlst@samba.org>
  */
 
 #ifndef __LINUX_SMCTR_H
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tokenring/smctr_firmware.h linux/drivers/net/tokenring/smctr_firmware.h
--- v2.4.4/linux/drivers/net/tokenring/smctr_firmware.h	Mon Dec 11 12:59:51 2000
+++ linux/drivers/net/tokenring/smctr_firmware.h	Wed May 16 10:31:27 2001
@@ -14,7 +14,7 @@
  *  - This is an 8K binary image. (MCT.BIN v6.3C1 03/01/95)
  *
  * Authors:
- *  - Jay Schulist <jschlst@turbolinux.com>
+ *  - Jay Schulist <jschlst@samba.org>
  */
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c
--- v2.4.4/linux/drivers/net/tokenring/tms380tr.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/tokenring/tms380tr.c	Wed May 16 10:31:27 2001
@@ -28,7 +28,7 @@
  *  	- Various Madge employees
  *
  *  Maintainer(s):
- *    JS	Jay Schulist		jschlst@turbolinux.com
+ *    JS	Jay Schulist		jschlst@samba.org
  *    CG	Christoph Goos		cgoos@syskonnect.de
  *    AF	Adam Fritzler		mid@auk.cx
  *    MLP       Mike Phillips           phillim@amtrak.com
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c
--- v2.4.4/linux/drivers/net/tulip/21142.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/21142.c	Wed May 16 10:25:39 2001
@@ -100,16 +100,14 @@
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	int csr14 = ((tp->to_advertise & 0x0780) << 9)  |
-		((tp->to_advertise&0x0020)<<1) | 0xffbf;
-
-	DPRINTK("ENTER\n");
+	int csr14 = ((tp->sym_advertise & 0x0780) << 9)  |
+		((tp->sym_advertise & 0x0020) << 1) | 0xffbf;
 
 	dev->if_port = 0;
 	tp->nway = tp->mediasense = 1;
 	tp->nwayset = tp->lpar = 0;
 	if (tp->chip_id == PNIC2) {
-		tp->csr6 = 0x01000000 | (tp->to_advertise & 0x0040 ? FullDuplex : 0);
+		tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0);
 		return;
 	}
 	if (tulip_debug > 1)
@@ -118,7 +116,7 @@
 	outl(0x0001, ioaddr + CSR13);
 	udelay(100);
 	outl(csr14, ioaddr + CSR14);
-	tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? FullDuplex : 0);
+	tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0);
 	tulip_outl_csr(tp, tp->csr6, CSR6);
 	if (tp->mtable  &&  tp->mtable->csr15dir) {
 		outl(tp->mtable->csr15dir, ioaddr + CSR15);
@@ -129,6 +127,24 @@
 }
 
 
+void pnic2_lnk_change(struct net_device *dev, int csr5)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr12 = inl(ioaddr + CSR12);
+
+	if (tulip_debug > 1)
+		printk(KERN_INFO"%s: PNIC-2 link status changed, CSR5/12/14 %8.8x"
+			" %8.8x, %8.8x.\n",
+			dev->name, csr12, csr5, (int)inl(ioaddr + CSR14));
+	dev->if_port = 5;
+	tp->lpar = csr12 >> 16;
+	tp->nwayset = 1;
+	tp->csr6 = 0x01000000 | (tp->csr6 & 0xffff);
+	outl(tp->csr6, ioaddr + CSR6);
+
+}
+
 void t21142_lnk_change(struct net_device *dev, int csr5)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -142,7 +158,7 @@
 	/* If NWay finished and we have a negotiated partner capability. */
 	if (tp->nway  &&  !tp->nwayset  &&  (csr12 & 0x7000) == 0x5000) {
 		int setup_done = 0;
-		int negotiated = tp->to_advertise & (csr12 >> 16);
+		int negotiated = tp->sym_advertise & (csr12 >> 16);
 		tp->lpar = csr12 >> 16;
 		tp->nwayset = 1;
 		if (negotiated & 0x0100)		dev->if_port = 5;
@@ -151,7 +167,7 @@
 		else if (negotiated & 0x0020)	dev->if_port = 0;
 		else {
 			tp->nwayset = 0;
-			if ((csr12 & 2) == 0  &&  (tp->to_advertise & 0x0180))
+			if ((csr12 & 2) == 0  &&  (tp->sym_advertise & 0x0180))
 				dev->if_port = 3;
 		}
 		tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0;
@@ -160,7 +176,7 @@
 			if (tp->nwayset)
 				printk(KERN_INFO "%s: Switching to %s based on link "
 					   "negotiation %4.4x & %4.4x = %4.4x.\n",
-					   dev->name, medianame[dev->if_port], tp->to_advertise,
+					   dev->name, medianame[dev->if_port], tp->sym_advertise,
 					   tp->lpar, negotiated);
 			else
 				printk(KERN_INFO "%s: Autonegotiation failed, using %s,"
@@ -173,7 +189,7 @@
 			for (i = 0; i < tp->mtable->leafcount; i++)
 				if (tp->mtable->mleaf[i].media == dev->if_port) {
 					tp->cur_index = i;
-					tulip_select_media(dev, 0);
+					tulip_select_media(dev, 1);
 					setup_done = 1;
 					break;
 				}
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog
--- v2.4.4/linux/drivers/net/tulip/ChangeLog	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/ChangeLog	Sat May 19 18:02:45 2001
@@ -1,3 +1,182 @@
+2001-05-18  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c: Added ethtool support.
+	  ETHTOOL_GDRVINFO ioctl only, for now.
+
+2001-05-14  Robert Olsson <Robert.Olsson@data.slu.se>
+
+	* Restored HW_FLOWCONTROL from Linux 2.1 series tulip (ANK)
+	  plus Jamal's NETIF_RX_* feedback control.
+
+2001-05-14  Robert Olsson <Robert.Olsson@data.slu.se>
+
+	* Added support for 21143's Interrupt Mitigation.
+	  Jamal original instigator.
+
+2001-05-14  Robert Olsson <Robert.Olsson@data.slu.se>
+
+	* tulip_refill_rx prototype added to tulip.h
+
+2001-05-13  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c: Remove HAS_PCI_MWI flag from Comet, untested.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c, tulip.h: Remove Conexant PCI id, no chip
+	docs are available to fix problems with support.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_init_one): Do not call
+	unregister_netdev in error cleanup.  Remnant of old
+	usage of init_etherdev.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_find_mii): Simple write the updated BMCR
+	twice, as it seems the best thing to do for both broken and
+	sane chips.
+	If the mii_advert value, as read from MII_ADVERTISE, is zero,
+	then generate a value we should advertise from the capability
+	bits in BMSR.
+	Fill in tp->advertising for all cases.
+	Just to be safe, clear all unwanted bits.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (private_ioctl):  Fill in tp->advertising
+	when advertising value is changed by the user.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c: Mark Comet chips as needed the updated MWI
+	csr0 configuration.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c, tulip_core.c:  Move MII scan into
+	from inlined inside tulip_init_one to new function
+	tulip_find_mii in media.c.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_check_duplex):
+	Only restart Rx/Tx engines if they are active
+	(and csr6 changes)
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_mwi_config):
+	Clamp values read from PCI cache line size register to
+	values acceptable to tulip chip.  Done for safety and
+	-almost- certainly unneeded.
+
+2001-05-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_init_one):
+	Instead of unconditionally enabling autonegotiation, disable
+	autonegotiation if not using the default port.  Further,
+	flip the nway bit immediately, and then update the
+	speed/duplex in a separate MII transaction.  We do this
+	because some boards require that nway be disabled separately,
+	before media selection is forced.
+
+	TODO: Investigate if we can simply write the same value
+	to BMCR twice, to avoid setting unnecessarily changing
+	phy settings.
+
+2001-05-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip.h, tulip_core.c:  If HAS_PCI_MWI is set for a
+	given chip, adjust the csr0 values not according to
+	provided values but according to system cache line size.
+	Currently cache alignment is matched as closely to cache
+	line size as possible.  Currently programmable burst limit
+	is set (ie. never unlimited), and always equal to cache
+	alignment and system cache size.  Currently MWI bit is set
+	only if the MWI bit is present in the PCI command register.
+
+2001-05-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_select_media):
+	For media types 1 and 3, only use the provided eeprom
+	advertising value if it is non-zero.
+	(tulip_check_duplex):
+	Do not exit ASAP if full_duplex_lock is set.  This
+	ensures that the csr6 value is written if an update
+	is needed.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	Merge PNIC-II-specific stuff from Becker's tulip.c:
+
+	* tulip.h, 21142.c (pnic2_lnk_change): new function
+	* tulip_core.c (tulip_init_one): use it
+
+	* tulip_core.c (tulip_tx_timeout): Add specific
+	debugging for PNIC2.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_init_one): Print out
+	tulip%d instead of PCI device number, for
+	consistency.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* Merge changes from Becker's tulip.c:
+	Fix bugs in ioctl.
+	Fix several bugs by distinguishing between MII
+	and SYM advertising values.
+	Set CSR14 autonegotiation bit for media types 2 and 4,
+	where the SIA CSR setup values are not provided.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_select_media): Only update MII
+	advertising value if startup arg < 2.
+
+	* tulip.h: Do not enable CSR13/14/15 autoconfiguration
+	for 21041.
+
+	* tulip_core.c:
+	21041: add specific code for reset, and do not set CAC bit
+	When resetting media, for media table type 11 media, pass
+	value 2 as 'startup' arg to select_media, to avoid updating
+	MII advertising value.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* pnic.c (pnic_check_duplex): remove
+	pnic.c (pnic_lnk_change, pnic_timer): use
+	tulip_check_duplex not pnic_check_duplex.
+
+	* media.c (tulip_check_duplex):
+	Clean up to use symbolic names instead of numeric constants.
+	Set TxThreshold mode as necessary as well as clearing it.
+	Update csr6 if csr6 changes, not simply if duplex changes.
+
+	(found by Manfred Spraul)
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* 21142.c, eeprom.c, tulip.h, tulip_core.c:
+	Remove DPRINTK as another, better method of
+	debug message printing is available.
+
+2001-05-09  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* 21142.c (t21142_lnk_change): Pass arg startup==1
+	to tulip_select_media, in order to force csr13 to be
+	zeroed out prior to going to full duplex mode.  Fixes
+	autonegotiation on a quad-port Znyx card.
+	(from Stephen Dengler)
+
+2001-05-09  Russell King  <rmk@arm.linux.org.uk>
+
+	* interrupt.c: Better PCI bus error reporting.
+
 2001-04-03  Jeff Garzik  <jgarzik@mandrakesoft.com>
 
 	* tulip_core.c: Now that dev->name is only available late
@@ -29,7 +208,7 @@
 	  the following defines existed.  These defines were never used
 	  by normal users in practice: TULIP_FULL_DUPLEX,
 	  TULIP_DEFAULT_MEDIA, and TULIP_NO_MEDIA_SWITCH.
-	  
+
 	* tulip.h, eeprom.c: Move EE_* constants from tulip.h to eeprom.c.
 	* tulip.h, media.c: Move MDIO_* constants from tulip.h to media.c.
 
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/eeprom.c linux/drivers/net/tulip/eeprom.c
--- v2.4.4/linux/drivers/net/tulip/eeprom.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/eeprom.c	Wed May 16 10:25:39 2001
@@ -167,7 +167,8 @@
 
 	        /* there is no phy information, don't even try to build mtable */
 	        if (count == 0) {
-			DPRINTK("no phy info, aborting mtable build\n");
+			if (tulip_debug > 0)
+				printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
 		        return;
 		}
 
@@ -259,7 +260,7 @@
 				   leaf->type);
 		}
 		if (new_advertise)
-			tp->to_advertise = new_advertise;
+			tp->sym_advertise = new_advertise;
 	}
 }
 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c
--- v2.4.4/linux/drivers/net/tulip/interrupt.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/interrupt.c	Sun May 20 12:11:38 2001
@@ -15,6 +15,7 @@
 */
 
 #include "tulip.h"
+#include <linux/config.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
 
@@ -22,6 +23,42 @@
 int tulip_rx_copybreak;
 unsigned int tulip_max_interrupt_work;
 
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+
+#define MIT_SIZE 15
+unsigned int mit_table[MIT_SIZE+1] =
+{
+        /*  CRS11 21143 hardware Mitigation Control Interrupt 
+            We use only RX mitigation we other techniques for 
+            TX intr. mitigation.
+
+           31    Cycle Size (timer control)
+           30:27 TX timer in 16 * Cycle size
+           26:24 TX No pkts before Int.
+           23:20 RX timer in Cycle size
+           19:17 RX No pkts before Int.
+           16       Continues Mode (CM)
+        */
+                         
+        0x0,             /* IM disabled */
+        0x80150000,      /* RX time = 1, RX pkts = 2, CM = 1 */
+        0x80150000,
+        0x80270000,
+        0x80370000,
+        0x80490000,
+        0x80590000,
+        0x80690000,
+        0x807B0000,
+        0x808B0000,
+        0x809D0000,
+        0x80AD0000,
+        0x80BD0000,
+        0x80CF0000,
+        0x80DF0000,
+//       0x80FF0000      /* RX time = 16, RX pkts = 7, CM = 1 */
+        0x80F10000      /* RX time = 16, RX pkts = 0, CM = 1 */
+};
+#endif
 
 
 int tulip_refill_rx(struct net_device *dev)
@@ -70,6 +107,15 @@
 	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
 	int received = 0;
 
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+        int drop = 0, mit_sel = 0;
+
+/* that one buffer is needed for mit activation; or might be a 
+   bug in the ring buffer code; check later -- JHS*/
+
+        if (rx_work_limit >=RX_RING_SIZE) rx_work_limit--;
+#endif
+
 	if (tulip_debug > 4)
 		printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
 			   tp->rx_ring[entry].status);
@@ -116,6 +162,12 @@
 				tp->stats.rx_length_errors++;
 			}
 #endif
+
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                        drop = atomic_read(&netdev_dropping);
+                        if (drop)
+                                goto throttle;
+#endif
 			/* Check if the packet is long enough to accept without copying
 			   to a minimally-sized skbuff. */
 			if (pkt_len < tulip_rx_copybreak
@@ -157,7 +209,44 @@
 				tp->rx_buffers[entry].mapping = 0;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                        mit_sel = 
+#endif
 			netif_rx(skb);
+
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                        switch (mit_sel) {
+                        case NET_RX_SUCCESS:
+                        case NET_RX_CN_LOW:
+                        case NET_RX_CN_MOD:
+                                break;
+
+                        case NET_RX_CN_HIGH:
+                                rx_work_limit -= NET_RX_CN_HIGH; /* additional*/
+                                break;
+                        case NET_RX_DROP:
+                                rx_work_limit = -1;
+                                break;
+                        default:
+                                printk("unknown feedback return code %d\n", mit_sel);
+                                break;
+                        }
+
+                        drop = atomic_read(&netdev_dropping);
+                        if (drop) {
+throttle:
+                                rx_work_limit = -1;
+                                mit_sel = NET_RX_DROP;
+
+                                if (tp->fc_bit) {
+                                        long ioaddr = dev->base_addr;
+
+                                        /* disable Rx & RxNoBuf ints. */
+                                        outl(tulip_tbl[tp->chip_id].valid_intrs&RX_A_NBF_STOP, ioaddr + CSR7);
+                                        set_bit(tp->fc_bit, &netdev_fc_xoff);
+                                }
+                        }
+#endif
 			dev->last_rx = jiffies;
 			tp->stats.rx_packets++;
 			tp->stats.rx_bytes += pkt_len;
@@ -165,8 +254,41 @@
 		received++;
 		entry = (++tp->cur_rx) % RX_RING_SIZE;
 	}
+#ifdef CONFIG_NET_HW_FLOWCONTROL
 
+        /* We use this simplistic scheme for IM. It's proven by
+           real life installations. We can have IM enabled
+           continuesly but this would cause unnecessary latency. 
+           Unfortunely we can't use all the NET_RX_* feedback here. 
+           This would turn on IM for devices that is not contributing 
+           to backlog congestion with unnecessary latency. 
+
+           We monitor the the device RX-ring and have:
+
+           HW Interrupt Mitigation either ON or OFF.
+
+           ON:  More then 1 pkt received (per intr.) OR we are dropping 
+           OFF: Only 1 pkt received
+           
+           Note. We only use min and max (0, 15) settings from mit_table */
+
+
+        if( tp->flags &  HAS_INTR_MITIGATION) {
+                if((received > 1 || mit_sel == NET_RX_DROP) 
+                   && tp->mit_sel != 15 ) { 
+                        tp->mit_sel = 15; 
+                        tp->mit_change = 1; /* Force IM change */
+                }
+                if((received <= 1 && mit_sel != NET_RX_DROP) && tp->mit_sel != 0 ) {
+                        tp->mit_sel = 0; 
+                        tp->mit_change = 1; /* Force IM change */
+                }
+        }
+
+        return RX_RING_SIZE+1; /* maxrx+1 */      
+#else
 	return received;
+#endif
 }
 
 
@@ -205,8 +327,22 @@
 				   dev->name, csr5, inl(dev->base_addr + CSR5));
 
 		if (csr5 & (RxIntr | RxNoBuf)) {
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                        if (tp->fc_bit) {
+                                if (test_bit(tp->fc_bit, &netdev_fc_xoff)) {
+                                        tulip_refill_rx(dev);
+                                } else {
+                                        tulip_refill_rx(dev);
+                                        rx += tulip_rx(dev);
+                                }
+                        } else {        /* not in fc mode */
+                                rx += tulip_rx(dev);
+                                tulip_refill_rx(dev);
+                        }
+#else
 			rx += tulip_rx(dev);
 			tulip_refill_rx(dev);
+#endif
 		}
 
 		if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
@@ -308,9 +444,17 @@
 				}
 			}
 			if (csr5 & RxDied) {		/* Missed a Rx frame. */
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                                if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
+                                        tp->stats.rx_errors++;
+                                        tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6);
+                                }
+                                tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+#else
 				tp->stats.rx_errors++;
 				tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
 				tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6);
+#endif
 			}
 			/*
 			 * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this
@@ -344,6 +488,10 @@
 			if (tulip_debug > 2)
 				printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
 					   dev->name, csr5);
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                        if (tp->fc_bit && (test_bit(tp->fc_bit, &netdev_fc_xoff)))
+                          if (net_ratelimit()) printk("BUG!! enabling interupt when FC off (timerintr.) \n");
+#endif
 			outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
 			tp->ttimer = 0;
 			oi++;
@@ -356,9 +504,16 @@
                        /* Acknowledge all interrupt sources. */
                         outl(0x8001ffff, ioaddr + CSR5);
                         if (tp->flags & HAS_INTR_MITIGATION) {
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+                                if(tp->mit_change) {
+                                        outl(mit_table[tp->mit_sel], ioaddr + CSR11);
+                                        tp->mit_change = 0;
+                                }
+#else
                      /* Josip Loncaric at ICASE did extensive experimentation
 			to develop a good interrupt mitigation setting.*/
                                 outl(0x8b240000, ioaddr + CSR11);
+#endif
                         } else if (tp->chip_id == LC82C168) {
 				/* the LC82C168 doesn't have a hw timer.*/
 				outl(0x00, ioaddr + CSR7);
@@ -366,8 +521,10 @@
 			} else {
                           /* Mask all interrupting sources, set timer to
 				re-enable. */
+#ifndef CONFIG_NET_HW_FLOWCONTROL
                                 outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
                                 outl(0x0012, ioaddr + CSR11);
+#endif
                         }
 			break;
 		}
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/media.c linux/drivers/net/tulip/media.c
--- v2.4.4/linux/drivers/net/tulip/media.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/media.c	Wed May 16 10:25:39 2001
@@ -14,6 +14,10 @@
 
 */
 
+#include <linux/kernel.h>
+#include <linux/mii.h>
+#include <linux/init.h>
+#include <linux/delay.h>
 #include "tulip.h"
 
 
@@ -228,7 +232,7 @@
 				outl(csr13val, ioaddr + CSR13);
 			} else {
 				csr13val = 1;
-				csr14val = 0x0003FF7F;
+				csr14val = 0x0003FFFF;
 				csr15dir = (setup[0]<<16) | 0x0008;
 				csr15val = (setup[1]<<16) | 0x0008;
 				if (dev->if_port <= 4)
@@ -253,8 +257,7 @@
 		case 1: case 3: {
 			int phy_num = p[0];
 			int init_length = p[1];
-			u16 *misc_info;
-			u16 to_advertise;
+			u16 *misc_info, tmp_info;
 
 			dev->if_port = 11;
 			new_csr6 = 0x020E0000;
@@ -281,13 +284,17 @@
 				for (i = 0; i < init_length; i++)
 					outl(init_sequence[i], ioaddr + CSR12);
 			}
-			to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;
-			tp->advertising[phy_num] = to_advertise;
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d (%d).\n",
-					   dev->name, to_advertise, phy_num, tp->phys[phy_num]);
-			/* Bogus: put in by a committee?  */
-			tulip_mdio_write(dev, tp->phys[phy_num], 4, to_advertise);
+			tmp_info = get_u16(&misc_info[1]);
+			if (tmp_info)
+				tp->advertising[phy_num] = tmp_info | 1;
+			if (tmp_info && startup < 2) {
+				if (tp->mii_advertise == 0)
+					tp->mii_advertise = tp->advertising[phy_num];
+				if (tulip_debug > 1)
+					printk(KERN_DEBUG "%s:  Advertising %4.4x on MII %d.\n",
+					       dev->name, tp->mii_advertise, tp->phys[phy_num]);
+				tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise);
+			}
 			break;
 		}
 		case 5: case 6: {
@@ -397,52 +404,164 @@
 }
 
 /*
-  Check the MII negotiated duplex, and change the CSR6 setting if
+  Check the MII negotiated duplex and change the CSR6 setting if
   required.
   Return 0 if everything is OK.
   Return < 0 if the transceiver is missing or has no link beat.
   */
 int tulip_check_duplex(struct net_device *dev)
 {
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	int mii_reg1, mii_reg5, negotiated, duplex;
+	long ioaddr = dev->base_addr;
+	struct tulip_private *tp = dev->priv;
+	unsigned int bmsr, lpa, negotiated, new_csr6;
 
-	if (tp->full_duplex_lock)
-		return 0;
-	mii_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-	mii_reg5 = tulip_mdio_read(dev, tp->phys[0], 5);
+	bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
+	lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA);
 	if (tulip_debug > 1)
 		printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
-			   "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
-	if (mii_reg1 == 0xffff)
+			   "%4.4x.\n", dev->name, bmsr, lpa);
+	if (bmsr == 0xffff)
 		return -2;
-	if ((mii_reg1 & 0x0004) == 0) {
-		int new_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-		if ((new_reg1 & 0x0004) == 0) {
+	if ((bmsr & BMSR_LSTATUS) == 0) {
+		int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
+		if ((new_bmsr & BMSR_LSTATUS) == 0) {
 			if (tulip_debug  > 1)
 				printk(KERN_INFO "%s: No link beat on the MII interface,"
-					   " status %4.4x.\n", dev->name, new_reg1);
+					   " status %4.4x.\n", dev->name, new_bmsr);
 			return -1;
 		}
 	}
-	negotiated = mii_reg5 & tp->advertising[0];
-	duplex = ((negotiated & 0x0300) == 0x0100
-			  || (negotiated & 0x00C0) == 0x0040);
-	/* 100baseTx-FD  or  10T-FD, but not 100-HD */
-	if (tp->full_duplex != duplex) {
-		tp->full_duplex = duplex;
-		if (negotiated & 0x038)	/* 100mbps. */
-			tp->csr6 &= ~0x00400000;
-		if (tp->full_duplex) tp->csr6 |= 0x0200;
-		else				 tp->csr6 &= ~0x0200;
-		tulip_restart_rxtx(tp, tp->csr6);
+	negotiated = lpa & tp->advertising[0];
+	tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated);
+
+	new_csr6 = tp->csr6;
+
+	if (negotiated & LPA_100) new_csr6 &= ~TxThreshold;
+	else			  new_csr6 |= TxThreshold;
+	if (tp->full_duplex) new_csr6 |= FullDuplex;
+	else		     new_csr6 &= ~FullDuplex;
+
+	if (new_csr6 != tp->csr6) {
+		if (inl(ioaddr + CSR6) & (csr6_st | csr6_sr))
+			tulip_restart_rxtx(tp, new_csr6);
+		else
+			outl(new_csr6, ioaddr + CSR6);
+		tp->csr6 = new_csr6;
+
 		if (tulip_debug > 0)
 			printk(KERN_INFO "%s: Setting %s-duplex based on MII"
 				   "#%d link partner capability of %4.4x.\n",
 				   dev->name, tp->full_duplex ? "full" : "half",
-				   tp->phys[0], mii_reg5);
+				   tp->phys[0], lpa);
 		return 1;
 	}
+
 	return 0;
 }
 
+void __devinit tulip_find_mii (struct net_device *dev, int board_idx)
+{
+	struct tulip_private *tp = dev->priv;
+	int phyn, phy_idx = 0;
+	int mii_reg0;
+	int mii_advert;
+	unsigned int to_advert, new_bmcr, ane_switch;
+
+	/* Find the connected MII xcvrs.
+	   Doing this in open() would allow detecting external xcvrs later,
+	   but takes much time. */
+	for (phyn = 1; phyn <= 32 && phy_idx < sizeof (tp->phys); phyn++) {
+		int phy = phyn & 0x1f;
+		int mii_status = tulip_mdio_read (dev, phy, MII_BMSR);
+		if ((mii_status & 0x8301) == 0x8001 ||
+		    ((mii_status & BMSR_100BASE4) == 0
+		     && (mii_status & 0x7800) != 0)) {
+			/* preserve Becker logic, gain indentation level */
+		} else {
+			continue;
+		}
+
+		mii_reg0 = tulip_mdio_read (dev, phy, MII_BMCR);
+		mii_advert = tulip_mdio_read (dev, phy, MII_ADVERTISE);
+		ane_switch = 0;
+
+		/* if not advertising at all, gen an
+		 * advertising value from the capability
+		 * bits in BMSR
+		 */
+		if ((mii_advert & ADVERTISE_ALL) == 0) {
+			unsigned int tmpadv = tulip_mdio_read (dev, phy, MII_BMSR);
+			mii_advert = ((tmpadv >> 6) & 0x3e0) | 1;
+		}
+
+		if (tp->mii_advertise) {
+			tp->advertising[phy_idx] =
+			to_advert = tp->mii_advertise;
+		} else if (tp->advertising[phy_idx]) {
+			to_advert = tp->advertising[phy_idx];
+		} else {
+			tp->advertising[phy_idx] =
+			tp->mii_advertise =
+			to_advert = mii_advert;
+		}
+
+		tp->phys[phy_idx++] = phy;
+
+		printk (KERN_INFO "tulip%d:  MII transceiver #%d "
+			"config %4.4x status %4.4x advertising %4.4x.\n",
+			board_idx, phy, mii_reg0, mii_status, mii_advert);
+
+		/* Fixup for DLink with miswired PHY. */
+		if (mii_advert != to_advert) {
+			printk (KERN_DEBUG "tulip%d:  Advertising %4.4x on PHY %d,"
+				" previously advertising %4.4x.\n",
+				board_idx, to_advert, phy, mii_advert);
+			tulip_mdio_write (dev, phy, 4, to_advert);
+		}
+
+		/* Enable autonegotiation: some boards default to off. */
+		if (tp->default_port == 0) {
+			new_bmcr = mii_reg0 | BMCR_ANENABLE;
+			if (new_bmcr != mii_reg0) {
+				new_bmcr |= BMCR_ANRESTART;
+				ane_switch = 1;
+			}
+		}
+		/* ...or disable nway, if forcing media */
+		else {
+			new_bmcr = mii_reg0 & ~BMCR_ANENABLE;
+			if (new_bmcr != mii_reg0)
+				ane_switch = 1;
+		}
+
+		/* clear out bits we never want at this point */
+		new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE |
+			      BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK |
+			      BMCR_RESET);
+
+		if (tp->full_duplex)
+			new_bmcr |= BMCR_FULLDPLX;
+		if (tulip_media_cap[tp->default_port] & MediaIs100)
+			new_bmcr |= BMCR_SPEED100;
+
+		if (new_bmcr != mii_reg0) {
+			/* some phys need the ANE switch to
+			 * happen before forced media settings
+			 * will "take."  However, we write the
+			 * same value twice in order not to
+			 * confuse the sane phys.
+			 */
+			if (ane_switch) {
+				tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
+				udelay (10);
+			}
+			tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
+		}
+	}
+	tp->mii_cnt = phy_idx;
+	if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
+		printk (KERN_INFO "tulip%d: ***WARNING***: No MII transceiver found!\n",
+			board_idx);
+		tp->phys[0] = 1;
+	}
+}
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/pnic.c linux/drivers/net/tulip/pnic.c
--- v2.4.4/linux/drivers/net/tulip/pnic.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/pnic.c	Sat May 19 18:02:45 2001
@@ -51,62 +51,6 @@
 	}
 }
 
-/* Modified version of tulip_check_duplex:
- * Always update the 100mbps bit, even if the
- * full duplex bit didn't change.
- *	Manfred Spraul <manfred@colorfullife.com>
- */
-int pnic_check_duplex(struct net_device *dev)
-{
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	int mii_reg1, mii_reg5, negotiated, duplex;
-	int new_csr6;
-
-	mii_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-	mii_reg5 = tulip_mdio_read(dev, tp->phys[0], 5);
-	if (tulip_debug > 1)
-		printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
-			   "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
-	if (mii_reg1 == 0xffff)
-		return -2;
-	if ((mii_reg1 & 0x0004) == 0) {
-		int new_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-		if ((new_reg1 & 0x0004) == 0) {
-			if (tulip_debug  > 1)
-				printk(KERN_INFO "%s: No link beat on the MII interface,"
-					   " status %4.4x.\n", dev->name, new_reg1);
-			return -1;
-		}
-	}
-	negotiated = mii_reg5 & tp->advertising[0];
-	/* 100baseTx-FD  or  10T-FD, but not 100-HD */
-	duplex = ((negotiated & 0x0300) == 0x0100
-			  || (negotiated & 0x00C0) == 0x0040) ||
-		tp->full_duplex_lock;
-
-	new_csr6 = tp->csr6;
-	if (negotiated & 0x0380)	/* 100mbps. */
-		new_csr6 &= ~0x00400000;
-	 else
-		new_csr6 |= 0x00400000;
-	if (duplex)
-		new_csr6 |= 0x0200;
-	 else	
-		new_csr6 &= ~0x0200;
-	if (new_csr6 != tp->csr6) {
-		tp->full_duplex = duplex;
-		tp->csr6 = new_csr6;
-		if (tulip_debug > 0)
-			printk(KERN_INFO "%s: Setting %s-duplex based on MII"
-				   "#%d link partner capability of %4.4x.\n",
-				   dev->name, tp->full_duplex ? "full" : "half",
-				   tp->phys[0], mii_reg5);
-		tulip_restart_rxtx(tp, tp->csr6);
-		return 1;
-	}
-	return 0;
-}
-
 void pnic_lnk_change(struct net_device *dev, int csr5)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -133,7 +77,7 @@
 	} else if (inl(ioaddr + CSR5) & TPLnkPass) {
 		if (tulip_media_cap[dev->if_port] & MediaIsMII) {
 			spin_lock(&tp->lock);
-			pnic_check_duplex(dev);
+			tulip_check_duplex(dev);
 			spin_unlock(&tp->lock);
 		} else {
 			pnic_do_nway(dev);
@@ -142,8 +86,6 @@
 	}
 }
 
-int tulip_refill_rx(struct net_device *dev);
-
 void pnic_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
@@ -162,7 +104,7 @@
 
 	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
 		spin_lock_irq(&tp->lock);
-		if (pnic_check_duplex(dev) > 0)
+		if (tulip_check_duplex(dev) > 0)
 			next_tick = 3*HZ;
 		spin_unlock_irq(&tp->lock);
 	} else {
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h
--- v2.4.4/linux/drivers/net/tulip/tulip.h	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/tulip.h	Sun May 20 12:11:38 2001
@@ -16,6 +16,7 @@
 #ifndef __NET_TULIP_H__
 #define __NET_TULIP_H__
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
@@ -27,17 +28,7 @@
 
 
 /* undefine, or define to various debugging levels (>4 == obscene levels) */
-#undef TULIP_DEBUG
-
-
-#ifdef TULIP_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-
+#define TULIP_DEBUG 1
 
 
 struct tulip_chip_table {
@@ -62,6 +53,7 @@
 	IS_ASIX			= 0x0200,
 	HAS_8023X		= 0x0400,
 	COMET_MAC_ADDR		= 0x0800,
+	HAS_PCI_MWI		= 0x1000,
 };
 
 
@@ -83,7 +75,6 @@
 	COMPEX9881,
 	I21145,
 	DM910X,
-	CONEXANT,
 };
 
 
@@ -145,8 +136,9 @@
 };
 
 
-enum tulip_rx_modes {
-	FullDuplex		= 0x0200,
+enum tulip_mode_bits {
+	TxThreshold		= (1 << 22),
+	FullDuplex		= (1 << 9),
 	AcceptBroadcast		= 0x0100,
 	AcceptAllMulticast	= 0x0080,
 	AcceptAllPhys		= 0x0040,
@@ -154,6 +146,15 @@
 };
 
 
+enum tulip_busconfig_bits {
+	MWI			= (1 << 24),
+	MRL			= (1 << 23),
+	MRM			= (1 << 21),
+	CALShift		= 14,
+	BurstLenShift		= 8,
+};
+
+
 /* The Tulip Rx and Tx buffer descriptors. */
 struct tulip_rx_desc {
 	s32 status;
@@ -184,8 +185,8 @@
 	csr13_cac = (1<<2), /* CSR13/14/15 autoconfiguration */
 	csr13_srl = (1<<0), /* When reset, resets all SIA functions, machines */
 
-	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_cac | csr13_srl),
-	csr13_mask_10bt = (csr13_eng | csr13_cac | csr13_srl),
+	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_srl),
+	csr13_mask_10bt = (csr13_eng | csr13_srl),
 };
 
 enum t21143_csr6_bits {
@@ -255,6 +256,18 @@
 
 #define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
 
+#define TULIP_MIN_CACHE_LINE	8	/* in units of 32-bit words */
+
+#if defined(__sparc__) || defined(__hppa__)
+/* The UltraSparc PCI controllers will disconnect at every 64-byte
+ * crossing anyways so it makes no sense to tell Tulip to burst
+ * any more than that.
+ */
+#define TULIP_MAX_CACHE_LINE	16	/* in units of 32-bit words */
+#else
+#define TULIP_MAX_CACHE_LINE	32	/* in units of 32-bit words */
+#endif
+
 
 /* Ring-wrap flag in length field, use for last ring entry.
 	0x01000000 means chain on buffer2 address,
@@ -333,6 +346,13 @@
 	spinlock_t mii_lock;
 	unsigned int cur_rx, cur_tx;	/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+#define RX_A_NBF_STOP 0xffffff3f /* To disable RX and RX-NOBUF ints. */
+        int fc_bit;
+        int mit_sel;
+        int mit_change; /* Signal for Interrupt Mitigtion */
+#endif
 	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
 	unsigned int full_duplex_lock:1;
 	unsigned int fake_addr:1;	/* Multiport board faked address. */
@@ -345,7 +365,7 @@
 	unsigned int csr6;	/* Current CSR6 control settings. */
 	unsigned char eeprom[EEPROM_SIZE];	/* Serial EEPROM contents. */
 	void (*link_change) (struct net_device * dev, int csr5);
-	u16 to_advertise;	/* NWay capabilities advertised.  */
+	u16 sym_advertise, mii_advertise; /* NWay capabilities advertised.  */
 	u16 lpar;		/* 21143 Link partner ability. */
 	u16 advertising[4];
 	signed char phys[4], mii_cnt;	/* MII device addresses. */
@@ -375,6 +395,7 @@
 void t21142_timer(unsigned long data);
 void t21142_start_nway(struct net_device *dev);
 void t21142_lnk_change(struct net_device *dev, int csr5);
+void pnic2_lnk_change(struct net_device *dev, int csr5);
 
 /* eeprom.c */
 void tulip_parse_eeprom(struct net_device *dev);
@@ -384,12 +405,14 @@
 extern unsigned int tulip_max_interrupt_work;
 extern int tulip_rx_copybreak;
 void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+int tulip_refill_rx(struct net_device *dev);
 
 /* media.c */
 int tulip_mdio_read(struct net_device *dev, int phy_id, int location);
 void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int value);
 void tulip_select_media(struct net_device *dev, int startup);
 int tulip_check_duplex(struct net_device *dev);
+void tulip_find_mii (struct net_device *dev, int board_idx);
 
 /* pnic.c */
 void pnic_do_nway(struct net_device *dev);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- v2.4.4/linux/drivers/net/tulip/tulip_core.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/tulip_core.c	Sun May 20 12:11:38 2001
@@ -14,16 +14,24 @@
 
 */
 
+#define DRV_NAME	"tulip"
+#define DRV_VERSION	"0.9.15-pre2"
+#define DRV_RELDATE	"May 16, 2001"
+
+#include <linux/config.h>
 #include <linux/module.h>
 #include "tulip.h"
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <asm/unaligned.h>
+#include <asm/uaccess.h>
 
 static char version[] __devinitdata =
-	"Linux Tulip driver version 0.9.14e (April 20, 2001)\n";
+	"Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n";
 
 
 /* A few user-configurable values. */
@@ -100,8 +108,7 @@
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
-#define TULIP_MODULE_NAME "tulip"
-#define PFX TULIP_MODULE_NAME ": "
+#define PFX DRV_NAME ": "
 
 #ifdef TULIP_DEBUG
 int tulip_debug = TULIP_DEBUG;
@@ -127,12 +134,12 @@
 
   /* DC21140 */
   { "Digital DS21140 Tulip", 128, 0x0001ebef,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer },
 
   /* DC21142, DC21143 */
   { "Digital DS21143 Tulip", 128, 0x0801fbff,
 	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY
-	| HAS_INTR_MITIGATION, t21142_timer },
+	| HAS_INTR_MITIGATION | HAS_PCI_MWI, t21142_timer },
 
   /* LC82C168 */
   { "Lite-On 82c168 PNIC", 256, 0x0001fbef,
@@ -152,11 +159,12 @@
 
   /* AX88140 */
   { "ASIX AX88140", 128, 0x0001fbff,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY | IS_ASIX, tulip_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
+	| IS_ASIX, tulip_timer },
 
   /* PNIC2 */
   { "Lite-On PNIC-II", 256, 0x0801fbff,
-	HAS_MII | HAS_NWAY | HAS_8023X, t21142_timer },
+	HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, t21142_timer },
 
   /* COMET */
   { "ADMtek Comet", 256, 0x0001abef,
@@ -168,18 +176,13 @@
 
   /* I21145 */
   { "Intel DS21145 Tulip", 128, 0x0801fbff,
-	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY,
-	t21142_timer },
+	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI
+	| HAS_NWAY | HAS_PCI_MWI, t21142_timer },
 
   /* DM910X */
   { "Davicom DM9102/DM9102A", 128, 0x0001ebef,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
 	tulip_timer },
-
-  /* CONEXANT */
-  { "Conexant LANfinity", 0x100, 0x0001ebef,
-	HAS_MII | HAS_ACPI,
-	tulip_timer },
 };
 
 
@@ -208,7 +211,6 @@
 	{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
 	{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
-	{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
 	{ } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -269,8 +271,6 @@
 	int next_tick = 3*HZ;
 	int i;
 
-	DPRINTK("ENTER\n");
-
 	/* Wake the chip from sleep/snooze mode. */
 	tulip_set_power_state (tp, 0, 0);
 
@@ -379,10 +379,30 @@
 	tp->csr6 = 0;
 	tp->cur_index = i;
 	tp->nwayset = 0;
-	if (dev->if_port == 0  && tp->chip_id == DC21041)
-		tp->nway = 1;
 
-	if (dev->if_port == 0  &&  tp->chip_id == DC21142) {
+	if (dev->if_port) {
+		if (tp->chip_id == DC21143  &&
+		    (tulip_media_cap[dev->if_port] & MediaIsMII)) {
+			/* We must reset the media CSRs when we force-select MII mode. */
+			outl(0x0000, ioaddr + CSR13);
+			outl(0x0000, ioaddr + CSR14);
+			outl(0x0008, ioaddr + CSR15);
+		}
+		tulip_select_media(dev, 1);
+	} else if (tp->chip_id == DC21041) {
+		dev->if_port = 0;
+		tp->nway = tp->mediasense = 1;
+		tp->nwayset = tp->lpar = 0;
+		outl(0x00000000, ioaddr + CSR13);
+		outl(0xFFFFFFFF, ioaddr + CSR14);
+		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
+		tp->csr6 = 0x80020000;
+		if (tp->sym_advertise & 0x0040)
+			tp->csr6 |= FullDuplex;
+		outl(tp->csr6, ioaddr + CSR6);
+		outl(0x0000EF01, ioaddr + CSR13);
+
+	} else if (tp->chip_id == DC21142) {
 		if (tp->mii_cnt) {
 			tulip_select_media(dev, 1);
 			if (tulip_debug > 1)
@@ -424,12 +444,6 @@
 		tp->csr6 = 0x01a80200;
 		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
 		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
-	} else if (tp->chip_id == DC21143  &&
-			   tulip_media_cap[dev->if_port] & MediaIsMII) {
-		/* We must reset the media CSRs when we force-select MII mode. */
-		outl(0x0000, ioaddr + CSR13);
-		outl(0x0000, ioaddr + CSR14);
-		outl(0x0008, ioaddr + CSR15);
 	} else if (tp->chip_id == COMET) {
 		/* Enable automatic Tx underrun recovery. */
 		outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
@@ -464,10 +478,27 @@
 	add_timer(&tp->timer);
 }
 
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+/* Enable receiver */
+void tulip_xon(struct net_device *dev)
+{
+        struct tulip_private *tp = (struct tulip_private *)dev->priv;
+
+        clear_bit(tp->fc_bit, &netdev_fc_xoff);
+        if (netif_running(dev)){
+
+                tulip_refill_rx(dev);
+                outl(tulip_tbl[tp->chip_id].valid_intrs,  dev->base_addr+CSR7);
+        }
+}
+#endif
 
 static int
 tulip_open(struct net_device *dev)
 {
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+        struct tulip_private *tp = (struct tulip_private *)dev->priv;
+#endif
 	int retval;
 	MOD_INC_USE_COUNT;
 
@@ -480,6 +511,10 @@
 
 	tulip_up (dev);
 
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+        tp->fc_bit = netdev_register_fc(dev, tulip_xon);
+#endif
+
 	netif_start_queue (dev);
 
 	return 0;
@@ -492,8 +527,6 @@
 	long ioaddr = dev->base_addr;
 	unsigned long flags;
 
-	DPRINTK("ENTER\n");
-
 	spin_lock_irqsave (&tp->lock, flags);
 
 	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
@@ -549,6 +582,11 @@
 			printk(KERN_WARNING "%s: transmit timed out, switching to %s "
 				   "media.\n", dev->name, medianame[dev->if_port]);
 		}
+	} else if (tp->chip_id == PNIC2) {
+		printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, "
+		       "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n",
+		       dev->name, (int)inl(ioaddr + CSR5), (int)inl(ioaddr + CSR6),
+		       (int)inl(ioaddr + CSR7), (int)inl(ioaddr + CSR12));
 	} else {
 		printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 "
 			   "%8.8x, resetting...\n",
@@ -584,6 +622,10 @@
 #endif
 
 	/* Stop and restart the chip's Tx processes . */
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+        if (tp->fc_bit && test_bit(tp->fc_bit,&netdev_fc_xoff))
+                printk("BUG tx_timeout restarting rx when fc on\n");
+#endif
 	tulip_restart_rxtx(tp, tp->csr6);
 	/* Trigger an immediate transmit demand. */
 	outl(0, ioaddr + CSR1);
@@ -603,8 +645,6 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 
-	DPRINTK("ENTER\n");
-
 	tp->cur_rx = tp->cur_tx = 0;
 	tp->dirty_rx = tp->dirty_tx = 0;
 	tp->susp_rx = 0;
@@ -742,6 +782,13 @@
 
 	netif_stop_queue (dev);
 
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+        if (tp->fc_bit) {
+                int bit = tp->fc_bit;
+                tp->fc_bit = 0;
+                netdev_unregister_fc(bit);
+        }
+#endif
 	tulip_down (dev);
 
 	if (tulip_debug > 1)
@@ -803,16 +850,43 @@
 }
 
 
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+	struct tulip_private *np = dev->priv;
+	u32 ethcmd;
+		
+	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+		return -EFAULT;
+
+        switch (ethcmd) {
+        case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		strcpy(info.driver, DRV_NAME);
+		strcpy(info.version, DRV_VERSION);
+		strcpy(info.bus_info, np->pdev->slot_name);
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+
+        }
+	
+	return -EOPNOTSUPP;
+}
+
 /* Provide ioctl() calls to examine the MII xcvr state. */
 static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct tulip_private *tp = dev->priv;
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *) & rq->ifr_data;
-	int phy = tp->phys[0] & 0x1f;
+	const unsigned int phy_idx = 0;
+	int phy = tp->phys[phy_idx] & 0x1f;
 	unsigned int regnum = data[1];
 
 	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
 		if (tp->mii_cnt)
 			data[0] = phy;
@@ -828,26 +902,31 @@
 			int csr14 = inl (ioaddr + CSR14);
 			switch (regnum) {
 			case 0:
-				data[3] = (csr14 << 5) & 0x1000;
+                                if (((csr14<<5) & 0x1000) ||
+                                        (dev->if_port == 5 && tp->nwayset))
+                                        data[3] = 0x1000;
+                                else
+                                        data[3] = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0)
+                                                | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0);
 				break;
 			case 1:
-				data[3] =
-				  0x7848 +
-				  ((csr12 & 0x7000) == 0x5000 ? 0x20 : 0) +
-				  (csr12 & 0x06 ? 0x04 : 0);
+                                data[3] =
+					0x1848 +
+					((csr12&0x7000) == 0x5000 ? 0x20 : 0) +
+					((csr12&0x06) == 6 ? 0 : 4);
+                                if (tp->chip_id != DC21041)
+                                        data[3] |= 0x6048;
 				break;
 			case 4:
-				data[3] =
-				  ((csr14 >> 9) & 0x07C0) +
-				  ((inl (ioaddr + CSR6) >> 3) & 0x0040) +
-				  ((csr14 >> 1) & 0x20) + 1;
-				break;
-			case 5:
-				data[3] = csr12 >> 16;
-				break;
-			default:
-				data[3] = 0;
+                                /* Advertised value, bogus 10baseTx-FD value from CSR6. */
+                                data[3] =
+					((inl(ioaddr + CSR6) >> 3) & 0x0040) + 
+					((csr14 >> 1) & 0x20) + 1;
+                                if (tp->chip_id != DC21041)
+                                         data[3] |= ((csr14 >> 9) & 0x03C0);
 				break;
+			case 5: data[3] = tp->lpar; break;
+			default: data[3] = 0; break;
 			}
 		} else {
 			data[3] = tulip_mdio_read (dev, data[0] & 0x1f, regnum);
@@ -867,7 +946,8 @@
 					tp->full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
 			case 4:
-				tp->to_advertise = data[2];
+				tp->advertising[phy_idx] =
+				tp->mii_advertise = data[2];
 				break;
 			}
 		}
@@ -877,7 +957,7 @@
 				if ((value & 0x1200) == 0x1200)
 					t21142_start_nway (dev);
 			} else if (regnum == 4)
-				tp->to_advertise = value;
+				tp->sym_advertise = value;
 		} else {
 			tulip_mdio_write (dev, data[0] & 0x1f, regnum, data[2]);
 		}
@@ -998,8 +1078,6 @@
 	long ioaddr = dev->base_addr;
 	int csr6;
 
-	DPRINTK("ENTER\n");
-
 	csr6 = inl(ioaddr + CSR6) & ~0x00D5;
 
 	tp->csr6 &= ~0x00D5;
@@ -1119,6 +1197,91 @@
 	tulip_outl_csr(tp, csr6 | 0x0000, CSR6);
 }
 
+static void __devinit tulip_mwi_config (struct pci_dev *pdev,
+					struct net_device *dev)
+{
+	struct tulip_private *tp = dev->priv;
+	u8 pci_cacheline;
+	u16 pci_command, new_command;
+	unsigned mwi = 1;
+	
+	if (tulip_debug > 3)
+		printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pdev->slot_name);
+
+	/* get a sane cache line size, if possible */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+	if (pci_cacheline < (SMP_CACHE_BYTES / 4))
+		pci_cacheline = SMP_CACHE_BYTES / 4;
+	if (pci_cacheline > TULIP_MAX_CACHE_LINE)
+		pci_cacheline = TULIP_MAX_CACHE_LINE;
+	switch (pci_cacheline) {
+	case 8:
+	case 16:
+	case 32: break;
+	default: pci_cacheline = TULIP_MIN_CACHE_LINE; break;
+	}
+	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
+
+	/* read back the result.  if zero, or if a buggy chip rev,
+	 * disable MWI
+	 */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+	if (!pci_cacheline || (tp->chip_id == DC21143 && tp->revision == 65))
+		mwi = 0;
+
+	/* re-clamp cache line values to ones supported by tulip */
+	/* From this point forward, 'pci_cacheline' is really
+	 * the value used for csr0 cache alignment and
+	 * csr0 programmable burst length
+	 */
+	switch (pci_cacheline) {
+	case 0:
+	case 8:
+	case 16:
+	case 32: break;
+	default: pci_cacheline = TULIP_MIN_CACHE_LINE; break;
+	}
+
+	/* set or disable MWI in the standard PCI command bit.
+	 * Check for the case where  mwi is desired but not available
+	 */
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+	if (mwi)	new_command = pci_command | PCI_COMMAND_INVALIDATE;
+	else		new_command = pci_command & ~PCI_COMMAND_INVALIDATE;
+	if (new_command != pci_command) {
+		pci_write_config_word(pdev, PCI_COMMAND, new_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+		if ((new_command != pci_command) && mwi &&
+		    ((pci_command & PCI_COMMAND_INVALIDATE) == 0))
+			mwi = 0;
+	}
+
+	tp->csr0 = MRL | MRM;	
+
+	/* if no PCI cache line size, bail out with minimal
+	 * burst size and cache alignment of 8 dwords.
+	 * We always want to have some sort of limit.
+	 */
+	if (!pci_cacheline) {
+		tp->csr0 |= (8 << BurstLenShift) | (1 << CALShift);
+		goto out;
+	}
+	
+	/* finally, build the csr0 value */
+	if (mwi)
+		tp->csr0 |= MWI;
+	tp->csr0 |= (pci_cacheline << BurstLenShift);
+	switch (pci_cacheline) {
+	case 8:  tp->csr0 |= (1 << CALShift);
+	case 16: tp->csr0 |= (2 << CALShift);
+	case 32: tp->csr0 |= (3 << CALShift);
+	}
+
+out:
+	if (tulip_debug > 2)
+		printk(KERN_DEBUG "%s: MWI config mwi=%d, cacheline=%d, csr0=%08x\n",
+		       pdev->slot_name, mwi, pci_cacheline, tp->csr0);
+}
 
 static int __devinit tulip_init_one (struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
@@ -1136,8 +1299,9 @@
 	long ioaddr;
 	static int board_idx = -1;
 	int chip_idx = ent->driver_data;
-	int t2104x_mode = 0;
-	int eeprom_missing = 0;
+	unsigned int t2104x_mode = 0;
+	unsigned int eeprom_missing = 0;
+	unsigned int force_csr0 = 0;
 
 #ifndef MODULE
 	static int did_version;		/* Already printed version info. */
@@ -1183,12 +1347,26 @@
 	   thankfully its an old 486 chipset.
 	*/
 	
-	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL))
-		csr0 = 0x00A04800;
+	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) {
+		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
+		force_csr0 = 1;
+	}
 	/* The dreaded SiS496 486 chipset. Same workaround as above. */
-	if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL))
-		csr0 = 0x00A04800;
+	if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL)) {
+		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
+		force_csr0 = 1;
+	}
 		
+	/* bugfix: the ASIX must have a burst limit or horrible things happen. */
+	if (chip_idx == AX88140) {
+		if ((csr0 & 0x3f00) == 0)
+			csr0 |= 0x2000;
+	}
+	
+	/* PNIC doesn't have MWI/MRL/MRM... */
+	if (chip_idx == LC82C168)
+		csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
+
 	/*
 	 *	And back to business
 	 */
@@ -1255,13 +1433,8 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	/* bugfix: the ASIX must have a burst limit or horrible things happen. */
-	if (chip_idx == AX88140) {
-		if ((tp->csr0 & 0x3f00) == 0)
-			tp->csr0 |= 0x2000;
-	}
-	else if (chip_idx == DC21143  &&  chip_rev == 65)
-		tp->csr0 &= ~0x01000000;
+	if (!force_csr0 && (tp->flags & HAS_PCI_MWI))
+		tulip_mwi_config (pdev, dev);
 
 	/* Stop the chip's Tx and Rx processes. */
 	tulip_stop_rxtx(tp, inl(ioaddr + CSR6));
@@ -1373,8 +1546,8 @@
 	if (dev->mem_start & MEDIA_MASK)
 		tp->default_port = dev->mem_start & MEDIA_MASK;
 	if (tp->default_port) {
-		printk(KERN_INFO "%s: Transceiver selection forced to %s.\n",
-		       pdev->slot_name, medianame[tp->default_port & MEDIA_MASK]);
+		printk(KERN_INFO "tulip%d: Transceiver selection forced to %s.\n",
+		       board_idx, medianame[tp->default_port & MEDIA_MASK]);
 		tp->medialock = 1;
 		if (tulip_media_cap[tp->default_port] & MediaAlwaysFD)
 			tp->full_duplex = 1;
@@ -1384,11 +1557,9 @@
 
 	if (tulip_media_cap[tp->default_port] & MediaIsMII) {
 		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
-		tp->to_advertise = media2advert[tp->default_port - 9];
-	} else if (tp->flags & HAS_8023X)
-		tp->to_advertise = 0x05e1;
-	else
-		tp->to_advertise = 0x01e1;
+		tp->mii_advertise = media2advert[tp->default_port - 9];
+		tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
+	}
 
 	if (tp->flags & HAS_MEDIA_TABLE) {
 		memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
@@ -1401,55 +1572,21 @@
 	if ((tp->flags & ALWAYS_CHECK_MII) ||
 		(tp->mtable  &&  tp->mtable->has_mii) ||
 		( ! tp->mtable  &&  (tp->flags & HAS_MII))) {
-		int phyn, phy_idx = 0;
 		if (tp->mtable  &&  tp->mtable->has_mii) {
 			for (i = 0; i < tp->mtable->leafcount; i++)
 				if (tp->mtable->mleaf[i].media == 11) {
 					tp->cur_index = i;
 					tp->saved_if_port = dev->if_port;
-					tulip_select_media(dev, 1);
+					tulip_select_media(dev, 2);
 					dev->if_port = tp->saved_if_port;
 					break;
 				}
 		}
+
 		/* Find the connected MII xcvrs.
-		   Doing this in open() would allow detecting external xcvrs later,
-		   but takes much time. */
-		for (phyn = 1; phyn <= 32 && phy_idx < sizeof(tp->phys); phyn++) {
-			int phy = phyn & 0x1f;
-			int mii_status = tulip_mdio_read(dev, phy, 1);
-			if ((mii_status & 0x8301) == 0x8001 ||
-				((mii_status & 0x8000) == 0  && (mii_status & 0x7800) != 0)) {
-				int mii_reg0 = tulip_mdio_read(dev, phy, 0);
-				int mii_advert = tulip_mdio_read(dev, phy, 4);
-				int reg4 = ((mii_status>>6) & tp->to_advertise) | 1;
-				tp->phys[phy_idx] = phy;
-				tp->advertising[phy_idx++] = reg4;
-				printk(KERN_INFO "%s:  MII transceiver #%d "
-					   "config %4.4x status %4.4x advertising %4.4x.\n",
-					   pdev->slot_name, phy, mii_reg0, mii_status, mii_advert);
-				/* Fixup for DLink with miswired PHY. */
-				if (mii_advert != reg4) {
-					printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d,"
-						   " previously advertising %4.4x.\n",
-						   pdev->slot_name, reg4, phy, mii_advert);
-					printk(KERN_DEBUG "%s:  Advertising %4.4x (to advertise"
-						   " is %4.4x).\n",
-						   pdev->slot_name, reg4, tp->to_advertise);
-					tulip_mdio_write(dev, phy, 4, reg4);
-				}
-				/* Enable autonegotiation: some boards default to off. */
-				tulip_mdio_write(dev, phy, 0, mii_reg0 |
-						   (tp->full_duplex ? 0x1100 : 0x1000) |
-						   (tulip_media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
-			}
-		}
-		tp->mii_cnt = phy_idx;
-		if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {
-			printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
-			       pdev->slot_name);
-			tp->phys[0] = 1;
-		}
+		   Doing this in open() would allow detecting external xcvrs
+		   later, but takes much time. */
+		tulip_find_mii (dev, board_idx);
 	}
 
 	/* The Tulip-specific entries in the device structure. */
@@ -1481,18 +1618,21 @@
 
 	if ((tp->flags & HAS_NWAY)  || tp->chip_id == DC21041)
 		tp->link_change = t21142_lnk_change;
+	else if (tp->chip_id == PNIC2)
+		tp->link_change = pnic2_lnk_change;
 	else if (tp->flags & HAS_PNICNWAY)
 		tp->link_change = pnic_lnk_change;
 
 	/* Reset the xcvr interface and turn on heartbeat. */
 	switch (chip_idx) {
 	case DC21041:
-		tp->to_advertise = 0x0061;
+		if (tp->sym_advertise == 0)
+			tp->sym_advertise = 0x0061;
 		outl(0x00000000, ioaddr + CSR13);
 		outl(0xFFFFFFFF, ioaddr + CSR14);
 		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
 		tulip_outl_csr(tp, inl(ioaddr + CSR6) | csr6_fd, CSR6);
-		outl(0x0000EF05, ioaddr + CSR13);
+		outl(0x0000EF01, ioaddr + CSR13);
 		break;
 	case DC21040:
 		outl(0x00000000, ioaddr + CSR13);
@@ -1552,7 +1692,6 @@
 err_out_free_res:
 	pci_release_regions (pdev);
 err_out_free_netdev:
-	unregister_netdev (dev);
 	kfree (dev);
 	return -ENODEV;
 }
@@ -1610,7 +1749,7 @@
 
 
 static struct pci_driver tulip_driver = {
-	name:		TULIP_MODULE_NAME,
+	name:		DRV_NAME,
 	id_table:	tulip_pci_tbl,
 	probe:		tulip_init_one,
 	remove:		tulip_remove_one,
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/comx-hw-comx.c linux/drivers/net/wan/comx-hw-comx.c
--- v2.4.4/linux/drivers/net/wan/comx-hw-comx.c	Mon Oct  2 12:00:16 2000
+++ linux/drivers/net/wan/comx-hw-comx.c	Tue May 22 10:23:16 2001
@@ -1044,10 +1044,20 @@
 		if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
 			return -ENOMEM;
 		}
-		copy_from_user(page, buffer, count = (min(count, PAGE_SIZE)));
-		if (*(page + count - 1) == '\n') {
-			*(page + count - 1) = 0;
+		if(copy_from_user(page, buffer, count = (min(count, PAGE_SIZE))))
+		{
+			count = -EFAULT;
+			goto out;
+		}
+		if (page[count-1] == '\n')
+			page[count-1] = '\0';
+		else if (count < PAGE_SIZE)
+			page[count] = '\0';
+		else if (page[count]) {
+ 			count = -EINVAL;
+			goto out;
 		}
+		page[count]=0;	/* Null terminate */
 	} else {
 		byte *tmp;
 
@@ -1140,7 +1150,7 @@
 			hw->clock = kbps ? COMX_CLOCK_CONST/kbps : 0;
 		}
 	}
-
+out:
 	free_page((unsigned long)page);
 	return count;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/comx.c linux/drivers/net/wan/comx.c
--- v2.4.4/linux/drivers/net/wan/comx.c	Tue Mar  6 19:44:36 2001
+++ linux/drivers/net/wan/comx.c	Tue May 22 10:23:16 2001
@@ -621,9 +621,20 @@
 
 	if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;
 
-	copy_from_user(page, buffer, count);
+	if(copy_from_user(page, buffer, count))
+	{
+		count = -EFAULT;
+		goto out;
+	}
 
-	if (*(page + count - 1) == '\n') *(page + count - 1) = 0;
+	if (page[count-1] == '\n')
+		page[count-1] = '\0';
+	else if (count < PAGE_SIZE)
+		page[count] = '\0';
+	else if (page[count]) {
+		count = -EINVAL;
+		goto out;
+	}
 
 	if (strcmp(entry->name, FILENAME_DEBUG) == 0) {
 		int i;
@@ -764,7 +775,7 @@
 			}
 		}
 	}
-
+out:
 	free_page((unsigned long)page);
 	return count;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c
--- v2.4.4/linux/drivers/net/wan/cycx_main.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/wan/cycx_main.c	Tue May 22 10:23:16 2001
@@ -3,7 +3,7 @@
 *
 * Author:	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
-* Copyright:	(c) 1998-2000 Arnaldo Carvalho de Melo
+* Copyright:	(c) 1998-2001 Arnaldo Carvalho de Melo
 *
 * Based on sdlamain.c by Gene Kozin <genek@compuserve.com> &
 *			 Jaspreet Singh	<jaspreet@sangoma.com>
@@ -13,8 +13,10 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* 2001/05/09	acme		Fix MODULE_DESC for debug, .bss nitpicks,
+* 				some cleanups
 * 2000/07/13	acme		remove useless #ifdef MODULE and crap
-*							#if KERNEL_VERSION > blah
+*				#if KERNEL_VERSION > blah
 * 2000/07/06	acme		__exit at cyclomx_cleanup
 * 2000/04/02	acme		dprintk and cycx_debug
 * 				module_init/module_exit
@@ -38,7 +40,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/slab.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>		/* kmalloc(), kfree() */
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
 #include <linux/module.h>	/* support for loadable modules */
 #include <linux/ioport.h>	/* request_region(), release_region() */
@@ -50,17 +52,17 @@
 
 /* Debug */
 
-unsigned int cycx_debug = 0;
+unsigned int cycx_debug;
 
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
 MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "cyclomx debug level");
+MODULE_PARM(cycx_debug, "i");
+MODULE_PARM_DESC(cycx_debug, "cyclomx debug level");
 
 /* Defines & Macros */
 
 #define	DRV_VERSION	0		/* version number */
-#define	DRV_RELEASE	9		/* release (minor version) number */
+#define	DRV_RELEASE	10		/* release (minor version) number */
 #define	MAX_CARDS	1		/* max number of adapters */
 
 #define	CONFIG_CYCLOMX_CARDS 1
@@ -82,10 +84,10 @@
 /* private data */
 static char drvname[]	= "cyclomx";
 static char fullname[]	= "CYCLOM 2X(tm) Sync Card Driver";
-static char copyright[] = "(c) 1998-2000 Arnaldo Carvalho de Melo "
+static char copyright[] = "(c) 1998-2001 Arnaldo Carvalho de Melo "
 			  "<acme@conectiva.com.br>";
 static int ncards = CONFIG_CYCLOMX_CARDS;
-static cycx_t *card_array = NULL;	/* adapter data space */
+static cycx_t *card_array;	/* adapter data space */
 
 /* Kernel Loadable Module Entry Points */
 
@@ -103,7 +105,7 @@
  */
 int __init cyclomx_init (void)
 {
-	int cnt, err = 0;
+	int cnt, err = -ENOMEM;
 
 	printk(KERN_INFO "%s v%u.%u %s\n",
 		fullname, DRV_VERSION, DRV_RELEASE, copyright);
@@ -112,9 +114,8 @@
 	ncards = min(ncards, MAX_CARDS);
 	ncards = max(ncards, 1);
 	card_array = kmalloc(sizeof(cycx_t) * ncards, GFP_KERNEL);
-
 	if (!card_array)
-		return -ENOMEM;
+		goto out;
 
 	memset(card_array, 0, sizeof(cycx_t) * ncards);
 
@@ -127,9 +128,9 @@
 		wandev->magic    = ROUTER_MAGIC;
 		wandev->name     = card->devname;
 		wandev->private  = card;
-		wandev->setup    = &setup;
-		wandev->shutdown = &shutdown;
-		wandev->ioctl    = &ioctl;
+		wandev->setup    = setup;
+		wandev->shutdown = shutdown;
+		wandev->ioctl    = ioctl;
 		err = register_wan_device(wandev);
 
 		if (err) {
@@ -140,14 +141,14 @@
 		}
 	}
 
-	if (cnt)
-		ncards = cnt;	/* adjust actual number of cards */
-	else {
+	err = -ENODEV;
+	if (!cnt) {
 		kfree(card_array);
-		err = -ENODEV;
+		goto out;
 	}
-
-	return err;
+	err = 0;
+	ncards = cnt;	/* adjust actual number of cards */
+out:	return err;
 }
 
 /*
@@ -182,29 +183,31 @@
  */
 static int setup (wan_device_t *wandev, wandev_conf_t *conf)
 {
+	int err = -EFAULT;
 	cycx_t *card;
-	int err = 0;
 	int irq;
 
 	/* Sanity checks */
+	
 	if (!wandev || !wandev->private || !conf)
-		return -EFAULT;
+		goto out;
 
 	card = wandev->private;
-
+	err = -EBUSY;
 	if (wandev->state != WAN_UNCONFIGURED)
-		return -EBUSY;
+		goto out;
 
+	err = -EINVAL;
 	if (!conf->data_size || !conf->data) {
 		printk(KERN_ERR "%s: firmware not found in configuration "
 				"data!\n", wandev->name);
-		return -EINVAL;
+		goto out;
 	}
 
 	if (conf->irq <= 0) {
 		printk(KERN_ERR "%s: can't configure without IRQ!\n",
 				wandev->name);
-		return -EINVAL;
+		goto out;
 	}
 
 	/* Allocate IRQ */
@@ -213,23 +216,21 @@
 	if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
 		printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
 				wandev->name, irq);
-		return -EINVAL;
+		goto out;
 	}
 
 	/* Configure hardware, load firmware, etc. */
 	memset(&card->hw, 0, sizeof(cycxhw_t));
-	card->hw.irq = irq;
+	card->hw.irq	 = irq;
 	card->hw.dpmbase = conf->maddr;
 	card->hw.dpmsize = CYCX_WINDOWSIZE;
-	card->hw.fwid = CFID_X25_2X;
-	card->lock = SPIN_LOCK_UNLOCKED;
+	card->hw.fwid	 = CFID_X25_2X;
+	card->lock	 = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&card->wait_stats);
-	err = cycx_setup(&card->hw, conf->data, conf->data_size);
 
-	if (err) {
-		free_irq(irq, card);
-		return err;
-	}
+	err = cycx_setup(&card->hw, conf->data, conf->data_size);
+	if (err)
+		goto out_irq;
 
 	/* Initialize WAN device data space */
 	wandev->irq       = irq;
@@ -254,11 +255,14 @@
 
 	if (err) {
 		cycx_down(&card->hw);
-		free_irq(irq, card);
-		return err;
+		goto out_irq;
 	}
 
-	return 0;
+	err = 0;
+out:	return err;
+out_irq:
+	free_irq(irq, card);
+	goto out;
 }
 
 /*
@@ -271,14 +275,16 @@
  */
 static int shutdown (wan_device_t *wandev)
 {
+	int ret = -EFAULT;
 	cycx_t *card;
 
 	/* sanity checks */
 	if (!wandev || !wandev->private)
-		return -EFAULT;
+		goto out;
 
+	ret = 0;
 	if (wandev->state == WAN_UNCONFIGURED)
-		return 0;
+		goto out;
 
 	card = wandev->private;
 	wandev->state = WAN_UNCONFIGURED;
@@ -286,8 +292,7 @@
 	printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
 			wandev->irq);
 	free_irq(wandev->irq, card);
-
-	return 0;
+out:	return ret;
 }
 
 /*
@@ -313,19 +318,20 @@
  */
 static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs)
 {
-#define	card	((cycx_t*)dev_id)
+	cycx_t *card = (cycx_t *)dev_id;
+
 	if (!card || card->wandev.state == WAN_UNCONFIGURED)
-		return;
+		goto out;
 
 	if (card->in_isr) {
 		printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
 				    card->devname, card->wandev.irq);
-		return;
+		goto out;
 	}
 
 	if (card->isr)
 		card->isr(card);
-#undef	card
+out:	return;
 }
 
 /*
@@ -355,10 +361,10 @@
 /* Set WAN device state.  */
 void cyclomx_set_state (cycx_t *card, int state)
 {
-	unsigned long host_cpu_flags;
+	unsigned long flags;
 	char *string_state = NULL;
 
-	spin_lock_irqsave(&card->lock, host_cpu_flags);
+	spin_lock_irqsave(&card->lock, flags);
 
 	if (card->wandev.state != state) {
 		switch (state) {
@@ -376,10 +382,8 @@
 	}
 
 	card->state_tick = jiffies;
-	spin_unlock_irqrestore(&card->lock, host_cpu_flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 module_init(cyclomx_init);
 module_exit(cyclomx_cleanup);
-
-/* End */
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/sdla_ppp.c linux/drivers/net/wan/sdla_ppp.c
--- v2.4.4/linux/drivers/net/wan/sdla_ppp.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/wan/sdla_ppp.c	Sun May 20 12:11:39 2001
@@ -115,7 +115,6 @@
 #endif
 
 #include <linux/if.h>
-#include <linux/wanpipe.h>
 #include <linux/sdla_ppp.h>		/* PPP firmware API definitions */
 #include <linux/sdlasfm.h>		/* S514 Type Definition */
 /****** Defines & Macros ****************************************************/
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/sdladrv.c linux/drivers/net/wan/sdladrv.c
--- v2.4.4/linux/drivers/net/wan/sdladrv.c	Thu Apr 12 12:11:39 2001
+++ linux/drivers/net/wan/sdladrv.c	Sun May 20 12:11:39 2001
@@ -90,6 +90,7 @@
 
 #if	defined(_LINUX_)	/****** Linux *******************************/
 
+#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
 #include <linux/stddef.h>	/* offsetof(), etc. */
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/syncppp.c linux/drivers/net/wan/syncppp.c
--- v2.4.4/linux/drivers/net/wan/syncppp.c	Wed Apr 18 14:40:07 2001
+++ linux/drivers/net/wan/syncppp.c	Tue May 22 10:23:16 2001
@@ -51,6 +51,7 @@
 #include <linux/random.h>
 #include <linux/pkt_sched.h>
 #include <asm/byteorder.h>
+#include <asm/uaccess.h>
 #include <linux/spinlock.h>
 #include <net/syncppp.h>
 
@@ -128,7 +129,7 @@
 
 static struct sppp *spppq;
 static struct timer_list sppp_keepalive_timer;
-static spinlock_t spppq_lock;
+static spinlock_t spppq_lock = SPIN_LOCK_UNLOCKED;
 
 static void sppp_keepalive (unsigned long dummy);
 static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
@@ -975,6 +976,14 @@
 			if(ifr->ifr_flags)
 				sp->pp_flags|=PP_DEBUG;
 			break;
+		case SPPPIOCGFLAGS:
+			if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags)))
+				return -EFAULT;
+			break;
+		case SPPPIOCSFLAGS:
+			if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags)))
+				return -EFAULT;
+			break;
 		default:
 			return -EINVAL;
 	}
@@ -1397,7 +1406,6 @@
 		debug=PP_DEBUG;
 	printk(KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n");
 	printk(KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & Jan \"Yenya\" Kasprzak.\n");
-	spin_lock_init(&spppq_lock);
 	sppp_packet_type.type=htons(ETH_P_WAN_PPP);	
 	dev_add_pack(&sppp_packet_type);
 	return 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wan/wanpipe_multppp.c linux/drivers/net/wan/wanpipe_multppp.c
--- v2.4.4/linux/drivers/net/wan/wanpipe_multppp.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/wan/wanpipe_multppp.c	Tue May 22 10:23:16 2001
@@ -599,6 +599,18 @@
 	chdlc_priv_area->if_ptr = pppdev;
 
 	/* prepare network device data space for registration */
+
+#ifdef LINUX_2_4
+	strcpy(dev->name,card->u.c.if_name);
+#else
+	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 
+	if(dev->name == NULL)
+	{
+		kfree(chdlc_priv_area);	
+		return -ENOMEM;
+	}
+	sprintf(dev->name, "%s", card->u.c.if_name);
+#endif
 	
 	/* Attach PPP protocol layer to pppdev
 	 * The sppp_attach() will initilize the dev structure
@@ -607,24 +619,17 @@
          *        if_open(), if_close(), if_send() and get_stats() functions.
          */
 	sppp_attach(pppdev);
-      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16)
 	dev = pppdev->dev;
-      #else
+#else
 	dev = &pppdev->dev;
-      #endif
+#endif
 	sp = &pppdev->sppp;
 	
 	/* Enable PPP Debugging */
 	// FIXME Fix this up somehow
 	//sp->pp_flags |= PP_DEBUG; 	
 	sp->pp_flags &= ~PP_CISCO;
-	
-      #ifdef LINUX_2_4
-	strcpy(dev->name,card->u.c.if_name);
-      #else
-	dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); 
-	sprintf(dev->name, "%s", card->u.c.if_name);
-      #endif
 
 	dev->init = &if_init;
 	dev->priv = chdlc_priv_area;
@@ -678,9 +683,9 @@
 	chdlc_private_area_t* chdlc_priv_area = dev->priv;
 	sdla_t* card = chdlc_priv_area->card;
 	wan_device_t* wandev = &card->wandev;
-      #ifdef LINUX_2_0
+#ifdef LINUX_2_0
 	int i;
-      #endif
+#endif
 	
 	/* NOTE: Most of the dev initialization was
          *       done in sppp_attach(), called by new_if() 
@@ -693,15 +698,15 @@
 	dev->stop		= &if_close;
 	dev->hard_start_xmit	= &if_send;
 	dev->get_stats		= &if_stats;
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
 	dev->tx_timeout		= &if_tx_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
-      #endif
+#endif
 
 
-      #ifdef LINUX_2_0
+#ifdef LINUX_2_0
 	dev->family		= AF_INET;
-      #endif	
+#endif	
  
 	/* Initialize hardware parameters */
 	dev->irq	= wandev->irq;
@@ -719,10 +724,10 @@
         dev->tx_queue_len = 100;
    
 	/* Initialize socket buffers */
-      #if !defined(LINUX_2_1) && !defined(LINUX_2_4)
+#if !defined(LINUX_2_1) && !defined(LINUX_2_4)
         for (i = 0; i < DEV_NUMBUFFS; ++i)
                 skb_queue_head_init(&dev->buffs[i]);
-      #endif
+#endif
 
 	return 0;
 }
@@ -768,13 +773,13 @@
 
 	/* Only one open per interface is allowed */
 
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
 	if (netif_running(dev))
 		return -EBUSY;
-      #else
+#else
 	if (dev->start)
 		return -EBUSY;		/* only one open is allowed */
-      #endif
+#endif
 
 	/* Start PPP Layer */
 	if (sppp_open(dev)){
@@ -784,13 +789,13 @@
 	do_gettimeofday(&tv);
 	chdlc_priv_area->router_start_time = tv.tv_sec;
  
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
 	netif_start_queue(dev);
-      #else
+#else
 	dev->interrupt = 0;
 	dev->tbusy = 0;
 	dev->start = 1;
-      #endif
+#endif
 	
 	wanpipe_open(card);
 
@@ -813,9 +818,9 @@
 	sppp_close(dev);
 	stop_net_queue(dev);
 
-      #ifndef LINUX_2_4
+#ifndef LINUX_2_4
 	dev->start=0;
-      #endif
+#endif
 
 	wanpipe_close(card);
 	
@@ -849,9 +854,9 @@
 	unsigned long smp_flags;
 	int err=0;
 
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
 	netif_stop_queue(dev);
-      #endif
+#endif
 
 	
 	if (skb == NULL){
@@ -865,7 +870,7 @@
 		return 0;
 	}
 
-      #ifndef LINUX_2_4
+#ifndef LINUX_2_4
 	if (dev->tbusy){
 
 		/* If our device stays busy for at least 5 seconds then we will
@@ -885,7 +890,7 @@
 		/* unbusy the interface */
 		dev->tbusy = 0;
 	}
-      #endif
+#endif
 
    	if (ntohs(skb->protocol) != htons(PVC_PROT)){
 		/* check the udp packet type */
@@ -927,12 +932,12 @@
 
 	}else{
 		++card->wandev.stats.tx_packets;
-              #if defined(LINUX_2_1) || defined(LINUX_2_4)
+#if defined(LINUX_2_1) || defined(LINUX_2_4)
        		card->wandev.stats.tx_bytes += skb->len;
-              #endif
-	      #ifdef LINUX_2_4
+#endif
+#ifdef LINUX_2_4
 		dev->trans_start = jiffies;
-	      #endif
+#endif
 		start_net_queue(dev);
 	}	
 
@@ -1499,15 +1504,15 @@
 		goto rx_exit;
 	}
 	
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
 	if (!netif_running(dev)){
 		goto rx_exit;
 	}
-      #else
+#else
 	if (!dev->start){ 
 		goto rx_exit;
 	}
-      #endif
+#endif
 
 	chdlc_priv_area = dev->priv;
 
@@ -2352,28 +2357,28 @@
 
 void s508_lock (sdla_t *card, unsigned long *smp_flags)
 {
-      #if defined(__SMP__) || defined(LINUX_2_4)
+#if defined(__SMP__) || defined(LINUX_2_4)
 	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
         if (card->next){
 		/* It is ok to use spin_lock here, since we
 		 * already turned off interrupts */
         	spin_lock(&card->next->wandev.lock);
 	}
-      #else
+#else
 	disable_irq(card->hw.irq);
-      #endif
+#endif
 }
 
 void s508_unlock (sdla_t *card, unsigned long *smp_flags)
 {
-      #if defined(__SMP__) || defined(LINUX_2_4)
+#if defined(__SMP__) || defined(LINUX_2_4)
 	if (card->next){
 		spin_unlock(&card->next->wandev.lock);
 	}
 	spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-      #else
+#else
 	enable_irq(card->hw.irq);
-      #endif           
+#endif           
 }
 
 
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/Config.in linux/drivers/net/wireless/Config.in
--- v2.4.4/linux/drivers/net/wireless/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/Config.in	Mon May  7 19:42:14 2001
@@ -0,0 +1,22 @@
+#
+# Wireless LAN device configuration
+#
+
+###tristate '  Hermes chipset support' CONFIG_NET_ORINOCO
+###dep_tristate '    PCMCIA Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)' CONFIG_PCMCIA_HERMES $CONFIG_NET_ORINOCO $CONFIG_PCMCIA
+
+if [ "$CONFIG_ALL_PPC" = "y" ]; then
+   tristate '  Apple Airport support (built-in)' CONFIG_APPLE_AIRPORT
+fi
+
+# If Pcmcia is compiled in, offer Pcmcia cards...
+if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
+   comment 'Wireless Pcmcia cards support' 
+
+   dep_tristate '  Hermes support (Orinoco/WavelanIEEE/PrismII/Symbol 802.11b cards)' CONFIG_PCMCIA_HERMES $CONFIG_PCMCIA
+
+# If one of the Pcmcia cards above is enabled, activate Pcmcia network support
+   if [ "$CONFIG_PCMCIA_HERMES" = "y" ]; then
+      define_bool CONFIG_PCMCIA_NETCARD y
+   fi
+fi
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/Makefile linux/drivers/net/wireless/Makefile
--- v2.4.4/linux/drivers/net/wireless/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/Makefile	Mon May  7 19:42:14 2001
@@ -0,0 +1,27 @@
+#
+# drivers/net/wireless/Makefile
+#
+# Makefile for the Linux Wireless network device drivers.
+#
+
+O_TARGET := orinoco_drvs.o
+
+obj-y		:=
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+# Things that need to export symbols
+export-objs	:= orinoco.o hermes.o
+
+# ISA Bus cards
+
+# PCI bus cards
+
+# Other cards
+obj-$(CONFIG_APPLE_AIRPORT)	+= airport.o orinoco.o hermes.o
+
+# 16-bit Pcmcia wireless client drivers
+obj-$(CONFIG_PCMCIA_HERMES)	+= orinoco_cs.o orinoco.o hermes.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/README linux/drivers/net/wireless/README
--- v2.4.4/linux/drivers/net/wireless/README	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/README	Mon May  7 19:42:14 2001
@@ -0,0 +1,25 @@
+	README
+	------
+
+	This directory is mostly for Wireless LAN drivers, in their
+various incarnations (ISA, PCI, Pcmcia...).
+	This separate directory is needed because a lot of driver work
+on different bus (typically PCI + Pcmcia) and share 95% of the
+code. This allow the code and the config options to be in one single
+place instead of scattered all over the driver tree, which is never
+100% satisfactory.
+
+	Note : if you want more info on the topic of Wireless LANs,
+you are kindly invited to have a look at the Wireless Howto :
+		http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
+	Some Wireless LAN drivers, like orinoco_cs, require the use of
+Wireless Tools to be configured :
+		http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
+
+	Special notes for distribution maintainers :
+	1) wvlan_cs will be discontinued soon in favor of orinoco_cs
+	2) Please add Wireless Tools support in your scripts
+
+	Have fun...
+
+	Jean
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/airport.c linux/drivers/net/wireless/airport.c
--- v2.4.4/linux/drivers/net/wireless/airport.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/airport.c	Mon May  7 19:42:14 2001
@@ -0,0 +1,270 @@
+/* airport.c 0.05
+ *
+ * A driver for "Hermes" chipset based Apple Airport wireless
+ * card.
+ *
+ * Copyright notice & release notes in file orinoco.c
+ * 
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/list.h>
+
+#include <asm/prom.h>
+#include <asm/feature.h>
+
+#include "hermes.h"
+#include "orinoco.h"
+
+typedef struct dldwd_card {
+	struct device_node* node;
+	int irq_requested;
+	int ndev_registered;
+	/* Common structure (fully included), see orinoco.h */
+	struct dldwd_priv priv;
+} dldwd_card_t;
+
+static char *version = "airport.c 0.05 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
+
+/*
+ * Function prototypes
+ */
+
+static dldwd_priv_t* airport_attach(struct device_node *of_node);
+static void airport_detach(dldwd_priv_t* priv);
+static int airport_init(struct net_device *dev);
+static int airport_open(struct net_device *dev);
+static int airport_stop(struct net_device *dev);
+
+/*
+   A linked list of "instances" of the dummy device.  Each actual
+   PCMCIA card corresponds to one device instance, and is described
+   by one dev_link_t structure (defined in ds.h).
+
+   You may not want to use a linked list for this -- for example, the
+   memory card driver uses an array of dev_link_t pointers, where minor
+   device numbers are used to derive the corresponding array index.
+*/
+
+static dldwd_priv_t *airport_dev;
+
+static int airport_init(struct net_device *dev)
+{
+	dldwd_priv_t *priv = dev->priv;
+	dldwd_card_t* card = (dldwd_card_t *)priv->card;
+	int rc;
+	
+	TRACE_ENTER(priv->ndev.name);
+
+	MOD_INC_USE_COUNT;
+
+	feature_set_airport_power(card->node, 1);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout(HZ);
+
+	rc = dldwd_init(dev);
+	if (rc) {	
+		feature_set_airport_power(card->node, 0);
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ);
+	}
+	priv->hw_ready = 1;
+
+	MOD_DEC_USE_COUNT;
+
+	return rc;
+}
+
+static int
+airport_open(struct net_device *dev)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int rc;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	netif_device_attach(dev);
+	rc = dldwd_reset(priv);
+	if (rc)
+		airport_stop(dev);
+	else
+		netif_start_queue(dev);
+
+	TRACE_EXIT(priv->ndev.name);
+
+	return rc;
+}
+
+static int
+airport_stop(struct net_device *dev)
+{
+	dldwd_priv_t *priv = dev->priv;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	netif_stop_queue(dev);
+
+	dldwd_shutdown(priv);
+
+	TRACE_EXIT(priv->ndev.name);
+
+	return 0;
+}
+
+static dldwd_priv_t*
+airport_attach(struct device_node* of_node)
+{
+	dldwd_priv_t *priv;
+	struct net_device *ndev;
+	dldwd_card_t* card;
+	hermes_t *hw;
+
+	TRACE_ENTER("dldwd");
+
+	if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
+		printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
+		return NULL;
+	}
+
+	/* Allocate space for private device-specific data */
+	card = kmalloc(sizeof(*card), GFP_KERNEL);
+	if (!card) {
+		printk(KERN_ERR "airport: can't allocate device datas\n");
+		return NULL;
+	}
+	memset(card, 0, sizeof(*card));
+
+	priv = &(card->priv);
+	priv->card = card;
+	ndev = &priv->ndev;
+	hw = &priv->hw;
+	card->node = of_node;
+
+	/* Setup the common part */
+	if (dldwd_setup(priv) < 0) {
+		kfree(card);
+		return NULL;
+	}
+
+	/* Overrides */
+	ndev->init = airport_init;
+	ndev->open = airport_open;
+	ndev->stop = airport_stop;
+
+	/* Setup interrupts & base address */
+	ndev->irq = of_node->intrs[0].line;
+	ndev->base_addr = (unsigned long)ioremap(of_node->addrs[0].address, 0x1000) - _IO_BASE;
+
+	hermes_struct_init(hw, ndev->base_addr);
+		
+	if (request_irq(ndev->irq, dldwd_interrupt, 0, "Airport", (void *)priv)) {
+		printk(KERN_ERR "airport: Couldn't get IRQ %d\n", ndev->irq);
+		goto failed;
+	}
+	card->irq_requested = 1;
+	
+	/* register_netdev will give us an ethX name */
+	ndev->name[0] = '\0';
+	/* Tell the stack we exist */
+	if (register_netdev(ndev) != 0) {
+		printk(KERN_ERR "airport: register_netdev() failed\n");
+		goto failed;
+	}
+	printk(KERN_INFO "airport: card registered for interface %s\n", ndev->name);
+	card->ndev_registered = 1;
+
+	SET_MODULE_OWNER(ndev);
+
+	/* And give us the proc nodes for debugging */
+	if (dldwd_proc_dev_init(priv) != 0)
+		printk(KERN_ERR "airport: Failed to create /proc node for %s\n",
+		       ndev->name);
+
+	return priv;
+	
+failed:
+	airport_detach(priv);
+	return NULL;
+}				/* airport_attach */
+
+/*======================================================================
+  This deletes a driver "instance".  
+  ======================================================================*/
+
+static void
+airport_detach(dldwd_priv_t *priv)
+{
+	dldwd_card_t* card = (dldwd_card_t *)priv->card;
+
+	priv->hw_ready = 0;
+	
+	/* Unregister proc entry */
+	dldwd_proc_dev_cleanup(priv);
+
+	if (card->ndev_registered)
+		unregister_netdev(&priv->ndev);
+	card->ndev_registered = 0;
+	
+	if (card->irq_requested)
+		free_irq(priv->ndev.irq, priv);
+	card->irq_requested = 0;
+
+// FIXME
+//	if (ndev->base_addr)
+//		iounmap(ndev->base_addr + _IO_BASE);
+//	ndev->base_addr = 0;
+	
+	feature_set_airport_power(card->node, 0);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout(HZ);
+	
+	kfree(card);
+}				/* airport_detach */
+
+static int __init
+init_airport(void)
+{
+	struct device_node* airport_node;
+
+	printk(KERN_INFO "%s\n", version);
+
+	MOD_INC_USE_COUNT;
+
+	/* Lookup card in device tree */
+	airport_node = find_devices("radio");
+	if (airport_node && !strcmp(airport_node->parent->name, "mac-io"))
+		airport_dev = airport_attach(airport_node);
+
+	MOD_DEC_USE_COUNT;
+
+	return airport_dev ? 0 : -ENODEV;
+}
+
+static void __exit
+exit_airport(void)
+{
+	if (airport_dev)
+		airport_detach(airport_dev);
+	airport_dev = NULL;
+}
+
+MODULE_DESCRIPTION("Apple Airport driver");
+
+module_init(init_airport);
+module_exit(exit_airport);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/hermes.c linux/drivers/net/wireless/hermes.c
--- v2.4.4/linux/drivers/net/wireless/hermes.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/hermes.c	Mon May  7 19:42:14 2001
@@ -0,0 +1,502 @@
+/* hermes.c
+ *
+ * Driver core for the "Hermes" wireless MAC controller, as used in
+ * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
+ * work on the hfa3841 and hfa3842 MAC controller chips used in the
+ * Prism I & II chipsets.
+ *
+ * This is not a complete driver, just low-level access routines for
+ * the MAC controller itself.
+ *
+ * Based on the prism2 driver from Absolute Value Systems' linux-wlan
+ * project, the Linux wvlan_cs driver, Lucent's HCF-Light
+ * (wvlan_hcf.c) library, and the NetBSD wireless driver.
+ *
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * 
+ * This file distributed under the GPL, version 2.
+ */
+
+static const char *version = "hermes.c: 12 Dec 2000 David Gibson <hermes@gibson.dropbear.id.au>";
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+#include <linux/ptrace.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/errno.h>
+
+#include "hermes.h"
+
+#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
+#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
+#define CMD_COMPL_TIMEOUT (10000) /* in iterations of ~10us */
+#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
+#define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
+#define BAP_ERROR_RETRY (10) /* How many times to retry a BAP seek when there is an error */
+
+#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+
+/*
+ * Debugging helpers
+ */
+
+#undef HERMES_DEBUG
+#ifdef HERMES_DEBUG
+
+#include <stdarg.h>
+
+#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ 0x%x: " , hw->iobase); \
+			printk(#stuff);} while (0)
+
+#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(#stuff)
+
+#else /* ! HERMES_DEBUG */
+
+#define DEBUG(lvl, stuff...) do { } while (0)
+
+#endif /* ! HERMES_DEBUG */
+
+/*
+ * Prototypes
+ */
+
+static int hermes_issue_cmd(hermes_t *hw, uint16_t cmd, uint16_t param0);
+
+/*
+ * Internal inline functions
+ */
+
+/*
+ * Internal functions
+ */
+
+/* Issue a command to the chip. Waiting for it to complete is the caller's
+   problem.
+
+   Returns -EBUSY if the command register is busy, 0 on success.
+
+   Callable from any context.
+*/
+static int hermes_issue_cmd(hermes_t *hw, uint16_t cmd, uint16_t param0)
+{
+	uint16_t reg;
+/*  	unsigned long k = CMD_BUSY_TIMEOUT; */
+
+	/* First check that the command register is not busy */
+	reg = hermes_read_regn(hw, CMD);
+	if (reg & HERMES_CMD_BUSY) {
+		return -EBUSY;
+	}
+
+	hermes_write_regn(hw, PARAM2, 0);
+	hermes_write_regn(hw, PARAM1, 0);
+	hermes_write_regn(hw, PARAM0, param0);
+	hermes_write_regn(hw, CMD, cmd);
+	
+	return 0;
+}
+
+/*
+ * Function definitions
+ */
+
+void hermes_struct_init(hermes_t *hw, uint io)
+{
+	hw->iobase = io;
+	hw->inten = 0x0;
+}
+
+int hermes_reset(hermes_t *hw)
+{
+	uint16_t status, reg;
+	int err = 0;
+	int k;
+
+	/* We don't want to be interrupted while resetting the chipset */
+	hw->inten = 0x0;
+	hermes_write_regn(hw, INTEN, 0);
+	hermes_write_regn(hw, EVACK, 0xffff);
+
+	/* Because we hope we can reset the card even if it gets into
+	   a stupid state, we actually wait to see if the command
+	   register will unbusy itself */
+	k = CMD_BUSY_TIMEOUT;
+	reg = hermes_read_regn(hw, CMD);
+	while (k && (reg & HERMES_CMD_BUSY)) {
+		if (reg == 0xffff) /* Special case - the card has probably been removed,
+				      so don't wait for the timeout */
+			return -ENODEV;
+
+		k--;
+		udelay(1);
+		reg = hermes_read_regn(hw, CMD);
+	}
+	
+	/* No need to explicitly handle the timeout - hermes_issue_cmd() will
+	   probably return -EBUSY */
+
+	/* We don't use hermes_docmd_wait here, because the reset wipes
+	   the magic constant in SWSUPPORT0 away, and it gets confused */
+	err = hermes_issue_cmd(hw, HERMES_CMD_INIT, 0);
+	if (err)
+		return err;
+
+	reg = hermes_read_regn(hw, EVSTAT);
+	k = CMD_INIT_TIMEOUT;
+	while ( (! (reg & HERMES_EV_CMD)) && k) {
+		k--;
+		udelay(10);
+		reg = hermes_read_regn(hw, EVSTAT);
+	}
+
+	DEBUG(0, "Reset completed in %d iterations\n", CMD_INIT_TIMEOUT - k);
+
+	hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
+
+	if (! hermes_present(hw)) {
+		DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
+		       hw->iobase);
+		err = -ENODEV;
+		goto out;
+	}
+		
+	if (! (reg & HERMES_EV_CMD)) {
+		printk(KERN_ERR "hermes @ 0x%x: Timeout waiting for card to reset (reg=0x%04x)!\n",
+		       hw->iobase, reg);
+		err = -ETIMEDOUT;
+		goto out;
+	}
+
+	status = hermes_read_regn(hw, STATUS);
+
+	hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
+
+	err = status & HERMES_STATUS_RESULT;
+
+ out:
+	return err;
+}
+
+/* Issue a command to the chip, and (busy!) wait for it to
+ * complete.
+ *
+ * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware
+ *
+ * Callable from any context, but locking is your problem. */
+int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp)
+{
+	int err;
+	int k;
+	uint16_t reg;
+
+	err = hermes_issue_cmd(hw, cmd, parm0);
+	if (err) {
+		if (! hermes_present(hw)) {
+			printk(KERN_WARNING "hermes @ 0x%x: Card removed while issuing command.\n",
+			       hw->iobase);
+			err = -ENODEV;
+		} else 
+			printk(KERN_ERR "hermes @ 0x%x: CMD register busy in hermes_issue_command().\n",
+			       hw->iobase);
+		goto out;
+	}
+
+	reg = hermes_read_regn(hw, EVSTAT);
+	k = CMD_COMPL_TIMEOUT;
+	while ( (! (reg & HERMES_EV_CMD)) && k) {
+		k--;
+		udelay(10);
+		reg = hermes_read_regn(hw, EVSTAT);
+	}
+
+	if (! hermes_present(hw)) {
+		printk(KERN_WARNING "hermes @ 0x%x: Card removed while waiting for command completion.\n",
+		       hw->iobase);
+		err = -ENODEV;
+		goto out;
+	}
+		
+	if (! (reg & HERMES_EV_CMD)) {
+		printk(KERN_ERR "hermes @ 0x%x: Timeout waiting for command completion.\n",
+		       hw->iobase);
+		err = -ETIMEDOUT;
+		goto out;
+	}
+
+	resp->status = hermes_read_regn(hw, STATUS);
+	resp->resp0 = hermes_read_regn(hw, RESP0);
+	resp->resp1 = hermes_read_regn(hw, RESP1);
+	resp->resp2 = hermes_read_regn(hw, RESP2);
+
+	hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
+
+	err = resp->status & HERMES_STATUS_RESULT;
+
+ out:
+	return err;
+}
+
+int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid)
+{
+	int err = 0;
+	hermes_response_t resp;
+	int k;
+	uint16_t reg;
+	
+	if ( (size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX) )
+		return -EINVAL;
+
+	err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, &resp);
+	if (err) {
+		printk(KERN_WARNING "hermes @ 0x%x: Frame allocation command failed (0x%X).\n",
+		       hw->iobase, err);
+		return err;
+	}
+
+	reg = hermes_read_regn(hw, EVSTAT);
+	k = ALLOC_COMPL_TIMEOUT;
+	while ( (! (reg & HERMES_EV_ALLOC)) && k) {
+		k--;
+		udelay(10);
+		reg = hermes_read_regn(hw, EVSTAT);
+	}
+	
+	if (! hermes_present(hw)) {
+		printk(KERN_WARNING "hermes @ 0x%x: Card removed waiting for frame allocation.\n",
+		       hw->iobase);
+		return -ENODEV;
+	}
+		
+	if (! (reg & HERMES_EV_ALLOC)) {
+		printk(KERN_ERR "hermes @ 0x%x: Timeout waiting for frame allocation\n",
+		       hw->iobase);
+		return -ETIMEDOUT;
+	}
+
+	*fid = hermes_read_regn(hw, ALLOCFID);
+	hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
+	
+	return 0;
+}
+
+/* Set up a BAP to read a particular chunk of data from card's internal buffer.
+ *
+ * Returns: < 0 on internal failure (errno), 0 on success, >0 on error
+ * from firmware
+ *
+ * Callable from any context */
+static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
+{
+	int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
+	int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
+	int k;
+	int l = BAP_ERROR_RETRY;
+	uint16_t reg;
+
+	/* Paranoia.. */
+	if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) )
+		return -EINVAL;
+
+	k = BAP_BUSY_TIMEOUT;
+	reg = hermes_read_reg(hw, oreg);
+
+	if (reg & HERMES_OFFSET_BUSY)
+		return -EBUSY;
+
+	/* Now we actually set up the transfer */
+ retry:
+	hermes_write_reg(hw, sreg, id);
+	hermes_write_reg(hw, oreg, offset);
+
+	/* Wait for the BAP to be ready */
+	k = BAP_BUSY_TIMEOUT;
+	reg = hermes_read_reg(hw, oreg);
+	while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
+		k--;
+		udelay(1);
+		reg = hermes_read_reg(hw, oreg);
+	}
+
+	if (reg & HERMES_OFFSET_BUSY)
+		return -ETIMEDOUT;
+
+	/* For some reason, seeking the BAP seems to randomly fail somewhere
+	   (firmware bug?). We retry a few times before giving up. */
+	if (reg & HERMES_OFFSET_ERR) {
+		if (l--) {
+			udelay(1);
+			goto retry;
+		} else
+			return -EIO;
+	}
+
+	return 0;
+}
+
+/* Read a block of data from the chip's buffer, via the
+ * BAP. Synchronization/serialization is the caller's problem.  len
+ * must be even.
+ *
+ * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
+ */
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
+		     uint16_t id, uint16_t offset)
+{
+	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
+	int err = 0;
+
+	if (len % 2)
+		return -EINVAL;
+
+	err = hermes_bap_seek(hw, bap, id, offset);
+	if (err)
+		goto out;
+
+	/* Actually do the transfer */
+	hermes_read_data(hw, dreg, buf, len/2);
+
+ out:
+	return err;
+}
+
+/* Write a block of data to the chip's buffer, via the
+ * BAP. Synchronization/serialization is the caller's problem. len
+ * must be even.
+ *
+ * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
+ */
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
+		      uint16_t id, uint16_t offset)
+{
+	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
+	int err = 0;
+
+	if (len % 2)
+		return -EINVAL;
+
+	err = hermes_bap_seek(hw, bap, id, offset);
+	if (err)
+		goto out;
+	
+	/* Actually do the transfer */
+	hermes_write_data(hw, dreg, buf, len/2);
+
+ out:	
+	return err;
+}
+
+/* Read a Length-Type-Value record from the card.
+ *
+ * If length is NULL, we ignore the length read from the card, and
+ * read the entire buffer regardless. This is useful because some of
+ * the configuration records appear to have incorrect lengths in
+ * practice.
+ *
+ * Callable from user or bh context.  */
+int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
+		    uint16_t *length, void *buf)
+{
+	int err = 0;
+	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
+	uint16_t rlength, rtype;
+	hermes_response_t resp;
+	int count;
+
+	if (buflen % 2)
+		return -EINVAL;
+
+	err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, &resp);
+	if (err)
+		goto out;
+
+	err = hermes_bap_seek(hw, bap, rid, 0);
+	if (err)
+		goto out;
+
+	rlength = hermes_read_reg(hw, dreg);
+	rtype = hermes_read_reg(hw, dreg);
+
+	if (length)
+		*length = rlength;
+
+	if (rtype != rid)
+		printk(KERN_WARNING "hermes_read_ltv(): rid  (0x%04x) does "
+		       "not match type (0x%04x)\n", rid, rtype);
+	if (HERMES_RECLEN_TO_BYTES(rlength) > buflen)
+		printk(KERN_WARNING "hermes @ 0x%x: Truncating LTV record from %d to %d bytes. "
+		       "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
+		       HERMES_RECLEN_TO_BYTES(rlength), buflen, rid, rlength);
+	
+	/* For now we always read the whole buffer, the
+	   lengths in the records seem to be wrong, frequently */
+	count = buflen / 2;
+
+#if 0
+	if (length)
+		count = (MIN(buflen, rlength) + 1) / 2;
+	else {
+		count = buflen / 2;
+		if (rlength != buflen)
+			printk(KERN_WARNING "hermes_read_ltv(): Incorrect \
+record length %d instead of %d on RID 0x%04x\n", rlength, buflen, rid);
+	}
+#endif
+	hermes_read_data(hw, dreg, buf, count);
+
+ out:
+	return err;
+}
+
+int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid, 
+		     uint16_t length, const void *value)
+{
+	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
+	int err = 0;
+	hermes_response_t resp;
+	int count;
+	
+	DEBUG(3, "write_ltv(): bap=%d rid=0x%04x length=%d (value=0x%04x)\n",
+	      bap, rid, length, * ((uint16_t *)value));
+
+	err = hermes_bap_seek(hw, bap, rid, 0);
+	if (err)
+		goto out;
+
+	hermes_write_reg(hw, dreg, length);
+	hermes_write_reg(hw, dreg, rid);
+
+	count = length - 1;
+
+	hermes_write_data(hw, dreg, value, count);
+
+	err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, 
+				rid, &resp);
+
+ out:
+	return err;
+}
+
+EXPORT_SYMBOL(hermes_struct_init);
+EXPORT_SYMBOL(hermes_reset);
+EXPORT_SYMBOL(hermes_docmd_wait);
+EXPORT_SYMBOL(hermes_allocate);
+
+EXPORT_SYMBOL(hermes_bap_pread);
+EXPORT_SYMBOL(hermes_bap_pwrite);
+EXPORT_SYMBOL(hermes_read_ltv);
+EXPORT_SYMBOL(hermes_write_ltv);
+
+static int __init init_hermes(void)
+{
+	printk(KERN_INFO "%s\n", version);
+
+	return 0;
+}
+
+module_init(init_hermes);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/hermes.h linux/drivers/net/wireless/hermes.h
--- v2.4.4/linux/drivers/net/wireless/hermes.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/hermes.h	Mon May  7 19:42:14 2001
@@ -0,0 +1,402 @@
+/* hermes.h
+ *
+ * Driver core for the "Hermes" wireless MAC controller, as used in
+ * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
+ * work on the hfa3841 and hfa3842 MAC controller chips used in the
+ * Prism I & II chipsets.
+ *
+ * This is not a complete driver, just low-level access routines for
+ * the MAC controller itself.
+ *
+ * Based on the prism2 driver from Absolute Value Systems' linux-wlan
+ * project, the Linux wvlan_cs driver, Lucent's HCF-Light
+ * (wvlan_hcf.c) library, and the NetBSD wireless driver.
+ *
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ *
+ * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+ *
+ * This file distributed under the GPL, version 2.
+ */
+
+#ifndef _HERMES_H
+#define _HERMES_H
+
+/* Notes on locking:
+ *
+ * As a module of low level hardware access routines, there is no
+ * locking. Users of this module should ensure that they serialize
+ * access to the hermes_t structure, and to the hardware
+*/
+
+#include <linux/delay.h>
+#include <linux/if_ether.h>
+
+/*
+ * Limits and constants
+ */
+#define		HERMES_ALLOC_LEN_MIN		(4)
+#define		HERMES_ALLOC_LEN_MAX		(2400)
+#define		HERMES_LTV_LEN_MAX		(34)
+#define		HERMES_BAP_DATALEN_MAX		(4096)
+#define		HERMES_BAP_OFFSET_MAX		(4096)
+#define		HERMES_PORTID_MAX		(7)
+#define		HERMES_NUMPORTS_MAX		(HERMES_PORTID_MAX+1)
+#define		HERMES_PDR_LEN_MAX		(260)	/* in bytes, from EK */
+#define		HERMES_PDA_RECS_MAX		(200)	/* a guess */
+#define		HERMES_PDA_LEN_MAX		(1024)	/* in bytes, from EK */
+#define		HERMES_SCANRESULT_MAX		(35)
+#define		HERMES_CHINFORESULT_MAX		(8)
+#define		HERMES_FRAME_LEN_MAX		(2304)
+#define		HERMES_MAX_MULTICAST		(16)
+#define		HERMES_MAGIC			(0x7d1f)
+
+/*
+ * Hermes register offsets
+ */
+#define		HERMES_CMD			(0x00)
+#define		HERMES_PARAM0			(0x02)
+#define		HERMES_PARAM1			(0x04)
+#define		HERMES_PARAM2			(0x06)
+#define		HERMES_STATUS			(0x08)
+#define		HERMES_RESP0			(0x0A)
+#define		HERMES_RESP1			(0x0C)
+#define		HERMES_RESP2			(0x0E)
+#define		HERMES_INFOFID			(0x10)
+#define		HERMES_RXFID			(0x20)
+#define		HERMES_ALLOCFID			(0x22)
+#define		HERMES_TXCOMPLFID		(0x24)
+#define		HERMES_SELECT0			(0x18)
+#define		HERMES_OFFSET0			(0x1C)
+#define		HERMES_DATA0			(0x36)
+#define		HERMES_SELECT1			(0x1A)
+#define		HERMES_OFFSET1			(0x1E)
+#define		HERMES_DATA1			(0x38)
+#define		HERMES_EVSTAT			(0x30)
+#define		HERMES_INTEN			(0x32)
+#define		HERMES_EVACK			(0x34)
+#define		HERMES_CONTROL			(0x14)
+#define		HERMES_SWSUPPORT0		(0x28)
+#define		HERMES_SWSUPPORT1		(0x2A)
+#define		HERMES_SWSUPPORT2		(0x2C)
+#define		HERMES_AUXPAGE			(0x3A)
+#define		HERMES_AUXOFFSET		(0x3C)
+#define		HERMES_AUXDATA			(0x3E)
+
+/*
+ * CMD register bitmasks
+ */
+#define		HERMES_CMD_BUSY			(0x8000)
+#define		HERMES_CMD_AINFO		(0x7f00)
+#define		HERMES_CMD_MACPORT		(0x0700)
+#define		HERMES_CMD_RECL			(0x0100)
+#define		HERMES_CMD_WRITE		(0x0100)
+#define		HERMES_CMD_PROGMODE		(0x0300)
+#define		HERMES_CMD_CMDCODE		(0x003f)
+
+/*
+ * STATUS register bitmasks
+ */
+#define		HERMES_STATUS_RESULT		(0x7f00)
+#define		HERMES_STATUS_CMDCODE		(0x003f)
+
+/*
+ * OFFSET refister bitmasks
+ */
+#define		HERMES_OFFSET_BUSY		(0x8000)
+#define		HERMES_OFFSET_ERR		(0x4000)
+#define		HERMES_OFFSET_DATAOFF		(0x0ffe)
+
+/*
+ * Event register bitmasks (INTEN, EVSTAT, EVACK)
+ */
+#define		HERMES_EV_TICK			(0x8000)
+#define		HERMES_EV_WTERR			(0x4000)
+#define		HERMES_EV_INFDROP		(0x2000)
+#define		HERMES_EV_INFO			(0x0080)
+#define		HERMES_EV_DTIM			(0x0020)
+#define		HERMES_EV_CMD			(0x0010)
+#define		HERMES_EV_ALLOC			(0x0008)
+#define		HERMES_EV_TXEXC			(0x0004)
+#define		HERMES_EV_TX			(0x0002)
+#define		HERMES_EV_RX			(0x0001)
+
+/*
+ * Command codes
+ */
+/*--- Controller Commands --------------------------*/
+#define		HERMES_CMD_INIT			(0x0000)
+#define		HERMES_CMD_ENABLE		(0x0001)
+#define		HERMES_CMD_DISABLE		(0x0002)
+#define		HERMES_CMD_DIAG			(0x0003)
+
+/*--- Buffer Mgmt Commands --------------------------*/
+#define		HERMES_CMD_ALLOC		(0x000A)
+#define		HERMES_CMD_TX			(0x000B)
+#define		HERMES_CMD_CLRPRST		(0x0012)
+
+/*--- Regulate Commands --------------------------*/
+#define		HERMES_CMD_NOTIFY		(0x0010)
+#define		HERMES_CMD_INQ			(0x0011)
+
+/*--- Configure Commands --------------------------*/
+#define		HERMES_CMD_ACCESS		(0x0021)
+#define		HERMES_CMD_DOWNLD		(0x0022)
+
+/*--- Debugging Commands -----------------------------*/
+#define 	HERMES_CMD_MONITOR		(0x0038)
+#define		HERMES_MONITOR_ENABLE		(0x000b)
+#define		HERMES_MONITOR_DISABLE		(0x000f)
+
+/*
+ * Configuration RIDs
+ */
+
+#define		HERMES_RID_CNF_PORTTYPE		(0xfc00)
+#define		HERMES_RID_CNF_MACADDR		(0xfc01)
+#define		HERMES_RID_CNF_DESIRED_SSID	(0xfc02)
+#define		HERMES_RID_CNF_CHANNEL		(0xfc03)
+#define		HERMES_RID_CNF_OWN_SSID		(0xfc04)
+#define		HERMES_RID_CNF_SYSTEM_SCALE	(0xfc06)
+#define		HERMES_RID_CNF_MAX_DATA_LEN	(0xfc07)
+#define		HERMES_RID_CNF_PM_ENABLE	(0xfc09)
+#define		HERMES_RID_CNF_PM_MCAST_RX	(0xfc0b)
+#define		HERMES_RID_CNF_PM_PERIOD	(0xfc0c)
+#define		HERMES_RID_CNF_PM_HOLDOVER	(0xfc0d)
+#define		HERMES_RID_CNF_NICKNAME		(0xfc0e)
+#define		HERMES_RID_CNF_WEP_ON		(0xfc20)
+#define		HERMES_RID_CNF_MWO_ROBUST	(0xfc25)
+#define		HERMES_RID_CNF_PRISM2_WEP_ON	(0xfc28)
+#define		HERMES_RID_CNF_MULTICAST_LIST	(0xfc80)
+#define		HERMES_RID_CNF_CREATEIBSS	(0xfc81)
+#define		HERMES_RID_CNF_FRAG_THRESH	(0xfc82)
+#define		HERMES_RID_CNF_RTS_THRESH	(0xfc83)
+#define		HERMES_RID_CNF_TX_RATE_CTRL	(0xfc84)
+#define		HERMES_RID_CNF_PROMISCUOUS	(0xfc85)
+#define		HERMES_RID_CNF_KEYS		(0xfcb0)
+#define		HERMES_RID_CNF_TX_KEY		(0xfcb1)
+#define		HERMES_RID_CNF_TICKTIME		(0xfce0)
+
+#define		HERMES_RID_CNF_PRISM2_TX_KEY	(0xfc23)
+#define		HERMES_RID_CNF_PRISM2_KEY0	(0xfc24)
+#define		HERMES_RID_CNF_PRISM2_KEY1	(0xfc25)
+#define		HERMES_RID_CNF_PRISM2_KEY2	(0xfc26)
+#define		HERMES_RID_CNF_PRISM2_KEY3	(0xfc27)
+#define		HERMES_RID_CNF_SYMBOL_MANDATORY_BSSID	(0xfc21)
+#define		HERMES_RID_CNF_SYMBOL_AUTH_TYPE		(0xfc2A)
+#define		HERMES_RID_CNF_SYMBOL_BASIC_RATES	(0xfc8A)
+#define		HERMES_RID_CNF_SYMBOL_PREAMBLE		(0xfc8C)
+
+/*
+ * Information RIDs
+ */
+#define		HERMES_RID_CHANNEL_LIST		(0xfd10)
+#define		HERMES_RID_STAIDENTITY		(0xfd20)
+#define		HERMES_RID_CURRENT_SSID		(0xfd41)
+#define		HERMES_RID_CURRENT_BSSID	(0xfd42)
+#define		HERMES_RID_COMMSQUALITY		(0xfd43)
+#define 	HERMES_RID_CURRENT_TX_RATE	(0xfd44)
+#define 	HERMES_RID_SHORT_RETRY_LIMIT	(0xfd48)
+#define 	HERMES_RID_LONG_RETRY_LIMIT	(0xfd49)
+#define 	HERMES_RID_MAX_TX_LIFETIME	(0xfd4A)
+#define		HERMES_RID_WEP_AVAIL		(0xfd4f)
+#define		HERMES_RID_CURRENT_CHANNEL	(0xfdc1)
+#define		HERMES_RID_DATARATES		(0xfdc6)
+#define		HERMES_RID_SYMBOL_PRIMARY_VER	(0xfd03)
+#define		HERMES_RID_SYMBOL_SECONDARY_VER	(0xfd21)
+#define		HERMES_RID_SYMBOL_KEY_LENGTH	(0xfc2B)
+
+/*
+ * Frame structures and constants
+ */
+
+typedef struct hermes_frame_desc {
+	/* Hermes - i.e. little-endian byte-order */
+	uint16_t status; /* 0x0 */
+	uint16_t res1, res2; /* 0x2, 0x4 */
+	uint16_t q_info; /* 0x6 */
+	uint16_t res3, res4; /* 0x8, 0xA */
+	uint16_t tx_ctl; /* 0xC */
+} __attribute__ ((packed)) hermes_frame_desc_t;
+
+#define		HERMES_RXSTAT_ERR		(0x0003)
+#define		HERMES_RXSTAT_MACPORT		(0x0700)
+#define		HERMES_RXSTAT_MSGTYPE		(0xE000)
+
+#define		HERMES_RXSTAT_BADCRC		(0x0001)
+#define		HERMES_RXSTAT_UNDECRYPTABLE	(0x0002)
+
+/* RFC-1042 encoded frame */
+#define		HERMES_RXSTAT_1042		(0x2000)
+/* Bridge-tunnel encoded frame */
+#define		HERMES_RXSTAT_TUNNEL		(0x4000)
+/* Wavelan-II Management Protocol frame */
+#define		HERMES_RXSTAT_WMP		(0x6000)
+
+#ifdef __KERNEL__
+
+/* Basic control structure */
+typedef struct hermes {
+	uint iobase;
+
+	uint16_t inten; /* Which interrupts should be enabled? */
+} hermes_t;
+
+typedef struct hermes_response {
+	uint16_t status, resp0, resp1, resp2;
+} hermes_response_t;
+
+/* Firmware information structure */
+typedef struct hermes_identity {
+	uint16_t id, vendor, major, minor;
+} __attribute__ ((packed)) hermes_identity_t;
+
+/* "ID" structure - used for ESSID and station nickname */
+typedef struct hermes_id {
+	uint16_t len;
+	uint16_t val[16];
+} __attribute__ ((packed)) hermes_id_t;
+
+typedef struct hermes_commsqual {
+	uint16_t qual, signal, noise;
+} __attribute__ ((packed)) hermes_commsqual_t;
+
+typedef struct hermes_multicast {
+	uint8_t addr[HERMES_MAX_MULTICAST][ETH_ALEN];
+} __attribute__ ((packed)) hermes_multicast_t;
+
+/* Register access convenience macros */
+#define hermes_read_reg(hw, off) (inw((hw)->iobase + (off)))
+#define hermes_write_reg(hw, off, val) (outw_p((val), (hw)->iobase + (off)))
+
+#define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
+#define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
+
+/* Note that for the next two, the count is in 16-bit words, not bytes */
+#define hermes_read_data(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
+#define hermes_write_data(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
+
+/* Function prototypes */
+void hermes_struct_init(hermes_t *hw, uint io);
+int hermes_reset(hermes_t *hw);
+int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp);
+int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid);
+
+
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
+		       uint16_t id, uint16_t offset);
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
+			uint16_t id, uint16_t offset);
+int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
+		    uint16_t *length, void *buf);
+int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid,
+		      uint16_t length, const void *value);
+
+/* Inline functions */
+
+static inline int hermes_present(hermes_t *hw)
+{
+	return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
+}
+
+static inline void hermes_enable_interrupt(hermes_t *hw, uint16_t events)
+{
+	hw->inten |= events;
+	hermes_write_regn(hw, INTEN, hw->inten);
+}
+
+static inline void hermes_set_irqmask(hermes_t *hw, uint16_t events)
+{
+	hw->inten = events;
+	hermes_write_regn(hw, INTEN, events);
+}
+
+static inline int hermes_enable_port(hermes_t *hw, int port)
+{
+	hermes_response_t resp;
+
+	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
+				 0, &resp);
+}
+
+static inline int hermes_disable_port(hermes_t *hw, int port)
+{
+	hermes_response_t resp;
+
+	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), 
+				 0, &resp);
+}
+
+#define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
+#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
+
+#define HERMES_READ_RECORD(hw, bap, rid, buf) \
+	(hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
+#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
+	(hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf)))
+
+static inline int hermes_read_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t *word)
+{
+	uint16_t rec;
+	int err;
+
+	err = HERMES_READ_RECORD(hw, bap, rid, &rec);
+	*word = le16_to_cpu(rec);
+	return err;
+}
+
+static inline int hermes_write_wordrec(hermes_t *hw, int bap, uint16_t rid, uint16_t word)
+{
+	uint16_t rec = cpu_to_le16(word);
+	return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
+}
+
+static inline int hermes_read_staidentity(hermes_t *hw, int bap, hermes_identity_t *buf)
+{
+	int err;
+
+	err = HERMES_READ_RECORD(hw, bap, HERMES_RID_STAIDENTITY, buf);
+	if (err)
+		return err;
+
+	le16_to_cpus(&buf->id);
+	le16_to_cpus(&buf->vendor);
+	le16_to_cpus(&buf->major);
+	le16_to_cpus(&buf->minor);
+	
+	return 0;
+}
+
+static inline int hermes_read_commsqual(hermes_t *hw, int bap, hermes_commsqual_t *buf)
+{
+	int err;
+
+	err = HERMES_READ_RECORD(hw, bap, HERMES_RID_COMMSQUALITY, buf);
+	if (err)
+		return err;
+
+	le16_to_cpus(&buf->qual);
+	le16_to_cpus(&buf->signal);
+	le16_to_cpus(&buf->noise);
+	
+	return 0;
+}
+
+#else /* ! __KERNEL__ */
+
+/* These are provided for the benefit of userspace drivers and testing programs
+   which use ioperm() or iopl() */
+
+#define hermes_read_reg(base, off) (inw((base) + (off)))
+#define hermes_write_reg(base, off, val) (outw((val), (base) + (off)))
+
+#define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name))
+#define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val)))
+
+/* Note that for the next two, the count is in 16-bit words, not bytes */
+#define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count)))
+#define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count)))
+
+#endif /* ! __KERNEL__ */
+
+#endif  /* _HERMES_H */
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/orinoco.c linux/drivers/net/wireless/orinoco.c
--- v2.4.4/linux/drivers/net/wireless/orinoco.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/orinoco.c	Mon May  7 19:42:14 2001
@@ -0,0 +1,3551 @@
+/* orinoco.c 0.05	- (formerly known as dldwd_cs.c and orinoco_cs.c)
+ *
+ * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
+ * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
+ * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
+ * It should also be usable on various Prism II based cards such as the
+ * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
+ * cards such as the 3Com AirConnect and Ericsson WLAN.
+ *
+ * Copyright (C) 2000 David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ *	With some help from :
+ * Copyright (C) 2001 Jean Tourrilhes, HP Labs <jt@hpl.hp.com>
+ * Copyright (C) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
+ *
+ * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy@fasta.fh-dortmund.de>
+ *      http://www.fasta.fh-dortmund.de/users/andy/wvlan/
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dahinds@users.sourceforge.net>.  Portions created by David
+ * A. Hinds are Copyright (C) 1999 David A. Hinds.  All Rights
+ * Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU Public License version 2 (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of the above.
+ * If you wish to allow the use of your version of this file only
+ * under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+/* Notes on locking:
+ *
+ * The basic principle of operation is that everything except the
+ * interrupt handler is serialized through a single spinlock in the
+ * dldwd_priv_t structure, using dldwd_lock() and
+ * dldwd_unlock() (which in turn use spin_lock_bh() and spin_unlock_bh()).
+ *
+ * The kernel's IRQ handling stuff ensures that the interrupt handler
+ * does not re-enter itself. The interrupt handler is written such
+ * that everything it does is safe without a lock: chiefly this means
+ * that the Rx path uses one of the Hermes chipset's BAPs while
+ * everything else uses the other.
+ *
+ * For the moment access to the device statistics from the interrupt
+ * handler is unsafe - we just put up with any resulting errors in the
+ * statisics. FIXME: This should probably be changed to store the
+ * stats in atomic types.
+ *
+ * EXCEPT that we don't want the irq handler running when we actually
+ * reset or shut down the card, because strange things might happen
+ * (probably the worst would be one packet of garbage, but you can't
+ * be too careful). For this we use __dldwd_stop_irqs() which will set
+ * a flag to disable the interrupt handler, and wait for any
+ * outstanding instances of the handler to complete. THIS WILL LOSE
+ * INTERRUPTS! so it shouldn't be used except for resets, when we
+ * don't care about that.*/
+
+/*
+ * Tentative changelog...
+ *
+ * v0.01 -> v0.02 - 21/3/2001 - Jean II
+ *	o Allow to use regular ethX device name instead of dldwdX
+ *	o Warning on IBSS with ESSID=any for firmware 6.06
+ *	o Put proper range.throughput values (optimistic)
+ *	o IWSPY support (IOCTL and stat gather in Rx path)
+ *	o Allow setting frequency in Ad-Hoc mode
+ *	o Disable WEP setting if !has_wep to work on old firmware
+ *	o Fix txpower range
+ *	o Start adding support for Samsung/Compaq firmware
+ *
+ * v0.02 -> v0.03 - 23/3/2001 - Jean II
+ *	o Start adding Symbol support - need to check all that
+ *	o Fix Prism2/Symbol WEP to accept 128 bits keys
+ *	o Add Symbol WEP (add authentication type)
+ *	o Add Prism2/Symbol rate
+ *	o Add PM timeout (holdover duration)
+ *	o Enable "iwconfig eth0 key off" and friends (toggle flags)
+ *	o Enable "iwconfig eth0 power unicast/all" (toggle flags)
+ *	o Try with an intel card. It report firmware 1.01, behave like
+ *	  an antiquated firmware, however on windows it says 2.00. Yuck !
+ *	o Workaround firmware bug in allocate buffer (Intel 1.01)
+ *	o Finish external renaming to orinoco...
+ *	o Testing with various Wavelan firmwares
+ *
+ * v0.03 -> v0.04 - 30/3/2001 - Jean II
+ *	o Update to Wireless 11 -> add retry limit/lifetime support
+ *	o Tested with a D-Link DWL 650 card, fill in firmware support
+ *	o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot)
+ *	o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-(
+ *	  It work on D-Link *only* after a tcpdump. Weird...
+ *	  And still doesn't work on Intel card. Grrrr...
+ *	o Update the mode after a setport3
+ *	o Add preamble setting for Symbol cards (not yet enabled)
+ *	o Don't complain as much about Symbol cards...
+ *
+ * v0.04 -> v0.04b - 22/4/2001 - David Gibson
+ *      o Removed the 'eth' parameter - always use ethXX as the
+ *        interface name instead of dldwdXX.  The other was racy
+ *        anyway.
+ *	o Clean up RID definitions in hermes.h, other cleanups
+ *
+ * v0.04b -> v0.04c - 24/4/2001 - Jean II
+ *	o Tim Hurley <timster@seiki.bliztech.com> reported a D-Link card
+ *	  with vendor 02 and firmware 0.08. Added in the capabilities...
+ *	o Tested Lucent firmware 7.28, everything works...
+ *
+ * v0.04c -> v0.05 - 3/5/2001 - Benjamin Herrenschmidt
+ *	o Spin-off Pcmcia code. This file is renamed orinoco.c,
+ *	  and orinoco_cs.c now contains only the Pcmcia specific stuff
+ *	o Add Airport driver support on top of orinoco.c (see airport.c)
+ *
+ * v0.05 -> v0.05a - 4/5/2001 - Jean II
+ *	o Revert to old Pcmcia code to fix breakage of Ben's changes...
+ *
+ * v0.05a -> v0.05b - 4/5/2001 - Jean II
+ *	o add module parameter 'ignore_cis_vcc' for D-Link @ 5V
+ *	o D-Link firmware doesn't support multicast. We just print a few
+ *	  error messages, but otherwise everything works...
+ *	o For David : set/getport3 works fine, just upgrade iwpriv...
+ *
+ * v0.05b -> v0.05c - 5/5/2001 - Benjamin Herrenschmidt
+ *	o Adapt airport.c to latest changes in orinoco.c
+ *	o Remove deferred power enabling code
+ *
+ * v0.05c -> v0.05d - 5/5/2001 - Jean II
+ *	o Workaround to SNAP decapsulate frame from LinkSys AP
+ *	  original patch from : Dong Liu <dliu@research.bell-labs.com>
+ *	  (note : the memcmp bug was mine - fixed)
+ *	o Remove set_retry stuff, no firmware support it (bloat--).
+ *
+ * TODO - Jean II
+ *	o inline functions (lot's of candidate, need to reorder code)
+ *	o Test PrismII/Symbol cards & firmware versions
+ *	o Mini-PCI support
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/list.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/bus_ops.h>
+
+#include "hermes.h"
+#include "orinoco.h"
+
+static char *version = "orinoco.c 0.05d (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+
+/* Level of debugging. Used in the macros in orinoco.h */
+#ifdef ORINOCO_DEBUG
+int dldwd_debug = ORINOCO_DEBUG;
+MODULE_PARM(dldwd_debug, "i");
+#endif
+
+const long channel_frequency[] = {
+	2412, 2417, 2422, 2427, 2432, 2437, 2442,
+	2447, 2452, 2457, 2462, 2467, 2472, 2484
+};
+
+#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
+
+/* This tables gives the actual meanings of the bitrate IDs returned by the firmware.
+   It gives the rate in halfMb/s, negative indicates auto mode */
+const int rate_list[] = { 0, 2, 4, -22, 11, 22, -4, -11, 0, 0, 0, 0};
+
+#define NUM_RATES (sizeof(rate_list) / sizeof(rate_list[0]))
+
+struct p80211_hdr {
+	uint16_t frame_ctl;
+	uint16_t duration_id;
+	uint8_t addr1[ETH_ALEN];
+	uint8_t addr2[ETH_ALEN];
+	uint8_t addr3[ETH_ALEN];
+	uint16_t seq_ctl;
+	uint8_t addr4[ETH_ALEN];
+	uint16_t data_len;
+} __attribute__ ((packed));
+
+/* Frame control field constants */
+#define DLDWD_FCTL_VERS			0x0002
+#define DLDWD_FCTL_FTYPE		0x000c
+#define DLDWD_FCTL_STYPE		0x00f0
+#define DLDWD_FCTL_TODS			0x0100
+#define DLDWD_FCTL_FROMDS		0x0200
+#define DLDWD_FCTL_MOREFRAGS		0x0400
+#define DLDWD_FCTL_RETRY		0x0800
+#define DLDWD_FCTL_PM			0x1000
+#define DLDWD_FCTL_MOREDATA		0x2000
+#define DLDWD_FCTL_WEP			0x4000
+#define DLDWD_FCTL_ORDER		0x8000
+
+#define DLDWD_FTYPE_MGMT		0x0000
+#define DLDWD_FTYPE_CTL			0x0004
+#define DLDWD_FTYPE_DATA		0x0008
+
+struct p8022_hdr {
+	uint8_t dsap;
+	uint8_t ssap;
+	uint8_t ctrl;
+	uint8_t oui[3];
+} __attribute__ ((packed));
+
+struct dldwd_frame_hdr {
+	hermes_frame_desc_t desc;
+	struct p80211_hdr p80211;
+	struct ethhdr p8023;
+	struct p8022_hdr p8022;
+	uint16_t ethertype;
+} __attribute__ ((packed));
+
+#define P8023_OFFSET		(sizeof(hermes_frame_desc_t) + \
+				sizeof(struct p80211_hdr))
+#define ENCAPS_OVERHEAD		(sizeof(struct p8022_hdr) + 2)
+
+/* 802.2 LLL header SNAP used for SNAP encapsulation over 802.11 */
+struct p8022_hdr encaps_hdr = {
+	0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}
+};
+
+/*
+ * Function prototypes
+ */
+
+static void dldwd_stat_gather(struct net_device *dev,
+			      struct sk_buff *skb,
+			      struct dldwd_frame_hdr *hdr);
+
+static struct net_device_stats *dldwd_get_stats(struct net_device *dev);
+static struct iw_statistics *dldwd_get_wireless_stats(struct net_device *dev);
+
+/* Hardware control routines */
+
+static int __dldwd_hw_reset(dldwd_priv_t *priv);
+static int __dldwd_hw_setup_wep(dldwd_priv_t *priv);
+static int dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN]);
+static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]);
+static long dldwd_hw_get_freq(dldwd_priv_t *priv);
+static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,
+				    int32_t *rates, int max);
+
+/* Interrupt handling routines */
+static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_wterr(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw);
+static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw);
+
+static int dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq);
+static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);
+static int dldwd_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq);
+static int dldwd_ioctl_setessid(struct net_device *dev, struct iw_point *erq);
+static int dldwd_ioctl_getessid(struct net_device *dev, struct iw_point *erq);
+static int dldwd_ioctl_setnick(struct net_device *dev, struct iw_point *nrq);
+static int dldwd_ioctl_getnick(struct net_device *dev, struct iw_point *nrq);
+static int dldwd_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq);
+static int dldwd_ioctl_getsens(struct net_device *dev, struct iw_param *srq);
+static int dldwd_ioctl_setsens(struct net_device *dev, struct iw_param *srq);
+static int dldwd_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);
+static int dldwd_ioctl_setfrag(struct net_device *dev, struct iw_param *frq);
+static int dldwd_ioctl_getfrag(struct net_device *dev, struct iw_param *frq);
+static int dldwd_ioctl_setrate(struct net_device *dev, struct iw_param *frq);
+static int dldwd_ioctl_getrate(struct net_device *dev, struct iw_param *frq);
+static int dldwd_ioctl_setpower(struct net_device *dev, struct iw_param *prq);
+static int dldwd_ioctl_getpower(struct net_device *dev, struct iw_param *prq);
+static int dldwd_ioctl_setport3(struct net_device *dev, struct iwreq *wrq);
+static int dldwd_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);
+static void __dldwd_set_multicast_list(struct net_device *dev);
+
+/* /proc debugging stuff */
+static int dldwd_proc_init(void);
+static void dldwd_proc_cleanup(void);
+
+/*
+ * Inline functions
+ */
+static inline void
+dldwd_lock(dldwd_priv_t *priv)
+{
+	spin_lock_bh(&priv->lock);
+}
+
+static inline void
+dldwd_unlock(dldwd_priv_t *priv)
+{
+	spin_unlock_bh(&priv->lock);
+}
+
+static inline int
+dldwd_irqs_allowed(dldwd_priv_t *priv)
+{
+	return test_bit(DLDWD_STATE_DOIRQ, &priv->state);
+}
+
+static inline void
+__dldwd_stop_irqs(dldwd_priv_t *priv)
+{
+	hermes_t *hw = &priv->hw;
+
+	hermes_set_irqmask(hw, 0);
+	clear_bit(DLDWD_STATE_DOIRQ, &priv->state);
+	while (test_bit(DLDWD_STATE_INIRQ, &priv->state))
+		;
+}
+
+static inline void
+__dldwd_start_irqs(dldwd_priv_t *priv, uint16_t irqmask)
+{
+	hermes_t *hw = &priv->hw;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	__cli();
+	set_bit(DLDWD_STATE_DOIRQ, &priv->state);
+	hermes_set_irqmask(hw, irqmask);
+	__sti();
+
+	TRACE_EXIT(priv->ndev.name);
+}
+
+static inline void
+set_port_type(dldwd_priv_t *priv)
+{
+	switch (priv->iw_mode) {
+	case IW_MODE_INFRA:
+		priv->port_type = 1;
+		priv->allow_ibss = 0;
+		break;
+	case IW_MODE_ADHOC:
+		if (priv->prefer_port3) {
+			priv->port_type = 3;
+			priv->allow_ibss = 0;
+		} else {
+			priv->port_type = 1;
+			priv->allow_ibss = 1;
+		}
+		break;
+	default:
+		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
+		       priv->ndev.name);
+	}
+}
+
+extern void
+dldwd_set_multicast_list(struct net_device *dev)
+{
+	dldwd_priv_t *priv = dev->priv;
+
+	dldwd_lock(priv);
+	__dldwd_set_multicast_list(dev);
+	dldwd_unlock(priv);
+}
+
+/*
+ * Hardware control routines
+ */
+
+static int
+__dldwd_hw_reset(dldwd_priv_t *priv)
+{
+	hermes_t *hw = &priv->hw;
+	int err;
+
+	if (! priv->broken_reset)
+		return hermes_reset(hw);
+	else {
+		hw->inten = 0;
+		hermes_write_regn(hw, INTEN, 0);
+		err = hermes_disable_port(hw, 0);
+		hermes_write_regn(hw, EVACK, 0xffff);
+		return err;
+	}
+}
+
+void
+dldwd_shutdown(dldwd_priv_t *priv)
+{
+/* 	hermes_t *hw = &priv->hw; */
+	int err = 0;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	dldwd_lock(priv);
+	__dldwd_stop_irqs(priv);
+
+	err = __dldwd_hw_reset(priv);
+	if (err && err != -ENODEV) /* If the card is gone, we don't care about shutting it down */
+		printk(KERN_ERR "%s: Error %d shutting down Hermes chipset\n", priv->ndev.name, err);
+
+	dldwd_unlock(priv);
+
+	TRACE_EXIT(priv->ndev.name);
+}
+
+int
+dldwd_reset(dldwd_priv_t *priv)
+{
+	struct net_device *dev = &priv->ndev;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	hermes_id_t idbuf;
+	int frame_size;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	dldwd_lock(priv);
+
+	__dldwd_stop_irqs(priv);
+
+	err = __dldwd_hw_reset(priv);
+	if (err)
+		goto out;
+
+	frame_size = TX_NICBUF_SIZE;
+	/* This stupid bug is present in Intel firmware 1.10, and
+	 * may be fixed in later firmwares - Jean II */
+	if(priv->broken_allocate)
+		frame_size = TX_NICBUF_SIZE_BUG;
+	err = hermes_allocate(hw, frame_size, &priv->txfid);
+	if (err)
+		goto out;
+
+	/* Now set up all the parameters on the card */
+	
+	/* Set up the link mode */
+	
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PORTTYPE, priv->port_type);
+	if (err)
+		goto out;
+	if (priv->has_ibss) {
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CREATEIBSS,
+					   priv->allow_ibss);
+		if (err)
+			goto out;
+		if((strlen(priv->desired_essid) == 0) && (priv->allow_ibss)
+		   && (!priv->has_ibss_any)) {
+			printk(KERN_WARNING "%s: This firmware requires an \
+ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
+			/* With wvlan_cs, in this case, we would crash.
+			 * hopefully, this driver will behave better...
+			 * Jean II */
+		}
+	}
+
+	/* Set up encryption */
+	if (priv->has_wep) {
+		err = __dldwd_hw_setup_wep(priv);
+		if (err)
+			goto out;
+	}
+
+	/* Set the desired ESSID */
+	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
+	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
+	err = hermes_write_ltv(hw, USER_BAP, (priv->port_type == 3) ?
+			       HERMES_RID_CNF_OWN_SSID : HERMES_RID_CNF_DESIRED_SSID,
+			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			       &idbuf);
+	if (err)
+		goto out;
+
+	/* Set the station name */
+	idbuf.len = cpu_to_le16(strlen(priv->nick));
+	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
+	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNF_NICKNAME,
+			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+			       &idbuf);
+	if (err)
+		goto out;
+
+	/* Set the channel/frequency */
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_CHANNEL, priv->channel);
+	if (err)
+		goto out;
+
+	/* Set AP density */
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, priv->ap_density);
+	if (err)
+		goto out;
+
+	/* Set RTS threshold */
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, priv->rts_thresh);
+	if (err)
+		goto out;
+
+	/* Set fragmentation threshold or MWO robustness */
+	if (priv->has_mwo)
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNF_MWO_ROBUST, priv->mwo_robust);
+	else
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNF_FRAG_THRESH, priv->frag_thresh);
+	if (err)
+		goto out;
+
+	/* Set bitrate */
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_RATE_CTRL,
+				   priv->tx_rate_ctrl);
+	if (err)
+		goto out;
+
+	/* Set power management */
+	if (priv->has_pm) {
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_ENABLE,
+					   priv->pm_on);
+		if (err)
+			goto out;
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_MCAST_RX,
+					   priv->pm_mcast);
+		if (err)
+			goto out;
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD,
+					   priv->pm_period);
+		if (err)
+			goto out;
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER,
+					   priv->pm_timeout);
+		if (err)
+			goto out;
+	}
+
+	/* Set preamble - only for Symbol so far... */
+	if (priv->has_preamble) {
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE,
+					   priv->preamble);
+		if (err) {
+			printk(KERN_WARNING "%s: Can't set preamble!\n", dev->name);
+			goto out;
+		}
+	}
+
+	/* Set promiscuity / multicast*/
+	priv->promiscuous = 0;
+	priv->allmulti = 0;
+	priv->mc_count = 0;
+	__dldwd_set_multicast_list(dev);
+	
+	err = hermes_enable_port(hw, DLDWD_MACPORT);
+	if (err)
+		goto out;
+	
+	__dldwd_start_irqs(priv, HERMES_EV_RX | HERMES_EV_ALLOC |
+			   HERMES_EV_TX | HERMES_EV_TXEXC |
+			   HERMES_EV_WTERR | HERMES_EV_INFO |
+			   HERMES_EV_INFDROP);
+
+ out:
+	dldwd_unlock(priv);
+
+	TRACE_EXIT(priv->ndev.name);
+
+	return err;
+}
+
+static int __dldwd_hw_setup_wep(dldwd_priv_t *priv)
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	int	extra_wep_flag = 0;
+
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_LUCENT: /* Lucent style WEP */
+		if (priv->wep_on) {
+			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_KEY, priv->tx_key);
+			if (err)
+				return err;
+			
+			err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNF_KEYS, &priv->keys);
+			if (err)
+				return err;
+		}
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_WEP_ON, priv->wep_on);
+		if (err)
+			return err;
+		break;
+
+	case FIRMWARE_TYPE_PRISM2: /* Prism II style WEP */
+	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
+		if (priv->wep_on) {
+			char keybuf[LARGE_KEY_SIZE+1];
+			int keylen;
+			int i;
+			
+			/* Write all 4 keys */
+			for(i = 0; i < MAX_KEYS; i++) {
+				keylen = priv->keys[i].len;
+				keybuf[keylen] = '\0';
+				memcpy(keybuf, priv->keys[i].data, keylen);
+				err = hermes_write_ltv(hw, USER_BAP,
+						       HERMES_RID_CNF_PRISM2_KEY0 + i,
+						       HERMES_BYTES_TO_RECLEN(keylen + 1),
+						       &keybuf);
+				if (err)
+					return err;
+			}
+
+			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_TX_KEY,
+						   priv->tx_key);
+			if (err)
+				return err;
+
+			/* Authentication is where Prism2 and Symbol
+			 * firmware differ... */
+			if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL) {
+				/* Symbol cards : set the authentication :
+				 * 0 -> no encryption, 1 -> open,
+				 * 2 -> shared key, 3 -> shared key 128bit */
+				if(priv->wep_restrict) {
+					if(priv->keys[priv->tx_key].len >
+					   SMALL_KEY_SIZE)
+						extra_wep_flag = 3;
+					else
+						extra_wep_flag = 2;
+				} else
+					extra_wep_flag = 1;
+				err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_AUTH_TYPE, priv->wep_restrict);
+				if (err)
+					return err;
+			} else {
+				/* Prism2 card : we need to modify master
+				 * WEP setting */
+				if(priv->wep_restrict)
+					extra_wep_flag = 2;
+				else
+					extra_wep_flag = 0;
+			}
+		}
+		
+		/* Master WEP setting : on/off */
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PRISM2_WEP_ON, (priv->wep_on | extra_wep_flag));
+		if (err)
+			return err;	
+		break;
+
+	default:
+		if (priv->wep_on) {
+			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
+			       priv->ndev.name);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int dldwd_hw_get_bssid(dldwd_priv_t *priv, char buf[ETH_ALEN])
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+
+	dldwd_lock(priv);
+
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_BSSID,
+			      ETH_ALEN, NULL, buf);
+
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_hw_get_essid(dldwd_priv_t *priv, int *active,
+			      char buf[IW_ESSID_MAX_SIZE+1])
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	hermes_id_t essidbuf;
+	char *p = (char *)(&essidbuf.val);
+	int len;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	dldwd_lock(priv);
+
+	if (strlen(priv->desired_essid) > 0) {
+		/* We read the desired SSID from the hardware rather
+		   than from priv->desired_essid, just in case the
+		   firmware is allowed to change it on us. I'm not
+		   sure about this */
+		/* My guess is that the OWN_SSID should always be whatever
+		 * we set to the card, whereas CURRENT_SSID is the one that
+		 * may change... - Jean II */
+		uint16_t rid;
+
+		*active = 1;
+
+		rid = (priv->port_type == 3) ? HERMES_RID_CNF_OWN_SSID :
+			HERMES_RID_CNF_DESIRED_SSID;
+		
+		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
+				      NULL, &essidbuf);
+		if (err)
+			goto fail_unlock;
+	} else {
+		*active = 0;
+
+		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_SSID,
+				      sizeof(essidbuf), NULL, &essidbuf);
+		if (err)
+			goto fail_unlock;
+	}
+
+	len = le16_to_cpu(essidbuf.len);
+
+	memset(buf, 0, sizeof(buf));
+	memcpy(buf, p, len);
+	buf[len] = '\0';
+
+ fail_unlock:
+	dldwd_unlock(priv);
+
+	TRACE_EXIT(priv->ndev.name);
+
+	return err;       
+}
+
+static long dldwd_hw_get_freq(dldwd_priv_t *priv)
+{
+	
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	uint16_t channel;
+	long freq = 0;
+
+	dldwd_lock(priv);
+	
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_CHANNEL, &channel);
+	if (err)
+		goto out;
+
+	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
+		struct net_device *dev = &priv->ndev;
+
+		printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel);
+		err = -EBUSY;
+		goto out;
+
+	}
+	freq = channel_frequency[channel-1] * 100000;
+
+ out:
+	dldwd_unlock(priv);
+
+	if (err > 0)
+		err = -EBUSY;
+	return err ? err : freq;
+}
+
+static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,
+				    int32_t *rates, int max)
+{
+	hermes_t *hw = &priv->hw;
+	hermes_id_t list;
+	unsigned char *p = (unsigned char *)&list.val;
+	int err = 0;
+	int num;
+	int i;
+
+	dldwd_lock(priv);
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_DATARATES, sizeof(list),
+			      NULL, &list);
+	dldwd_unlock(priv);
+
+	if (err)
+		return err;
+	
+	num = le16_to_cpu(list.len);
+	*numrates = num;
+	num = MIN(num, max);
+
+	for (i = 0; i < num; i++) {
+		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
+	}
+
+	return 0;
+}
+
+#ifndef PCMCIA_DEBUG
+static inline void show_rx_frame(struct dldwd_frame_hdr *frame) {}
+#else
+static void show_rx_frame(struct dldwd_frame_hdr *frame)
+{
+	printk(KERN_DEBUG "RX descriptor:\n");
+	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
+	printk(KERN_DEBUG "  res1        = 0x%04x\n", frame->desc.res1);
+	printk(KERN_DEBUG "  res2        = 0x%04x\n", frame->desc.res2);
+	printk(KERN_DEBUG "  q_info      = 0x%04x\n", frame->desc.q_info);
+	printk(KERN_DEBUG "  res3        = 0x%04x\n", frame->desc.res3);
+	printk(KERN_DEBUG "  res4        = 0x%04x\n", frame->desc.res4);
+	printk(KERN_DEBUG "  tx_ctl      = 0x%04x\n", frame->desc.tx_ctl);
+
+	printk(KERN_DEBUG "IEEE 802.11 header:\n");
+	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
+	       frame->p80211.frame_ctl);
+	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
+	       frame->p80211.duration_id);
+	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr1[0], frame->p80211.addr1[1],
+	       frame->p80211.addr1[2], frame->p80211.addr1[3],
+	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
+	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr2[0], frame->p80211.addr2[1],
+	       frame->p80211.addr2[2], frame->p80211.addr2[3],
+	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
+	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr3[0], frame->p80211.addr3[1],
+	       frame->p80211.addr3[2], frame->p80211.addr3[3],
+	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
+	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
+	       frame->p80211.seq_ctl);
+	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr4[0], frame->p80211.addr4[1],
+	       frame->p80211.addr4[2], frame->p80211.addr4[3],
+	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
+	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
+	       frame->p80211.data_len);
+
+	printk(KERN_DEBUG "IEEE 802.3 header:\n");
+	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
+	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
+	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
+	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p8023.h_source[0], frame->p8023.h_source[1],
+	       frame->p8023.h_source[2], frame->p8023.h_source[3],
+	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
+	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
+
+	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
+	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
+	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
+	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
+	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
+	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
+	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
+}
+#endif
+
+/*
+ * Interrupt handler
+ */
+void dldwd_interrupt(int irq, void * dev_id, struct pt_regs *regs)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *) dev_id;
+	hermes_t *hw = &priv->hw;
+	struct net_device *dev = &priv->ndev;
+	int count = IRQ_LOOP_MAX;
+	uint16_t evstat, events;
+	static int old_time = 0, timecount = 0; /* Eugh, revolting hack for now */
+
+	if (test_and_set_bit(DLDWD_STATE_INIRQ, &priv->state))
+		BUG();
+
+	if (! dldwd_irqs_allowed(priv)) {
+		clear_bit(DLDWD_STATE_INIRQ, &priv->state);
+		return;
+	}
+
+	DEBUG(3, "%s: dldwd_interrupt()\n", priv->ndev.name);
+
+	while (1) {
+		if (jiffies != old_time)
+			timecount = 0;
+		if ( (++timecount > 50) || (! count--) ) {
+			printk(KERN_CRIT "%s: IRQ handler is looping too \
+much! Shutting down.\n",
+			       dev->name);
+			/* Perform an emergency shutdown */
+			clear_bit(DLDWD_STATE_DOIRQ, &priv->state);
+			hermes_set_irqmask(hw, 0);
+			break;
+		}
+
+		evstat = hermes_read_regn(hw, EVSTAT);
+		DEBUG(3, "__dldwd_interrupt(): count=%d EVSTAT=0x%04x inten=0x%04x\n",
+		      count, evstat, hw->inten);
+
+		events = evstat & hw->inten;
+
+		if (! events) {
+			if (netif_queue_stopped(dev)) {
+				/* There seems to be a firmware bug which
+				   sometimes causes the card to give an
+				   interrupt with no event set, when there
+				   sould be a Tx completed event. */
+				DEBUG(3, "%s: Interrupt with no event (ALLOCFID=0x%04x)\n",
+				      dev->name, (int)hermes_read_regn(hw, ALLOCFID));
+				events = HERMES_EV_TX | HERMES_EV_ALLOC;
+			} else /* Nothing's happening, we're done */
+				break;
+		}
+
+		/* Check the card hasn't been removed */
+		if (! hermes_present(hw)) {
+			DEBUG(0, "dldwd_interrupt(): card removed\n");
+			break;
+		}
+
+		if (events & HERMES_EV_TICK)
+			__dldwd_ev_tick(priv, hw);
+		if (events & HERMES_EV_WTERR)
+			__dldwd_ev_wterr(priv, hw);
+		if (events & HERMES_EV_INFDROP)
+			__dldwd_ev_infdrop(priv, hw);
+		if (events & HERMES_EV_INFO)
+			__dldwd_ev_info(priv, hw);
+		if (events & HERMES_EV_RX)
+			__dldwd_ev_rx(priv, hw);
+		if (events & HERMES_EV_TXEXC)
+			__dldwd_ev_txexc(priv, hw);
+		if (events & HERMES_EV_TX)
+			__dldwd_ev_tx(priv, hw);
+		if (events & HERMES_EV_ALLOC)
+			__dldwd_ev_alloc(priv, hw);
+		
+		hermes_write_regn(hw, EVACK, events);
+	}
+
+	clear_bit(DLDWD_STATE_INIRQ, &priv->state);
+}
+
+static void __dldwd_ev_tick(dldwd_priv_t *priv, hermes_t *hw)
+{
+	printk(KERN_DEBUG "%s: TICK\n", priv->ndev.name);
+}
+
+static void __dldwd_ev_wterr(dldwd_priv_t *priv, hermes_t *hw)
+{
+	/* This seems to happen a fair bit under load, but ignoring it
+	   seems to work fine...*/
+	DEBUG(1, "%s: MAC controller error (WTERR). Ignoring.\n",
+	      priv->ndev.name);
+}
+
+static void __dldwd_ev_infdrop(dldwd_priv_t *priv, hermes_t *hw)
+{
+	printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev.name);
+}
+
+static void __dldwd_ev_info(dldwd_priv_t *priv, hermes_t *hw)
+{
+	DEBUG(3, "%s: Information frame received.\n", priv->ndev.name);
+	/* We don't actually do anything about it - we assume the MAC
+	   controller can deal with it */
+}
+
+static void __dldwd_ev_rx(dldwd_priv_t *priv, hermes_t *hw)
+{
+	struct net_device *dev = &priv->ndev;
+	struct net_device_stats *stats = &priv->stats;
+	struct iw_statistics *wstats = &priv->wstats;
+	struct sk_buff *skb = NULL;
+	uint16_t rxfid, status;
+	int length, data_len, data_off;
+	char *p;
+	struct dldwd_frame_hdr hdr;
+	struct ethhdr *eh;
+	int err;
+
+	rxfid = hermes_read_regn(hw, RXFID);
+	DEBUG(3, "__dldwd_ev_rx(): RXFID=0x%04x\n", rxfid);
+
+	/* We read in the entire frame header here. This isn't really
+	   necessary, since we ignore most of it, but it's
+	   conceptually simpler. We can tune this later if
+	   necessary. */
+	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading frame header. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	status = le16_to_cpu(hdr.desc.status);
+	
+	if (status & HERMES_RXSTAT_ERR) {
+		if ((status & HERMES_RXSTAT_ERR) == HERMES_RXSTAT_BADCRC) {
+			stats->rx_crc_errors++;
+			printk(KERN_WARNING "%s: Bad CRC on Rx. Frame dropped.\n",
+			       dev->name);
+			show_rx_frame(&hdr);
+		} else if ((status & HERMES_RXSTAT_ERR)
+			   == HERMES_RXSTAT_UNDECRYPTABLE) {
+			wstats->discard.code++;
+			printk(KERN_WARNING "%s: Undecryptable frame on Rx. Frame dropped.\n",
+			       dev->name);
+		} else {
+			wstats->discard.misc++;
+			printk("%s: Unknown Rx error (0x%x). Frame dropped.\n",
+			       dev->name, status & HERMES_RXSTAT_ERR);
+		}
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	length = le16_to_cpu(hdr.p80211.data_len);
+	/* Yes, you heard right, that's le16. 802.2 and 802.3 are
+	   big-endian, but 802.11 is little-endian believe it or
+	   not. */
+	/* Correct. 802.3 is big-endian byte order and little endian bit
+	 * order, whereas 802.11 is little endian for both byte and bit
+	 * order. That's specified in the 802.11 spec. - Jean II */
+	
+	/* Sanity check */
+	if (length > MAX_FRAME_SIZE) {
+		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
+		       dev->name, length);
+		stats->rx_length_errors++;
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	/* We need space for the packet data itself, plus an ethernet
+	   header, plus 2 bytes so we can align the IP header on a
+	   32bit boundary, plus 1 byte so we can read in odd length
+	   packets from the card, which has an IO granularity of 16
+	   bits */  
+	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+	if (!skb) {
+		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
+		       dev->name);
+		stats->rx_dropped++;
+		goto drop;
+	}
+
+	skb_reserve(skb, 2); /* This way the IP header is aligned */
+
+	/* Handle decapsulation
+	 * In most cases, the firmware tell us about SNAP frames.
+	 * For some reason, the SNAP frames sent by LinkSys APs
+	 * are not properly recognised by most firmwares.
+	 * So, check ourselves (note : only 3 bytes out of 6).
+	 */
+	if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
+	   ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
+	   (!memcmp(&hdr.p8022, &encaps_hdr, 3))) {
+		/* These indicate a SNAP within 802.2 LLC within
+		   802.11 frame which we'll need to de-encapsulate to
+		   the original EthernetII frame.
+		   IEEE and ISO OSI have a lot to answer for.  */
+
+		/* Remove SNAP header, reconstruct EthernetII frame */
+		data_len = length - ENCAPS_OVERHEAD;
+		data_off = sizeof(hdr);
+
+		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+
+		memcpy(eh, &hdr.p8023, sizeof(hdr.p8023));
+		eh->h_proto = hdr.ethertype;
+	} else {
+		/* All other cases indicate a genuine 802.3 frame.
+		 * No decapsulation needed */
+
+		/* Otherwise, we just throw the whole thing in,
+		 * and hope the protocol layer can deal with it
+		 * as 802.3 */
+		data_len = length;
+		data_off = P8023_OFFSET;
+	}
+
+	p = skb_put(skb, data_len);
+	if (hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
+			     rxfid, data_off) != 0) {
+		printk(KERN_WARNING "%s: Error reading packet data\n",
+		       dev->name);
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	dev->last_rx = jiffies;
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_NONE;
+	
+	/* Process the wireless stats if needed */
+	dldwd_stat_gather(dev, skb, &hdr);
+
+	/* Pass the packet to the networking stack */
+	netif_rx(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += length;
+
+	return;
+
+ drop:	
+	if (skb)
+		dev_kfree_skb_irq(skb);
+	return;
+}
+
+static void __dldwd_ev_txexc(dldwd_priv_t *priv, hermes_t *hw)
+{
+	struct net_device *dev = &priv->ndev;
+	struct net_device_stats *stats = &priv->stats;
+
+	printk(KERN_WARNING "%s: Tx error!\n", dev->name);
+
+	netif_wake_queue(dev);
+	stats->tx_errors++;
+}
+
+static void __dldwd_ev_tx(dldwd_priv_t *priv, hermes_t *hw)
+{
+	struct net_device *dev = &priv->ndev;
+	struct net_device_stats *stats = &priv->stats;
+
+	DEBUG(3, "%s: Transmit completed\n", dev->name);
+
+	stats->tx_packets++;
+	netif_wake_queue(dev);
+}
+
+static void __dldwd_ev_alloc(dldwd_priv_t *priv, hermes_t *hw)
+{
+	uint16_t allocfid;
+
+	allocfid = hermes_read_regn(hw, ALLOCFID);
+	DEBUG(3, "%s: Allocation complete FID=0x%04x\n", priv->ndev.name, allocfid);
+
+	/* For some reason we don't seem to get transmit completed events properly */
+	if (allocfid == priv->txfid)
+		__dldwd_ev_tx(priv, hw);
+
+/* 	hermes_write_regn(hw, ALLOCFID, 0); */
+}
+
+/*
+ * struct net_device methods
+ */
+
+int
+dldwd_init(struct net_device *dev)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	hermes_id_t nickbuf;
+	uint16_t reclen;
+	int len;
+	char *vendor_str;
+	uint32_t firmver;
+
+	TRACE_ENTER("dldwd");
+	
+	dldwd_lock(priv);
+
+	err = hermes_reset(hw);
+	if (err != 0) {
+		printk(KERN_ERR "%s: failed to reset hardware\n", dev->name);
+		goto out;
+	}
+	
+	/* Get the firmware version */
+	err = hermes_read_staidentity(hw, USER_BAP, &priv->firmware_info);
+	if (err) {
+		printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",
+		       dev->name, err);
+		memset(&priv->firmware_info, 0, sizeof(priv->firmware_info));
+	}
+
+	firmver = ((uint32_t)priv->firmware_info.major << 16) | priv->firmware_info.minor;
+	DEBUG(2, "%s: firmver = 0x%X\n", dev->name, firmver);
+
+	/* Determine capabilities from the firmware version */
+
+	switch (priv->firmware_info.vendor) {
+	case 0x1:
+		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
+		 * ELSA, Melco, HP, IBM, Dell 1150 cards */
+		vendor_str = "Lucent";
+		/* Lucent MAC : 00:60:1D:* & 00:02:2D:* */
+
+		priv->firmware_type = FIRMWARE_TYPE_LUCENT;
+		priv->broken_reset = 0;
+		priv->broken_allocate = 0;
+		priv->has_port3 = 1;		/* Still works in 7.28 */
+		priv->has_ibss = (firmver >= 0x60006);
+		priv->has_ibss_any = (firmver >= 0x60010);
+		priv->has_wep = (firmver >= 0x40020);
+		priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
+					  Gold cards from the others? */
+		priv->has_mwo = (firmver >= 0x60000);
+		priv->has_pm = (firmver >= 0x40020);
+		priv->has_preamble = 0;
+		/* Tested with Lucent firmware :
+		 *	1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
+		 * Tested CableTron firmware : 4.32 => Anton */
+		break;
+	case 0x2:
+		vendor_str = "Generic Prism II";
+		/* Some D-Link cards report vendor 0x02... */
+
+		priv->firmware_type = FIRMWARE_TYPE_PRISM2;
+		priv->broken_reset = 0;
+		priv->broken_allocate = 0;
+		priv->has_port3 = 1;
+		priv->has_ibss = (firmver >= 0x00007); /* FIXME */
+		priv->has_wep = (firmver >= 0x00007); /* FIXME */
+		priv->has_big_wep = 0;
+		priv->has_mwo = 0;
+		priv->has_pm = (firmver >= 0x00007); /* FIXME */
+		priv->has_preamble = 0;
+
+		/* Tim Hurley -> D-Link card, vendor 02, firmware 0.08 */
+
+		/* Special case for Symbol cards */
+		if(firmver == 0x10001) {
+			/* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
+			vendor_str = "Symbol";
+			/* Intel MAC : 00:02:B3:* */
+			/* 3Com MAC : 00:50:DA:* */
+
+			/* FIXME : probably need to use SYMBOL_***ARY_VER
+			 * to get proper firmware version */
+			priv->firmware_type = FIRMWARE_TYPE_SYMBOL;
+			priv->broken_reset = 0;
+			priv->broken_allocate = 1;
+			priv->has_port3 = 1;
+			priv->has_ibss = 1; /* FIXME */
+			priv->has_wep = 1; /* FIXME */
+			priv->has_big_wep = 1;	/* RID_SYMBOL_KEY_LENGTH */
+			priv->has_mwo = 0;
+			priv->has_pm = 1; /* FIXME */
+			priv->has_preamble = 0; /* FIXME */
+			/* Tested with Intel firmware : v15 => Jean II */
+		}
+		break;
+	case 0x3:
+		vendor_str = "Samsung";
+		/* To check - Should cover Samsung & Compaq */
+
+		priv->firmware_type = FIRMWARE_TYPE_PRISM2;
+		priv->broken_reset = 0;
+		priv->broken_allocate = 0;
+		priv->has_port3 = 1;
+		priv->has_ibss = 0; /* FIXME: available in later firmwares */
+		priv->has_wep = (firmver >= 0x20000); /* FIXME */
+		priv->has_big_wep = 0; /* FIXME */
+		priv->has_mwo = 0;
+		priv->has_pm = (firmver >= 0x20000); /* FIXME */
+		priv->has_preamble = 0;
+		break;
+	case 0x6:
+		/* D-Link DWL 650, ... */
+		vendor_str = "LinkSys/D-Link";
+		/* D-Link MAC : 00:40:05:* */
+
+		priv->firmware_type = FIRMWARE_TYPE_PRISM2;
+		priv->broken_reset = 0;
+		priv->broken_allocate = 0;
+		priv->has_port3 = 1;
+		priv->has_ibss = (firmver >= 0x00007); /* FIXME */
+		priv->has_wep = (firmver >= 0x00007); /* FIXME */
+		priv->has_big_wep = 0;
+		priv->has_mwo = 0;
+		priv->has_pm = (firmver >= 0x00007); /* FIXME */
+		priv->has_preamble = 0;
+		/* Tested with D-Link firmware 0.07 => Jean II */
+		/* Note : with 0.07, IBSS to a Lucent card seem flaky */
+		break;
+	default:
+		vendor_str = "UNKNOWN";
+
+		priv->firmware_type = 0;
+		priv->broken_reset = 0;
+		priv->broken_allocate = 0;
+		priv->has_port3 = 0;
+		priv->has_ibss = 0;
+		priv->has_wep = 0;
+		priv->has_big_wep = 0;
+		priv->has_mwo = 0;
+		priv->has_pm = 0;
+		priv->has_preamble = 0;
+	}
+
+	printk(KERN_INFO "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n",
+	       dev->name, priv->firmware_info.id, priv->firmware_info.vendor,
+	       vendor_str, priv->firmware_info.major, priv->firmware_info.minor);
+	
+	if (priv->has_port3)
+		printk(KERN_INFO "%s: Ad-hoc demo mode supported.\n", dev->name);
+	if (priv->has_ibss)
+		printk(KERN_INFO "%s: IEEE standard IBSS ad-hoc mode supported.\n",
+		       dev->name);
+	if (priv->has_wep) {
+		printk(KERN_INFO "%s: WEP supported, ", dev->name);
+		if (priv->has_big_wep)
+			printk("\"128\"-bit key.\n");
+		else
+			printk("40-bit key.\n");
+	}
+
+	/* Get the MAC address */
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNF_MACADDR,
+			      ETH_ALEN, NULL, dev->dev_addr);
+	if (err) {
+		printk(KERN_WARNING "%s: failed to read MAC address!\n",
+		       dev->name);
+		goto out;
+	}
+
+	printk(KERN_INFO "%s: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
+	       dev->name, dev->dev_addr[0], dev->dev_addr[1],
+	       dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4],
+	       dev->dev_addr[5]);
+
+	/* Get the station name */
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNF_NICKNAME,
+			      sizeof(nickbuf), &reclen, &nickbuf);
+	if (err) {
+		printk(KERN_ERR "%s: failed to read station name!n",
+		       dev->name);
+		goto out;
+	}
+	if ( nickbuf.len )
+		len = MIN(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));
+	else
+		len = MIN(IW_ESSID_MAX_SIZE, 2 * reclen);
+	memcpy(priv->nick, &nickbuf.val, len);
+	priv->nick[len] = '\0';
+
+	printk(KERN_INFO "%s: Station name \"%s\"\n", dev->name, priv->nick);
+
+	/* Get allowed channels */
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNEL_LIST, &priv->channel_mask);
+	if (err) {
+		printk(KERN_ERR "%s: failed to read channel list!\n",
+		       dev->name);
+		goto out;
+	}
+
+	/* Get initial AP density */
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, &priv->ap_density);
+	if (err) {
+		printk(KERN_ERR "%s: failed to read AP density!\n", dev->name);
+		goto out;
+	}
+
+	/* Get initial RTS threshold */
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_RTS_THRESH, &priv->rts_thresh);
+	if (err) {
+		printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name);
+		goto out;
+	}
+
+	/* Get initial fragmentation settings */
+	if (priv->has_mwo)
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_MWO_ROBUST,
+					  &priv->mwo_robust);
+	else
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH,
+					  &priv->frag_thresh);
+	if (err) {
+		printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name);
+		goto out;
+	}
+
+	/* Set initial bitrate control*/
+	priv->tx_rate_ctrl = 3;
+
+	/* Power management setup */
+	if (priv->has_pm) {
+		priv->pm_on = 0;
+		priv->pm_mcast = 1;
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD,
+					  &priv->pm_period);
+		if (err) {
+			printk(KERN_ERR "%s: failed to read power management period!\n",
+			       dev->name);
+			goto out;
+		}
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER,
+					  &priv->pm_timeout);
+		if (err) {
+			printk(KERN_ERR "%s: failed to read power management timeout!\n",
+			       dev->name);
+			goto out;
+		}
+	}
+
+	/* Preamble setup */
+	if (priv->has_preamble) {
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYMBOL_PREAMBLE, &priv->preamble);
+		if (err)
+			goto out;
+	}
+		
+	/* Set up the default configuration */
+	priv->iw_mode = IW_MODE_INFRA;
+	/* By default use IEEE/IBSS ad-hoc mode if we have it */
+	priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
+	set_port_type(priv);
+
+	priv->promiscuous = 0;
+	priv->allmulti = 0;
+	priv->wep_on = 0;
+	priv->tx_key = 0;
+
+	printk(KERN_INFO "%s: ready\n", dev->name);
+
+ out:
+	dldwd_unlock(priv);
+
+	TRACE_EXIT("dldwd");
+
+	return err;
+}
+
+struct net_device_stats *
+dldwd_get_stats(struct net_device *dev)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	
+	return &priv->stats;
+}
+
+struct iw_statistics *
+dldwd_get_wireless_stats(struct net_device *dev)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	hermes_t *hw = &priv->hw;
+	struct iw_statistics *wstats = &priv->wstats;
+	int err = 0;
+	hermes_commsqual_t cq;
+
+	if (!priv->hw_ready)
+		return NULL;
+
+	dldwd_lock(priv);
+
+	if (priv->port_type == 3) {
+		memset(&wstats->qual, 0, sizeof(wstats->qual));
+#ifdef WIRELESS_SPY
+		/* If a spy address is defined, we report stats of the
+		 * first spy address - Jean II */
+		if (priv->spy_number > 0) {
+			wstats->qual.qual = priv->spy_stat[0].qual;
+			wstats->qual.level = priv->spy_stat[0].level;
+			wstats->qual.noise = priv->spy_stat[0].noise;
+			wstats->qual.updated = priv->spy_stat[0].updated;
+		}
+#endif /* WIRELESS_SPY */
+	} else {
+		err = hermes_read_commsqual(hw, USER_BAP, &cq);
+		
+		DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name,
+		      cq.qual, cq.signal, cq.noise);
+
+		/* Why are we using MIN/MAX ? We don't really care
+		 * if the value goes above max, because we export the
+		 * raw dBm values anyway. The normalisation should be done
+		 * in user space - Jean II */
+		wstats->qual.qual = MAX(MIN(cq.qual, 0x8b-0x2f), 0);
+		wstats->qual.level = MAX(MIN(cq.signal, 0x8a), 0x2f) - 0x95;
+		wstats->qual.noise = MAX(MIN(cq.noise, 0x8a), 0x2f) - 0x95;
+		wstats->qual.updated = 7;
+	}
+
+	dldwd_unlock(priv);
+
+	if (err)
+		return NULL;
+		
+	return wstats;
+}
+
+#ifdef WIRELESS_SPY
+static inline void dldwd_spy_gather(struct net_device *dev,
+				    u_char *mac,
+				    hermes_commsqual_t *cq)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	int i;
+
+	/* Gather wireless spy statistics: for each packet, compare the
+	 * source address with out list, and if match, get the stats... */
+	for (i = 0; i < priv->spy_number; i++)
+		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
+			priv->spy_stat[i].qual = MAX(MIN(cq->qual, 0x8b-0x2f), 0);
+			priv->spy_stat[i].level = MAX(MIN(cq->signal, 0x8a), 0x2f) - 0x95;
+			priv->spy_stat[i].noise = MAX(MIN(cq->noise, 0x8a), 0x2f) - 0x95;
+			priv->spy_stat[i].updated = 7;
+		}
+}
+#endif /* WIRELESS_SPY */
+
+void
+dldwd_stat_gather( struct net_device *dev,
+		   struct sk_buff *skb,
+		   struct dldwd_frame_hdr *hdr)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	hermes_commsqual_t cq;
+
+	/* Using spy support with lots of Rx packets, like in an
+	 * infrastructure (AP), will really slow down everything, because
+	 * the MAC address must be compared to each entry of the spy list.
+	 * If the user really asks for it (set some address in the
+	 * spy list), we do it, but he will pay the price.
+	 * Note that to get here, you need both WIRELESS_SPY
+	 * compiled in AND some addresses in the list !!!
+	 */
+#ifdef WIRELESS_EXT
+	/* Note : gcc will optimise the whole section away if
+	 * WIRELESS_SPY is not defined... - Jean II */
+	if (
+#ifdef WIRELESS_SPY
+		(priv->spy_number > 0) ||
+#endif
+		0 )
+	{
+		u_char *stats = (u_char *) &(hdr->desc.q_info);
+		/* This code may look strange. Everywhere we are using 16 bit
+		 * ints except here. I've verified that these are are the
+		 * correct values. Please check on PPC - Jean II */
+		cq.signal = stats[1];	/* High order byte */
+		cq.noise = stats[0];	/* Low order byte */
+		cq.qual = stats[0] - stats[1];	/* Better than nothing */
+
+		DEBUG(3, "%s: Packet stats = %X-%X-%X\n", dev->name,
+		      cq.qual, cq.signal, cq.noise);
+
+#ifdef WIRELESS_SPY
+		dldwd_spy_gather(dev, skb->mac.raw + ETH_ALEN, &cq);  
+#endif
+	}
+#endif /* WIRELESS_EXT */
+}
+
+int
+dldwd_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	struct net_device_stats *stats = &priv->stats;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	uint16_t txfid = priv->txfid;
+	char *p;
+	struct ethhdr *eh;
+	int len, data_len, data_off;
+	struct dldwd_frame_hdr hdr;
+	hermes_response_t resp;
+
+	if (! netif_running(dev)) {
+		printk(KERN_ERR "%s: Tx on stopped device!\n",
+		       dev->name);
+		return 1;
+
+	}
+	
+	if (netif_queue_stopped(dev)) {
+		printk(KERN_ERR "%s: Tx while transmitter busy!\n", 
+		       dev->name);
+		return 1;
+	}
+	
+	dldwd_lock(priv);
+
+	/* Length of the packet body */
+	len = MAX(skb->len - ETH_HLEN, ETH_ZLEN);
+
+	eh = (struct ethhdr *)skb->data;
+
+	/* Build the IEEE 802.11 header */
+	memset(&hdr, 0, sizeof(hdr));
+	memcpy(hdr.p80211.addr1, eh->h_dest, ETH_ALEN);
+	memcpy(hdr.p80211.addr2, eh->h_source, ETH_ALEN);
+	hdr.p80211.frame_ctl = DLDWD_FTYPE_DATA;
+
+	/* Encapsulate Ethernet-II frames */
+	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
+		data_len = len;
+		data_off = sizeof(hdr);
+		p = skb->data + ETH_HLEN;
+
+		/* 802.11 header */
+		hdr.p80211.data_len = cpu_to_le16(data_len + ENCAPS_OVERHEAD);
+
+		/* 802.3 header */
+		memcpy(hdr.p8023.h_dest, eh->h_dest, ETH_ALEN);
+		memcpy(hdr.p8023.h_source, eh->h_source, ETH_ALEN);
+		hdr.p8023.h_proto = htons(data_len + ENCAPS_OVERHEAD);
+		
+		/* 802.2 header */
+		memcpy(&hdr.p8022, &encaps_hdr, sizeof(encaps_hdr));
+
+		hdr.ethertype = eh->h_proto;
+		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
+					 txfid, 0);
+		if (err) {
+			printk(KERN_ERR
+			       "%s: Error %d writing packet header to BAP\n",
+			       dev->name, err);
+			stats->tx_errors++;
+			goto fail;
+		}
+	} else { /* IEEE 802.3 frame */
+		data_len = len + ETH_HLEN;
+		data_off = P8023_OFFSET;
+		p = skb->data;
+		
+		/* 802.11 header */
+		hdr.p80211.data_len = cpu_to_le16(len);
+		err = hermes_bap_pwrite(hw, USER_BAP, &hdr, P8023_OFFSET,
+					txfid, 0);
+		if (err) {
+			printk(KERN_ERR
+			       "%s: Error %d writing packet header to BAP\n",
+			       dev->name, err);
+			stats->tx_errors++;
+			goto fail;
+		}
+	}
+
+	/* Round up for odd length packets */
+	err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d writing packet data to BAP\n",
+		       dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
+	
+
+	/* Finally, we actually initiate the send */
+	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, &resp);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
+
+	dev->trans_start = jiffies;
+	stats->tx_bytes += data_off + data_len;
+
+	netif_stop_queue(dev);
+
+	dldwd_unlock(priv);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+ fail:
+
+	dldwd_unlock(priv);
+	return err;
+}
+
+void
+dldwd_tx_timeout(struct net_device *dev)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	struct net_device_stats *stats = &priv->stats;
+	int err = 0;
+
+	printk(KERN_WARNING "%s: Tx timeout! Resetting card.\n", dev->name);
+
+	stats->tx_errors++;
+
+	err = dldwd_reset(priv);
+	if (err)
+		printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n",
+		       dev->name, err);
+	else {
+		dev->trans_start = jiffies;
+		netif_wake_queue(dev);
+	}
+}
+
+static int dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int err = 0;
+	int ptype;
+	struct iw_range range;
+	int numrates;
+	int i, k;
+
+	TRACE_ENTER(dev->name);
+
+	err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range));
+	if (err)
+		return err;
+
+	rrq->length = sizeof(range);
+
+	dldwd_lock(priv);
+	ptype = priv->port_type;
+	dldwd_unlock(priv);
+
+	memset(&range, 0, sizeof(range));
+
+	/* Much of this shamelessly taken from wvlan_cs.c. No idea
+	 * what it all means -dgibson */
+#if WIRELESS_EXT > 10
+	range.we_version_compiled = WIRELESS_EXT;
+	range.we_version_source = 11;
+#endif /* WIRELESS_EXT > 10 */
+
+	range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
+
+	/* Set available channels/frequencies */
+	range.num_channels = NUM_CHANNELS;
+	k = 0;
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (priv->channel_mask & (1 << i)) {
+			range.freq[k].i = i + 1;
+			range.freq[k].m = channel_frequency[i] * 100000;
+			range.freq[k].e = 1;
+			k++;
+		}
+		
+		if (k >= IW_MAX_FREQUENCIES)
+			break;
+	}
+	range.num_frequency = k;
+
+	range.sensitivity = 3;
+
+	if ((ptype == 3) && (priv->spy_number == 0)){
+		/* Quality stats meaningless in ad-hoc mode */
+		range.max_qual.qual = 0;
+		range.max_qual.level = 0;
+		range.max_qual.noise = 0;
+	} else {
+		range.max_qual.qual = 0x8b - 0x2f;
+		range.max_qual.level = 0x2f - 0x95 - 1;
+		range.max_qual.noise = 0x2f - 0x95 - 1;
+	}
+
+	err = dldwd_hw_get_bitratelist(priv, &numrates,
+				       range.bitrate, IW_MAX_BITRATES);
+	if (err)
+		return err;
+	range.num_bitrates = numrates;
+	
+	/* Set an indication of the max TCP throughput in bit/s that we can
+	 * expect using this interface. May be use for QoS stuff...
+	 * Jean II */
+	if(numrates > 2)
+		range.throughput = 5 * 1000 * 1000;	/* ~5 Mb/s */
+	else
+		range.throughput = 1.5 * 1000 * 1000;	/* ~1.5 Mb/s */
+
+	range.min_rts = 0;
+	range.max_rts = 2347;
+	range.min_frag = 256;
+	range.max_frag = 2346;
+
+	dldwd_lock(priv);
+	if (priv->has_wep) {
+		range.max_encoding_tokens = MAX_KEYS;
+
+		range.encoding_size[0] = SMALL_KEY_SIZE;
+		range.num_encoding_sizes = 1;
+
+		if (priv->has_big_wep) {
+			range.encoding_size[1] = LARGE_KEY_SIZE;
+			range.num_encoding_sizes = 2;
+		}
+	} else {
+		range.num_encoding_sizes = 0;
+		range.max_encoding_tokens = 0;
+	}
+	dldwd_unlock(priv);
+		
+	range.min_pmp = 0;
+	range.max_pmp = 65535000;
+	range.min_pmt = 0;
+	range.max_pmt = 65535 * 1000;	/* ??? */
+	range.pmp_flags = IW_POWER_PERIOD;
+	range.pmt_flags = IW_POWER_TIMEOUT;
+	range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
+
+	range.num_txpower = 1;
+	range.txpower[0] = 15; /* 15dBm */
+	range.txpower_capa = IW_TXPOW_DBM;
+
+#if WIRELESS_EXT > 10
+	range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
+	range.retry_flags = IW_RETRY_LIMIT;
+	range.r_time_flags = IW_RETRY_LIFETIME;
+	range.min_retry = 0;
+	range.max_retry = 65535;	/* ??? */
+	range.min_r_time = 0;
+	range.max_r_time = 65535 * 1000;	/* ??? */
+#endif /* WIRELESS_EXT > 10 */
+
+	if (copy_to_user(rrq->pointer, &range, sizeof(range)))
+		return -EFAULT;
+
+	TRACE_EXIT(dev->name);
+
+	return 0;
+}
+
+static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+	int setindex = priv->tx_key;
+	int enable = priv->wep_on;
+	int restricted = priv->wep_restrict;
+	uint16_t xlen = 0;
+	int err = 0;
+	char keybuf[MAX_KEY_SIZE];
+
+	if (erq->pointer) {
+		/* We actually have a key to set */
+		
+		if (copy_from_user(keybuf, erq->pointer, erq->length))
+			return -EFAULT;
+	}
+	
+	dldwd_lock(priv);
+	
+	if (erq->pointer) {
+		if (erq->length > MAX_KEY_SIZE) {
+			err = -E2BIG;
+			goto out;
+		}
+		
+		if ( (erq->length > LARGE_KEY_SIZE)
+		     || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE))  ) {
+			err = -EINVAL;
+			goto out;
+		}
+		
+		if ((index < 0) || (index >= MAX_KEYS))
+			index = priv->tx_key;
+		
+		if (erq->length > SMALL_KEY_SIZE) {
+			xlen = LARGE_KEY_SIZE;
+		} else if (erq->length > 0) {
+			xlen = SMALL_KEY_SIZE;
+		} else
+			xlen = 0;
+		
+		/* Switch on WEP if off */
+		if ((!enable) && (xlen > 0)) {
+			setindex = index;
+			enable = 1;
+		}
+	} else {
+		/* Important note : if the user do "iwconfig eth0 enc off",
+		 * we will arrive there with an index of -1. This is valid
+		 * but need to be taken care off... Jean II */
+		if ((index < 0) || (index >= MAX_KEYS)) {
+			if((index != -1) || (erq->flags == 0)) {
+				err = -EINVAL;
+				goto out;
+			}
+		} else {
+			/* Set the index : Check that the key is valid */
+			if(priv->keys[index].len == 0) {
+				err = -EINVAL;
+				goto out;
+			}
+			setindex = index;
+		}
+	}
+	
+	if (erq->flags & IW_ENCODE_DISABLED)
+		enable = 0;
+	/* Only for Prism2 & Symbol cards (so far) - Jean II */
+	if (erq->flags & IW_ENCODE_OPEN)
+		restricted = 0;
+	if (erq->flags & IW_ENCODE_RESTRICTED)
+		restricted = 1;
+
+	if (erq->pointer) {
+		priv->keys[index].len = cpu_to_le16(xlen);
+		memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data));
+		memcpy(priv->keys[index].data, keybuf, erq->length);
+	}
+	priv->tx_key = setindex;
+	priv->wep_on = enable;
+	priv->wep_restrict = restricted;
+	
+ out:
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+static int dldwd_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
+	uint16_t xlen = 0;
+	char keybuf[MAX_KEY_SIZE];
+
+	
+	dldwd_lock(priv);
+
+	if ((index < 0) || (index >= MAX_KEYS))
+		index = priv->tx_key;
+
+	erq->flags = 0;
+	if (! priv->wep_on)
+		erq->flags |= IW_ENCODE_DISABLED;
+	erq->flags |= index + 1;
+	
+	/* Only for symbol cards - Jean II */
+	if (priv->firmware_type != FIRMWARE_TYPE_LUCENT) {
+		if(priv->wep_restrict)
+			erq->flags |= IW_ENCODE_RESTRICTED;
+		else
+			erq->flags |= IW_ENCODE_OPEN;
+	}
+
+	xlen = le16_to_cpu(priv->keys[index].len);
+
+	erq->length = xlen;
+
+	if (erq->pointer) {
+		memcpy(keybuf, priv->keys[index].data, MAX_KEY_SIZE);
+	}
+	
+	dldwd_unlock(priv);
+
+	if (erq->pointer) {
+		if (copy_to_user(erq->pointer, keybuf, xlen))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int dldwd_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	char essidbuf[IW_ESSID_MAX_SIZE+1];
+
+	/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
+	 * anyway... - Jean II */
+
+	memset(&essidbuf, 0, sizeof(essidbuf));
+
+	if (erq->flags) { 
+		if (erq->length > IW_ESSID_MAX_SIZE)
+			return -E2BIG;
+		
+		if (copy_from_user(&essidbuf, erq->pointer, erq->length))
+			return -EFAULT;
+
+		essidbuf[erq->length] = '\0';
+	}
+
+	dldwd_lock(priv);
+
+	memcpy(priv->desired_essid, essidbuf, IW_ESSID_MAX_SIZE+1);
+
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+static int dldwd_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	char essidbuf[IW_ESSID_MAX_SIZE+1];
+	int active;
+	int err = 0;
+
+	TRACE_ENTER(dev->name);
+
+	err = dldwd_hw_get_essid(priv, &active, essidbuf);
+	if (err)
+		return err;
+
+	erq->flags = 1;
+	erq->length = strlen(essidbuf) + 1;
+	if (erq->pointer)
+		if ( copy_to_user(erq->pointer, essidbuf, erq->length) )
+			return -EFAULT;
+
+	TRACE_EXIT(dev->name);
+	
+	return 0;
+}
+
+static int dldwd_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	char nickbuf[IW_ESSID_MAX_SIZE+1];
+
+	if (nrq->length > IW_ESSID_MAX_SIZE)
+		return -E2BIG;
+
+	memset(nickbuf, 0, sizeof(nickbuf));
+
+	if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
+		return -EFAULT;
+
+	nickbuf[nrq->length] = '\0';
+	
+	dldwd_lock(priv);
+
+	memcpy(priv->nick, nickbuf, sizeof(priv->nick));
+
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+static int dldwd_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	char nickbuf[IW_ESSID_MAX_SIZE+1];
+
+	dldwd_lock(priv);
+	memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
+	dldwd_unlock(priv);
+
+	nrq->length = strlen(nickbuf)+1;
+
+	if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int dldwd_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int chan = -1;
+
+	/* We can only use this in Ad-Hoc demo mode to set the operating
+	 * frequency, or in IBSS mode to set the frequency where the IBSS
+	 * will be created - Jean II */
+	if (priv->iw_mode != IW_MODE_ADHOC)
+		return -EOPNOTSUPP;
+
+	if ( (frq->e == 0) && (frq->m <= 1000) ) {
+		/* Setting by channel number */
+		chan = frq->m;
+	} else {
+		/* Setting by frequency - search the table */
+		int mult = 1;
+		int i;
+
+		for (i = 0; i < (6 - frq->e); i++)
+			mult *= 10;
+
+		for (i = 0; i < NUM_CHANNELS; i++)
+			if (frq->m == (channel_frequency[i] * mult))
+				chan = i+1;
+	}
+
+	if ( (chan < 1) || (chan > NUM_CHANNELS) ||
+	     ! (priv->channel_mask & (1 << (chan-1)) ) )
+		return -EINVAL;
+
+	dldwd_lock(priv);
+	priv->channel = chan;
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+static int dldwd_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	uint16_t val;
+	int err;
+
+	dldwd_lock(priv);
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_SYSTEM_SCALE, &val);
+	dldwd_unlock(priv);
+
+	if (err)
+		return err;
+
+	srq->value = val;
+	srq->fixed = 0; /* auto */
+
+	return 0;
+}
+
+static int dldwd_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int val = srq->value;
+
+	if ((val < 1) || (val > 3))
+		return -EINVAL;
+	
+	dldwd_lock(priv);
+	priv->ap_density = val;
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+static int dldwd_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int val = rrq->value;
+
+	if (rrq->disabled)
+		val = 2347;
+
+	if ( (val < 0) || (val > 2347) )
+		return -EINVAL;
+
+	dldwd_lock(priv);
+	priv->rts_thresh = val;
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+static int dldwd_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int err = 0;
+
+	dldwd_lock(priv);
+
+	if (priv->has_mwo) {
+		if (frq->disabled)
+			priv->mwo_robust = 0;
+		else {
+			if (frq->fixed)
+				printk(KERN_WARNING "%s: Fixed fragmentation not \
+supported on this firmware. Using MWO robust instead.\n", dev->name);
+			priv->mwo_robust = 1;
+		}
+	} else {
+		if (frq->disabled)
+			priv->frag_thresh = 2346;
+		else {
+			if ( (frq->value < 256) || (frq->value > 2346) )
+				err = -EINVAL;
+			else
+				priv->frag_thresh = frq->value & ~0x1; /* must be even */
+		}
+	}
+
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	uint16_t val;
+
+	dldwd_lock(priv);
+	
+	if (priv->has_mwo) {
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_MWO_ROBUST, &val);
+		if (err)
+			val = 0;
+
+		frq->value = val ? 2347 : 0;
+		frq->disabled = ! val;
+		frq->fixed = 0;
+	} else {
+		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH, &val);
+		if (err)
+			val = 0;
+
+		frq->value = val;
+		frq->disabled = (val >= 2346);
+		frq->fixed = 1;
+	}
+
+	dldwd_unlock(priv);
+	
+	return err;
+}
+
+static int dldwd_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int err = 0;
+	int rate_ctrl = -1;
+	int fixed, upto;
+	int brate;
+	int i;
+
+	dldwd_lock(priv);
+
+	/* Normalise value */
+	brate = rrq->value / 500000;
+
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_LUCENT: /* Lucent style rate */
+		if (! rrq->fixed) {
+			if (brate > 0)
+				brate = -brate;
+			else
+				brate = -22;
+		}
+	
+		for (i = 0; i < NUM_RATES; i++)
+			if (rate_list[i] == brate) {
+				rate_ctrl = i;
+				break;
+			}
+	
+		if ( (rate_ctrl < 1) || (rate_ctrl >= NUM_RATES) )
+			err = -EINVAL;
+		else
+			priv->tx_rate_ctrl = rate_ctrl;
+		break;
+	case FIRMWARE_TYPE_PRISM2: /* Prism II style rate */
+	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
+		switch(brate) {
+		case 0:
+			fixed = 0x0;
+			upto = 0x15;
+			break;
+		case 2:
+			fixed = 0x1;
+			upto = 0x1;
+			break;
+		case 4:
+			fixed = 0x2;
+			upto = 0x3;
+			break;
+		case 11:
+			fixed = 0x4;
+			upto = 0x7;
+			break;
+		case 22:
+			fixed = 0x8;
+			upto = 0x15;
+			break;
+		default:
+			fixed = 0x0;
+			upto = 0x0;
+		}
+		if (rrq->fixed)
+			rate_ctrl = fixed;
+		else
+			rate_ctrl = upto;
+		if (rate_ctrl == 0)
+			err = -EINVAL;
+		else
+			priv->tx_rate_ctrl = rate_ctrl;
+		break;
+	}
+
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	uint16_t val;
+	int brate = 0;
+
+	dldwd_lock(priv);
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_TX_RATE_CTRL, &val);
+	if (err)
+		goto out;
+	
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_LUCENT: /* Lucent style rate */
+		brate = rate_list[val];
+	
+		if (brate < 0) {
+			rrq->fixed = 0;
+
+			err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_TX_RATE, &val);
+			if (err)
+				goto out;
+
+			if (val == 6)
+				brate = 11;
+			else
+				brate = 2*val;
+		} else
+			rrq->fixed = 1;
+		break;
+	case FIRMWARE_TYPE_PRISM2: /* Prism II style rate */
+	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
+		/* Check if auto or fixed (crude approximation) */
+		if((val & 0x1) && (val > 1)) {
+			rrq->fixed = 0;
+
+			err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENT_TX_RATE, &val);
+			if (err)
+				goto out;
+		} else
+			rrq->fixed = 1;
+
+		if(val >= 8)
+			brate = 22;
+		else if(val >= 4)
+			brate = 11;
+		else if(val >= 2)
+			brate = 4;
+		else
+			brate = 2;
+		break;
+	}
+
+	rrq->value = brate * 500000;
+	rrq->disabled = 0;
+
+ out:
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int err = 0;
+
+
+	dldwd_lock(priv);
+
+	if (prq->disabled) {
+		priv->pm_on = 0;
+	} else {
+		switch (prq->flags & IW_POWER_MODE) {
+		case IW_POWER_UNICAST_R:
+			priv->pm_mcast = 0;
+			priv->pm_on = 1;
+			break;
+		case IW_POWER_ALL_R:
+			priv->pm_mcast = 1;
+			priv->pm_on = 1;
+			break;
+		case IW_POWER_ON:
+			/* No flags : but we may have a value - Jean II */
+			break;
+		default:
+			err = -EINVAL;
+		}
+		if (err)
+			goto out;
+		
+		if (prq->flags & IW_POWER_TIMEOUT) {
+			priv->pm_on = 1;
+			priv->pm_timeout = prq->value / 1000;
+		}
+		if (prq->flags & IW_POWER_PERIOD) {
+			priv->pm_on = 1;
+			priv->pm_period = prq->value / 1000;
+		}
+		/* It's valid to not have a value if we are just toggling
+		 * the flags... Jean II */
+		if(!priv->pm_on) {
+			err = -EINVAL;
+			goto out;
+		}			
+	}
+
+ out:
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	uint16_t enable, period, timeout, mcast;
+
+	dldwd_lock(priv);
+	
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_ENABLE, &enable);
+	if (err)
+		goto out;
+
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_PERIOD, &period);
+	if (err)
+		goto out;
+
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_HOLDOVER, &timeout);
+	if (err)
+		goto out;
+
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_PM_MCAST_RX, &mcast);
+	if (err)
+		goto out;
+
+	prq->disabled = !enable;
+	/* Note : by default, display the period */
+	if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
+		prq->flags = IW_POWER_TIMEOUT;
+		prq->value = timeout * 1000;
+	} else {
+		prq->flags = IW_POWER_PERIOD;
+		prq->value = period * 1000;
+	}
+	if (mcast)
+		prq->flags |= IW_POWER_ALL_R;
+	else
+		prq->flags |= IW_POWER_UNICAST_R;
+
+ out:
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+#if WIRELESS_EXT > 10
+static int dldwd_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	uint16_t short_limit, long_limit, lifetime;
+
+	dldwd_lock(priv);
+	
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, &short_limit);
+	if (err)
+		goto out;
+
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT, &long_limit);
+	if (err)
+		goto out;
+
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME, &lifetime);
+	if (err)
+		goto out;
+
+	rrq->disabled = 0;		/* Can't be disabled */
+
+	/* Note : by default, display the retry number */
+	if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+		rrq->flags = IW_RETRY_LIFETIME;
+		rrq->value = lifetime * 1000;	/* ??? */
+	} else {
+		/* By default, display the min number */
+		if ((rrq->flags & IW_RETRY_MAX)) {
+			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+			rrq->value = long_limit;
+		} else {
+			rrq->flags = IW_RETRY_LIMIT;
+			rrq->value = short_limit;
+			if(short_limit != long_limit)
+				rrq->flags |= IW_RETRY_MIN;
+		}
+	}
+
+ out:
+	dldwd_unlock(priv);
+
+	return err;
+}
+#endif /* WIRELESS_EXT > 10 */
+
+static int dldwd_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int val = *( (int *) wrq->u.name );
+	int err = 0;
+
+	dldwd_lock(priv);
+	switch (val) {
+	case 0: /* Try to do IEEE ad-hoc mode */
+		if (! priv->has_ibss) {
+			err = -EINVAL;
+			break;
+		}
+		DEBUG(2, "%s: Prefer IBSS Ad-Hoc mode\n", dev->name);
+		priv->prefer_port3 = 0;
+			
+		break;
+
+	case 1: /* Try to do Lucent proprietary ad-hoc mode */
+		if (! priv->has_port3) {
+			err = -EINVAL;
+			break;
+		}
+		DEBUG(2, "%s: Prefer Ad-Hoc demo mode\n", dev->name);
+		priv->prefer_port3 = 1;
+		break;
+
+	default:
+		err = -EINVAL;
+	}
+
+	if (! err)
+		/* Actually update the mode we are using */
+		set_port_type(priv);
+
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	int *val = (int *)wrq->u.name;
+
+	dldwd_lock(priv);
+	*val = priv->prefer_port3;
+	dldwd_unlock(priv);
+
+	return 0;
+}
+
+/* Spy is used for link quality/strength measurements in Ad-Hoc mode
+ * Jean II */
+static int dldwd_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	struct sockaddr address[IW_MAX_SPY];
+	int number = srq->length;
+	int i;
+	int err = 0;
+
+	/* Check the number of addresses */
+	if (number > IW_MAX_SPY)
+		return -E2BIG;
+
+	/* Get the data in the driver */
+	if (srq->pointer) {
+		if (copy_from_user(address, srq->pointer,
+				   sizeof(struct sockaddr) * number))
+			return -EFAULT;
+	}
+
+	/* Make sure nobody mess with the structure while we do */
+	dldwd_lock(priv);
+
+	/* dldwd_lock() doesn't disable interrupts, so make sure the
+	 * interrupt rx path don't get confused while we copy */
+	priv->spy_number = 0;
+
+	if (number > 0) {
+		/* Extract the addresses */
+		for (i = 0; i < number; i++)
+			memcpy(priv->spy_address[i], address[i].sa_data,
+			       ETH_ALEN);
+		/* Reset stats */
+		memset(priv->spy_stat, 0,
+		       sizeof(struct iw_quality) * IW_MAX_SPY);
+		/* Set number of addresses */
+		priv->spy_number = number;
+	}
+
+	/* Time to show what we have done... */
+	DEBUG(0, "%s: New spy list:\n", dev->name);
+	for (i = 0; i < number; i++) {
+		DEBUG(0, "%s: %d - %02x:%02x:%02x:%02x:%02x:%02x\n",
+		      dev->name, i+1,
+		      priv->spy_address[i][0], priv->spy_address[i][1],
+		      priv->spy_address[i][2], priv->spy_address[i][3],
+		      priv->spy_address[i][4], priv->spy_address[i][5]);
+	}
+
+	/* Now, let the others play */
+	dldwd_unlock(priv);
+
+	return err;
+}
+
+static int dldwd_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
+{
+	dldwd_priv_t *priv = dev->priv;
+	struct sockaddr address[IW_MAX_SPY];
+	struct iw_quality spy_stat[IW_MAX_SPY];
+	int number;
+	int i;
+
+	dldwd_lock(priv);
+
+	number = priv->spy_number;
+	if ((number > 0) && (srq->pointer)) {
+		/* Create address struct */
+		for (i = 0; i < number; i++) {
+			memcpy(address[i].sa_data, priv->spy_address[i],
+			       ETH_ALEN);
+			address[i].sa_family = AF_UNIX;
+		}
+		/* Copy stats */
+		/* In theory, we should disable irqs while copying the stats
+		 * because the rx path migh update it in the middle...
+		 * Bah, who care ? - Jean II */
+		memcpy(&spy_stat, priv->spy_stat,
+		       sizeof(struct iw_quality) * IW_MAX_SPY);
+		for (i=0; i < number; i++)
+			priv->spy_stat[i].updated = 0;
+	}
+
+	dldwd_unlock(priv);
+
+	/* Push stuff to user space */
+	srq->length = number;
+	if(copy_to_user(srq->pointer, address,
+			 sizeof(struct sockaddr) * number))
+		return -EFAULT;
+	if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
+			&spy_stat, sizeof(struct iw_quality) * number))
+		return -EFAULT;
+
+	return 0;
+}
+
+int
+dldwd_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	dldwd_priv_t *priv = dev->priv;
+	struct iwreq *wrq = (struct iwreq *)rq;
+	int err = 0;
+	int changed = 0;
+
+	TRACE_ENTER(dev->name);
+
+	/* In theory, we could allow most of the the SET stuff to be done
+	 * In practice, the laps of time at startup when the card is not
+	 * ready is very short, so why bother...
+	 * Note that hw_ready is different from up/down (ifconfig), when
+	 * the device is not yet up, it is usually already ready...
+	 * Jean II */
+	if (!priv->hw_ready)
+		return -ENODEV;
+
+	switch (cmd) {
+	case SIOCGIWNAME:
+		DEBUG(1, "%s: SIOCGIWNAME\n", dev->name);
+		strcpy(wrq->u.name, "IEEE 802.11-DS");
+		break;
+		
+	case SIOCGIWAP:
+		DEBUG(1, "%s: SIOCGIWAP\n", dev->name);
+		wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+		err = dldwd_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
+		break;
+
+	case SIOCGIWRANGE:
+		DEBUG(1, "%s: SIOCGIWRANGE\n", dev->name);
+		err = dldwd_ioctl_getiwrange(dev, &wrq->u.data);
+		break;
+
+	case SIOCSIWMODE:
+		DEBUG(1, "%s: SIOCSIWMODE\n", dev->name);
+		dldwd_lock(priv);
+		switch (wrq->u.mode) {
+		case IW_MODE_ADHOC:
+			if (! (priv->has_ibss || priv->has_port3) )
+				err = -EINVAL;
+			else {
+				priv->iw_mode = IW_MODE_ADHOC;
+				changed = 1;
+			}
+			break;
+
+		case IW_MODE_INFRA:
+			priv->iw_mode = IW_MODE_INFRA;
+			changed = 1;
+			break;
+
+		default:
+			err = -EINVAL;
+			break;
+		}
+		set_port_type(priv);
+		dldwd_unlock(priv);
+		break;
+
+	case SIOCGIWMODE:
+		DEBUG(1, "%s: SIOCGIWMODE\n", dev->name);
+		dldwd_lock(priv);
+		wrq->u.mode = priv->iw_mode;
+		dldwd_unlock(priv);
+		break;
+
+	case SIOCSIWENCODE:
+		DEBUG(1, "%s: SIOCSIWENCODE\n", dev->name);
+		if (! priv->has_wep) {
+			err = -EOPNOTSUPP;
+			break;
+		}
+
+		err = dldwd_ioctl_setiwencode(dev, &wrq->u.encoding);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWENCODE:
+		DEBUG(1, "%s: SIOCGIWENCODE\n", dev->name);
+		if (! priv->has_wep) {
+			err = -EOPNOTSUPP;
+			break;
+		}
+
+		if (! capable(CAP_NET_ADMIN)) {
+			err = -EPERM;
+			break;
+		}
+
+		err = dldwd_ioctl_getiwencode(dev, &wrq->u.encoding);
+		break;
+
+	case SIOCSIWESSID:
+		DEBUG(1, "%s: SIOCSIWESSID\n", dev->name);
+		err = dldwd_ioctl_setessid(dev, &wrq->u.essid);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWESSID:
+		DEBUG(1, "%s: SIOCGIWESSID\n", dev->name);
+		err = dldwd_ioctl_getessid(dev, &wrq->u.essid);
+		break;
+
+	case SIOCSIWNICKN:
+		DEBUG(1, "%s: SIOCSIWNICKN\n", dev->name);
+		err = dldwd_ioctl_setnick(dev, &wrq->u.data);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWNICKN:
+		DEBUG(1, "%s: SIOCGIWNICKN\n", dev->name);
+		err = dldwd_ioctl_getnick(dev, &wrq->u.data);
+		break;
+
+	case SIOCGIWFREQ:
+		DEBUG(1, "%s: SIOCGIWFREQ\n", dev->name);
+		wrq->u.freq.m = dldwd_hw_get_freq(priv);
+		wrq->u.freq.e = 1;
+		break;
+
+	case SIOCSIWFREQ:
+		DEBUG(1, "%s: SIOCSIWFREQ\n", dev->name);
+		err = dldwd_ioctl_setfreq(dev, &wrq->u.freq);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWSENS:
+		DEBUG(1, "%s: SIOCGIWSENS\n", dev->name);
+		err = dldwd_ioctl_getsens(dev, &wrq->u.sens);
+		break;
+
+	case SIOCSIWSENS:
+		DEBUG(1, "%s: SIOCSIWSENS\n", dev->name);
+		err = dldwd_ioctl_setsens(dev, &wrq->u.sens);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWRTS:
+		DEBUG(1, "%s: SIOCGIWRTS\n", dev->name);
+		wrq->u.rts.value = priv->rts_thresh;
+		wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
+		wrq->u.rts.fixed = 1;
+		break;
+
+	case SIOCSIWRTS:
+		DEBUG(1, "%s: SIOCSIWRTS\n", dev->name);
+		err = dldwd_ioctl_setrts(dev, &wrq->u.rts);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCSIWFRAG:
+		DEBUG(1, "%s: SIOCSIWFRAG\n", dev->name);
+		err = dldwd_ioctl_setfrag(dev, &wrq->u.frag);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWFRAG:
+		DEBUG(1, "%s: SIOCGIWFRAG\n", dev->name);
+		err = dldwd_ioctl_getfrag(dev, &wrq->u.frag);
+		break;
+
+	case SIOCSIWRATE:
+		DEBUG(1, "%s: SIOCSIWRATE\n", dev->name);
+		err = dldwd_ioctl_setrate(dev, &wrq->u.bitrate);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWRATE:
+		DEBUG(1, "%s: SIOCGIWRATE\n", dev->name);
+		err = dldwd_ioctl_getrate(dev, &wrq->u.bitrate);
+		break;
+
+	case SIOCSIWPOWER:
+		DEBUG(1, "%s: SIOCSIWPOWER\n", dev->name);
+		err = dldwd_ioctl_setpower(dev, &wrq->u.power);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCGIWPOWER:
+		DEBUG(1, "%s: SIOCGIWPOWER\n", dev->name);
+		err = dldwd_ioctl_getpower(dev, &wrq->u.power);
+		break;
+
+	case SIOCGIWTXPOW:
+		DEBUG(1, "%s: SIOCGIWTXPOW\n", dev->name);
+		/* The card only supports one tx power, so this is easy */
+		wrq->u.txpower.value = 15; /* dBm */
+		wrq->u.txpower.fixed = 1;
+		wrq->u.txpower.disabled = 0;
+		wrq->u.txpower.flags = IW_TXPOW_DBM;
+		break;
+
+#if WIRELESS_EXT > 10
+	case SIOCSIWRETRY:
+		DEBUG(1, "%s: SIOCSIWRETRY\n", dev->name);
+		err = -EOPNOTSUPP;
+		break;
+
+	case SIOCGIWRETRY:
+		DEBUG(1, "%s: SIOCGIWRETRY\n", dev->name);
+		err = dldwd_ioctl_getretry(dev, &wrq->u.retry);
+		break;
+#endif /* WIRELESS_EXT > 10 */
+
+	case SIOCSIWSPY:
+		DEBUG(1, "%s: SIOCSIWSPY\n", dev->name);
+
+		err = dldwd_ioctl_setspy(dev, &wrq->u.data);
+		break;
+
+	case SIOCGIWSPY:
+		DEBUG(1, "%s: SIOCGIWSPY\n", dev->name);
+
+		err = dldwd_ioctl_getspy(dev, &wrq->u.data);
+		break;
+
+	case SIOCGIWPRIV:
+		DEBUG(1, "%s: SIOCGIWPRIV\n", dev->name);
+		if (wrq->u.data.pointer) {
+			struct iw_priv_args privtab[] = {
+				{ SIOCDEVPRIVATE + 0x0, 0, 0, "force_reset" },
+				{ SIOCDEVPRIVATE + 0x2,
+				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+				  0, "set_port3" },
+				{ SIOCDEVPRIVATE + 0x3, 0,
+				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+				  "get_port3" },
+				{ SIOCDEVPRIVATE + 0x4,
+				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+				  0, "set_preamble" },
+				{ SIOCDEVPRIVATE + 0x5, 0,
+				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+				  "get_preamble" }
+			};
+
+			err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab));
+			if (err)
+				break;
+			
+			wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
+			if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+				err = -EFAULT;
+		}
+		break;
+	       
+	case SIOCDEVPRIVATE + 0x0: /* force_reset */
+		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x0 (force_reset)\n",
+		      dev->name);
+		if (! capable(CAP_NET_ADMIN)) {
+			err = -EPERM;
+			break;
+		}
+		
+		printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
+		dldwd_reset(priv);
+		break;
+
+	case SIOCDEVPRIVATE + 0x2: /* set_port3 */
+		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x2 (set_port3)\n",
+		      dev->name);
+		if (! capable(CAP_NET_ADMIN)) {
+			err = -EPERM;
+			break;
+		}
+
+		err = dldwd_ioctl_setport3(dev, wrq);
+		if (! err)
+			changed = 1;
+		break;
+
+	case SIOCDEVPRIVATE + 0x3: /* get_port3 */
+		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x3 (get_port3)\n",
+		      dev->name);
+		err = dldwd_ioctl_getport3(dev, wrq);
+		break;
+
+	case SIOCDEVPRIVATE + 0x4: /* set_preamble */
+		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x4 (set_preamble)\n",
+		      dev->name);
+		if (! capable(CAP_NET_ADMIN)) {
+			err = -EPERM;
+			break;
+		}
+
+		/* 802.11b has recently defined some short preamble.
+		 * Basically, the Phy header has been reduced in size.
+		 * This increase performance, especially at high rates
+		 * (the preamble is transmitted at 1Mb/s), unfortunately
+		 * this give compatibility troubles... - Jean II */
+		if(priv->has_preamble) {
+			int val = *( (int *) wrq->u.name );
+
+			dldwd_lock(priv);
+			if(val)
+				priv->preamble = 1;
+			else
+				priv->preamble = 0;
+			dldwd_unlock(priv);
+			changed = 1;
+		} else
+			err = -EOPNOTSUPP;
+		break;
+
+	case SIOCDEVPRIVATE + 0x5: /* get_preamble */
+		DEBUG(1, "%s: SIOCDEVPRIVATE + 0x5 (get_preamble)\n",
+		      dev->name);
+		if(priv->has_preamble) {
+			int *val = (int *)wrq->u.name;
+
+			dldwd_lock(priv);
+			*val = priv->preamble;
+			dldwd_unlock(priv);
+		} else
+			err = -EOPNOTSUPP;
+		break;
+
+	default:
+		err = -EOPNOTSUPP;
+	}
+	
+	if (! err && changed && netif_running(dev)) {
+		err = dldwd_reset(priv);
+		if (err) {
+			/* Ouch ! What are we supposed to do ? */
+			printk(KERN_ERR "orinoco_cs: Failed to set parameters on %s\n",
+			       dev->name);
+			netif_stop_queue(dev);
+			dldwd_shutdown(priv);
+			priv->hw_ready = 0;
+		}
+	}		
+
+	TRACE_EXIT(dev->name);
+		
+	return err;
+}
+
+int
+dldwd_change_mtu(struct net_device *dev, int new_mtu)
+{
+	TRACE_ENTER(dev->name);
+
+	if ( (new_mtu < DLDWD_MIN_MTU) || (new_mtu > DLDWD_MAX_MTU) )
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+
+	TRACE_EXIT(dev->name);
+
+	return 0;
+}
+
+static void
+__dldwd_set_multicast_list(struct net_device *dev)
+{
+	dldwd_priv_t *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	int promisc, allmulti, mc_count;
+
+	/* We'll wait until it's ready. Anyway, the network doesn't call us
+	 * here until we are open - Jean II */
+	if (!priv->hw_ready)
+		return;
+
+
+	TRACE_ENTER(dev->name);
+
+	DEBUG(3, "dev->flags=0x%x, priv->promiscuous=%d, dev->mc_count=%d priv->mc_count=%d\n",
+	      dev->flags, priv->promiscuous, dev->mc_count, priv->mc_count);
+
+	/* The Hermes doesn't seem to have an allmulti mode, so we go
+	 * into promiscuous mode and let the upper levels deal. */
+	if ( (dev->flags & IFF_PROMISC) ) {
+		promisc = 1;
+		allmulti = 0;
+		mc_count = 0;
+	} else if ( (dev->flags & IFF_ALLMULTI) ||
+		    (dev->mc_count > HERMES_MAX_MULTICAST) ) {
+		promisc = 0;
+		allmulti = 1;
+		mc_count = HERMES_MAX_MULTICAST;
+	} else {
+		promisc = 0;
+		allmulti = 0;
+		mc_count = dev->mc_count;
+	}
+
+	DEBUG(3, "promisc=%d mc_count=%d\n",
+	      promisc, mc_count);
+
+	if (promisc != priv->promiscuous) { /* Don't touch the hardware if we don't have to */
+		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNF_PROMISCUOUS,
+					   promisc);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting promiscuity to %d.\n",
+			       dev->name, err, promisc);
+		} else 
+			priv->promiscuous = promisc;
+	}
+
+	if (allmulti) {
+		/* FIXME: This method of doing allmulticast reception
+		   comes from the NetBSD driver. Haven't actually
+		   tested whether it works or not. */
+		hermes_multicast_t mclist;
+
+		memset(&mclist, 0, sizeof(mclist));
+		err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNF_MULTICAST_LIST, &mclist);
+		if (err)
+			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
+			       dev->name, err);
+		else
+			priv->allmulti = 1;
+		       
+	} else if (mc_count || (! mc_count && priv->mc_count) ) {
+		struct dev_mc_list *p = dev->mc_list;
+		hermes_multicast_t mclist;
+		int i;
+
+		for (i = 0; i < mc_count; i++) {
+			/* First some paranoid checks */
+			if (! p) {
+				printk(KERN_ERR "%s: Multicast list shorter than mc_count.\n",
+				       dev->name);
+				break;
+			}
+			if (p->dmi_addrlen != ETH_ALEN) {
+
+				printk(KERN_ERR "%s: Bad address size (%d) in multicast list.\n",
+				       dev->name, p->dmi_addrlen);
+				break;
+			}
+
+			memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
+			p = p->next;
+		}
+
+		/* More paranoia */
+		if (p)
+			printk(KERN_ERR "%s: Multicast list longer than mc_count.\n",
+			       dev->name);
+
+		priv->mc_count = i;			
+
+		DEBUG(3, "priv->mc_count = %d\n", priv->mc_count);
+
+		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNF_MULTICAST_LIST,
+				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
+				       &mclist);
+		if (err)
+			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
+			       dev->name, err);
+		else
+			priv->allmulti = 0;
+	}
+
+	/* Since we can set the promiscuous flag when it wasn't asked
+	   for, make sure the net_device knows about it. */
+	if (priv->promiscuous)
+		dev->flags |= IFF_PROMISC;
+	else
+		dev->flags &= ~IFF_PROMISC;
+
+	if (priv->allmulti)
+		dev->flags |= IFF_ALLMULTI;
+	else
+		dev->flags &= ~IFF_ALLMULTI;
+
+	TRACE_EXIT(dev->name);
+}
+
+/*
+ * procfs stuff
+ */
+
+static struct proc_dir_entry *dir_base = NULL;
+
+/*
+ * This function updates the total amount of data printed so far. It then
+ * determines if the amount of data printed into a buffer  has reached the
+ * offset requested. If it hasn't, then the buffer is shifted over so that
+ * the next bit of data can be printed over the old bit. If the total
+ * amount printed so far exceeds the total amount requested, then this
+ * function returns 1, otherwise 0.
+ */
+static int 
+
+shift_buffer(char *buffer, int requested_offset, int requested_len,
+	     int *total, int *slop, char **buf)
+{
+	int printed;
+	
+	printed = *buf - buffer;
+	if (*total + printed <= requested_offset) {
+		*total += printed;
+		*buf = buffer;
+	}
+	else {
+		if (*total < requested_offset) {
+			*slop = requested_offset - *total;
+		}
+		*total = requested_offset + printed - *slop;
+	}
+	if (*total > requested_offset + requested_len) {
+		return 1;
+	}
+	else {
+		return 0;
+	}
+}
+
+/*
+ * This function calculates the actual start of the requested data
+ * in the buffer. It also calculates actual length of data returned,
+ * which could be less that the amount of data requested.
+ */
+#define PROC_BUFFER_SIZE 4096
+#define PROC_SAFE_SIZE 3072
+
+static int
+calc_start_len(char *buffer, char **start, int requested_offset,
+	       int requested_len, int total, char *buf)
+{
+	int return_len, buffer_len;
+	
+	buffer_len = buf - buffer;
+	if (buffer_len >= PROC_BUFFER_SIZE - 1) {
+		printk(KERN_ERR "calc_start_len: exceeded /proc buffer size\n");
+	}
+	
+	/*
+	 * There may be bytes before and after the
+	 * chunk that was actually requested.
+	 */
+	return_len = total - requested_offset;
+	if (return_len < 0) {
+		return_len = 0;
+	}
+	*start = buf - return_len;
+	if (return_len > requested_len) {
+		return_len = requested_len;
+	}
+	return return_len;
+}
+
+static int
+dldwd_proc_get_hermes_regs(char *page, char **start, off_t requested_offset,
+			   int requested_len, int *eof, void *data)
+{
+	dldwd_priv_t *dev = (dldwd_priv_t *)data;
+	hermes_t *hw = &dev->hw;
+	char *buf;
+	int total = 0, slop = 0;
+
+	/* Hum, in this case hardware register are probably not readable... */
+	if (!dev->hw_ready)
+		return -ENODEV;
+
+	buf = page;
+
+#define DHERMESREG(name) buf += sprintf(buf, "%-16s: %04x\n", #name, hermes_read_regn(hw, name))
+
+	DHERMESREG(CMD);
+	DHERMESREG(PARAM0);
+	DHERMESREG(PARAM1);
+	DHERMESREG(PARAM2);
+	DHERMESREG(STATUS);
+	DHERMESREG(RESP0);
+	DHERMESREG(RESP1);
+	DHERMESREG(RESP2);
+	DHERMESREG(INFOFID);
+	DHERMESREG(RXFID);
+	DHERMESREG(ALLOCFID);
+	DHERMESREG(TXCOMPLFID);
+	DHERMESREG(SELECT0);
+	DHERMESREG(OFFSET0);
+	DHERMESREG(SELECT1);
+	DHERMESREG(OFFSET1);
+	DHERMESREG(EVSTAT);
+	DHERMESREG(INTEN);
+	DHERMESREG(EVACK);
+	DHERMESREG(CONTROL);
+	DHERMESREG(SWSUPPORT0);
+	DHERMESREG(SWSUPPORT1);
+	DHERMESREG(SWSUPPORT2);
+	DHERMESREG(AUXPAGE);
+	DHERMESREG(AUXOFFSET);
+	DHERMESREG(AUXDATA);
+#undef DHERMESREG
+
+	shift_buffer(page, requested_offset, requested_len, &total,
+		     &slop, &buf);
+	return calc_start_len(page, start, requested_offset, requested_len,
+			      total, buf);
+}
+
+struct {
+	uint16_t rid;
+	char *name;
+	int minlen, maxlen;
+	int displaytype;
+#define DISPLAY_WORDS	0
+#define DISPLAY_BYTES	1
+#define DISPLAY_STRING	2
+} record_table[] = {
+#define RTCNFENTRY(name, type) { HERMES_RID_CNF_##name, #name, 0, LTV_BUF_SIZE, type }
+	RTCNFENTRY(PORTTYPE, DISPLAY_WORDS),
+	RTCNFENTRY(MACADDR, DISPLAY_BYTES),
+	RTCNFENTRY(DESIRED_SSID, DISPLAY_STRING),
+	RTCNFENTRY(CHANNEL, DISPLAY_WORDS),
+	RTCNFENTRY(OWN_SSID, DISPLAY_STRING),
+	RTCNFENTRY(SYSTEM_SCALE, DISPLAY_WORDS),
+	RTCNFENTRY(MAX_DATA_LEN, DISPLAY_WORDS),
+	RTCNFENTRY(PM_ENABLE, DISPLAY_WORDS),
+	RTCNFENTRY(PM_MCAST_RX, DISPLAY_WORDS),
+	RTCNFENTRY(PM_PERIOD, DISPLAY_WORDS),
+	RTCNFENTRY(NICKNAME, DISPLAY_STRING),
+	RTCNFENTRY(WEP_ON, DISPLAY_WORDS),
+	RTCNFENTRY(MWO_ROBUST, DISPLAY_WORDS),
+	RTCNFENTRY(MULTICAST_LIST, DISPLAY_BYTES),
+	RTCNFENTRY(CREATEIBSS, DISPLAY_WORDS),
+	RTCNFENTRY(FRAG_THRESH, DISPLAY_WORDS),
+	RTCNFENTRY(RTS_THRESH, DISPLAY_WORDS),
+	RTCNFENTRY(TX_RATE_CTRL, DISPLAY_WORDS),
+	RTCNFENTRY(PROMISCUOUS, DISPLAY_WORDS),
+	RTCNFENTRY(KEYS, DISPLAY_BYTES),
+	RTCNFENTRY(TX_KEY, DISPLAY_WORDS),
+	RTCNFENTRY(TICKTIME, DISPLAY_WORDS),
+	RTCNFENTRY(PRISM2_TX_KEY, DISPLAY_WORDS),
+	RTCNFENTRY(PRISM2_KEY0, DISPLAY_BYTES),
+	RTCNFENTRY(PRISM2_KEY1, DISPLAY_BYTES),
+	RTCNFENTRY(PRISM2_KEY2, DISPLAY_BYTES),
+	RTCNFENTRY(PRISM2_KEY3, DISPLAY_BYTES),
+	RTCNFENTRY(PRISM2_WEP_ON, DISPLAY_WORDS),
+#undef RTCNFENTRY
+#define RTINFENTRY(name,type) { HERMES_RID_##name, #name, 0, LTV_BUF_SIZE, type }
+	RTINFENTRY(CHANNEL_LIST, DISPLAY_WORDS),
+	RTINFENTRY(STAIDENTITY, DISPLAY_WORDS),
+	RTINFENTRY(CURRENT_SSID, DISPLAY_STRING),
+	RTINFENTRY(CURRENT_BSSID, DISPLAY_BYTES),
+	RTINFENTRY(COMMSQUALITY, DISPLAY_WORDS),
+	RTINFENTRY(CURRENT_TX_RATE, DISPLAY_WORDS),
+	RTINFENTRY(WEP_AVAIL, DISPLAY_WORDS),
+	RTINFENTRY(CURRENT_CHANNEL, DISPLAY_WORDS),
+	RTINFENTRY(DATARATES, DISPLAY_BYTES),
+#undef RTINFENTRY
+};
+#define NUM_RIDS ( sizeof(record_table) / sizeof(record_table[0]) )
+
+static int
+dldwd_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
+			   int requested_len, int *eof, void *data)
+{
+	dldwd_priv_t *dev = (dldwd_priv_t *)data;
+	hermes_t *hw = &dev->hw;
+	char *buf;
+	int total = 0, slop = 0;
+	int i;
+	uint16_t length;
+	int err;
+
+	/* Hum, in this case hardware register are probably not readable... */
+	if (!dev->hw_ready)
+		return -ENODEV;
+		
+	buf = page;
+
+	/* print out all the config RIDs */
+	for (i = 0; i < NUM_RIDS; i++) {
+		uint16_t rid = record_table[i].rid;
+		int minlen = record_table[i].minlen;
+		int maxlen = record_table[i].maxlen;
+		int len;
+		uint8_t *val8;
+		uint16_t *val16;
+		int j;
+
+		val8 = kmalloc(maxlen + 2, GFP_KERNEL);
+		if (! val8)
+			return -ENOMEM;
+
+		err = hermes_read_ltv(hw, USER_BAP, rid, maxlen,
+				      &length, val8);
+		if (err) {
+			DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid);
+			continue;
+		}
+		val16 = (uint16_t *)val8;
+
+		buf += sprintf(buf, "%-15s (0x%04x): length=%d (%d bytes)\tvalue=", record_table[i].name,
+			       rid, length, (length-1)*2);
+		len = MIN( MAX(minlen, (length-1)*2), maxlen);
+
+		switch (record_table[i].displaytype) {
+		case DISPLAY_WORDS:
+			for (j = 0; j < len / 2; j++) {
+				buf += sprintf(buf, "%04X-", le16_to_cpu(val16[j]));
+			}
+			buf--;
+			break;
+
+		case DISPLAY_BYTES:
+		default:
+			for (j = 0; j < len; j++) {
+				buf += sprintf(buf, "%02X:", val8[j]);
+			}
+			buf--;
+			break;
+
+		case DISPLAY_STRING:
+			len = MIN(len, le16_to_cpu(val16[0])+2);
+			val8[len] = '\0';
+			buf += sprintf(buf, "\"%s\"", (char *)&val16[1]);
+			break;
+		}
+
+		buf += sprintf(buf, "\n");
+
+		kfree(val8);
+
+		if (shift_buffer(page, requested_offset, requested_len,
+				 &total, &slop, &buf))
+			break;
+
+		if ( (buf - page) > PROC_SAFE_SIZE )
+			break;
+	}
+
+	return calc_start_len(page, start, requested_offset, requested_len,
+			      total, buf);
+}
+
+/* initialise the /proc subsystem for the hermes driver, creating the
+ * separate entries */
+static int
+dldwd_proc_init(void)
+{
+	int err = 0;
+
+	TRACE_ENTER("dldwd");
+
+	/* create the directory for it to sit in */
+	dir_base = create_proc_entry("hermes", S_IFDIR, &proc_root);
+	if (dir_base == NULL) {
+		printk(KERN_ERR "Unable to initialise /proc/hermes.\n");
+		dldwd_proc_cleanup();
+		err = -ENOMEM;
+	}
+
+	TRACE_EXIT("dldwd");
+
+	return err;
+}
+
+int
+dldwd_proc_dev_init(dldwd_priv_t *dev)
+{
+	struct net_device *ndev = &dev->ndev;
+
+	dev->dir_dev = NULL;
+	/* create the directory for it to sit in */
+	dev->dir_dev = create_proc_entry(ndev->name, S_IFDIR | S_IRUGO | S_IXUGO,
+					 dir_base);
+	if (dev->dir_dev == NULL) {
+		printk(KERN_ERR "Unable to initialise /proc/hermes/%s.\n",  ndev->name);
+		goto fail;
+	}
+
+	dev->dir_regs = NULL;
+	dev->dir_regs = create_proc_read_entry("regs", S_IFREG | S_IRUGO,
+					       dev->dir_dev, dldwd_proc_get_hermes_regs, dev);
+	if (dev->dir_regs == NULL) {
+		printk(KERN_ERR "Unable to initialise /proc/hermes/%s/regs.\n",  ndev->name);
+		goto fail;
+	}
+
+	dev->dir_recs = NULL;
+	dev->dir_recs = create_proc_read_entry("recs", S_IFREG | S_IRUGO,
+					       dev->dir_dev, dldwd_proc_get_hermes_recs, dev);
+	if (dev->dir_recs == NULL) {
+		printk(KERN_ERR "Unable to initialise /proc/hermes/%s/recs.\n",  ndev->name);
+		goto fail;
+	}
+
+	return 0;
+ fail:
+	dldwd_proc_dev_cleanup(dev);
+	return -ENOMEM;
+}
+
+void
+dldwd_proc_dev_cleanup(dldwd_priv_t *priv)
+{
+	struct net_device *ndev = &priv->ndev;
+
+	if (priv->dir_regs) {
+		remove_proc_entry("regs", priv->dir_dev);
+		priv->dir_regs = NULL;
+	}		
+	if (priv->dir_recs) {
+		remove_proc_entry("recs", priv->dir_dev);
+		priv->dir_recs = NULL;
+	}		
+	if (priv->dir_dev) {
+		remove_proc_entry(ndev->name, dir_base);
+		priv->dir_dev = NULL;
+	}
+}
+
+static void
+dldwd_proc_cleanup(void)
+{
+	TRACE_ENTER("dldwd");
+
+	if (dir_base) {
+		remove_proc_entry("hermes", &proc_root);
+		dir_base = NULL;
+	}
+	
+	TRACE_EXIT("dldwd");
+}
+
+int
+dldwd_setup(dldwd_priv_t* priv)
+{
+	struct net_device *ndev = &priv->ndev;;
+
+	spin_lock_init(&priv->lock);
+
+	/* Set up the net_device */
+	ether_setup(ndev);
+	ndev->priv = priv;
+
+	/* Setup up default routines */
+	ndev->init = dldwd_init;
+	ndev->open = NULL;		/* Caller *must* override */
+	ndev->stop = NULL;
+	ndev->hard_start_xmit = dldwd_xmit;
+	ndev->tx_timeout = dldwd_tx_timeout;
+	ndev->watchdog_timeo = 4*HZ; /* 4 second timeout */
+
+	ndev->get_stats = dldwd_get_stats;
+	ndev->get_wireless_stats = dldwd_get_wireless_stats;
+
+	ndev->do_ioctl = dldwd_ioctl;
+
+	ndev->change_mtu = dldwd_change_mtu;
+	ndev->set_multicast_list = dldwd_set_multicast_list;
+
+	netif_stop_queue(ndev);
+
+	return 0;
+}
+
+#ifdef ORINOCO_DEBUG
+EXPORT_SYMBOL(dldwd_debug);
+#endif
+EXPORT_SYMBOL(dldwd_init);
+EXPORT_SYMBOL(dldwd_xmit);
+EXPORT_SYMBOL(dldwd_tx_timeout);
+EXPORT_SYMBOL(dldwd_ioctl);
+EXPORT_SYMBOL(dldwd_change_mtu);
+EXPORT_SYMBOL(dldwd_set_multicast_list);
+EXPORT_SYMBOL(dldwd_shutdown);
+EXPORT_SYMBOL(dldwd_reset);
+EXPORT_SYMBOL(dldwd_setup);
+EXPORT_SYMBOL(dldwd_proc_dev_init);
+EXPORT_SYMBOL(dldwd_proc_dev_cleanup);
+EXPORT_SYMBOL(dldwd_interrupt);
+
+static int __init init_dldwd(void)
+{
+	int err;
+
+	err = dldwd_proc_init();
+
+	printk(KERN_INFO "%s\n", version);
+
+	return 0;
+}
+
+static void __exit exit_dldwd(void)
+{
+	dldwd_proc_cleanup();
+}
+
+module_init(init_dldwd);
+module_exit(exit_dldwd);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/orinoco.h linux/drivers/net/wireless/orinoco.h
--- v2.4.4/linux/drivers/net/wireless/orinoco.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/orinoco.h	Mon May  7 19:42:14 2001
@@ -0,0 +1,145 @@
+/* orinoco.h
+ * 
+ * Common definitions to all pieces of the various orinoco
+ * drivers
+ */
+
+#ifndef _ORINOCO_H
+#define _ORINOCO_H
+
+/* To enable debug messages */
+//#define ORINOCO_DEBUG		3
+
+#if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
+#error "orinoco_cs requires Wireless extensions v10 or later."
+#endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */
+#define WIRELESS_SPY		// enable iwspy support
+
+
+#define DLDWD_MIN_MTU		256
+#define DLDWD_MAX_MTU		(HERMES_FRAME_LEN_MAX - ENCAPS_OVERHEAD)
+
+#define LTV_BUF_SIZE		128
+#define USER_BAP		0
+#define IRQ_BAP			1
+#define DLDWD_MACPORT		0
+#define IRQ_LOOP_MAX		10
+#define TX_NICBUF_SIZE		2048
+#define TX_NICBUF_SIZE_BUG	1585		/* Bug in Intel firmware */
+#define MAX_KEYS		4
+#define MAX_KEY_SIZE		14
+#define LARGE_KEY_SIZE		13
+#define SMALL_KEY_SIZE		5
+#define MAX_FRAME_SIZE		2304
+
+typedef struct dldwd_key {
+	uint16_t len;
+	char data[MAX_KEY_SIZE];
+} __attribute__ ((packed)) dldwd_key_t;
+
+typedef dldwd_key_t dldwd_keys_t[MAX_KEYS];
+
+/*====================================================================*/
+
+
+typedef struct dldwd_priv {
+	void* card;	/* Pointer to card dependant structure */
+
+	spinlock_t lock;
+	long state;
+#define DLDWD_STATE_INIRQ 0
+#define DLDWD_STATE_DOIRQ 1
+	int hw_ready;	/* HW may be suspended by platform */
+
+	/* Net device stuff */
+	struct net_device ndev;
+	struct net_device_stats stats;
+	struct iw_statistics wstats;
+
+
+	/* Hardware control variables */
+	hermes_t hw;
+	uint16_t txfid;
+
+	/* Capabilities of the hardware/firmware */
+	hermes_identity_t firmware_info;
+	int firmware_type;
+#define FIRMWARE_TYPE_LUCENT 1
+#define FIRMWARE_TYPE_PRISM2 2
+#define FIRMWARE_TYPE_SYMBOL 3
+	int has_ibss, has_port3, prefer_port3, has_ibss_any;
+	int has_wep, has_big_wep;
+	int has_mwo;
+	int has_pm;
+	int has_preamble;
+	int broken_reset, broken_allocate;
+	uint16_t channel_mask;
+
+	/* Current configuration */
+	uint32_t iw_mode;
+	int port_type, allow_ibss;
+	uint16_t wep_on, wep_restrict, tx_key;
+	dldwd_keys_t keys;
+ 	char nick[IW_ESSID_MAX_SIZE+1];
+	char desired_essid[IW_ESSID_MAX_SIZE+1];
+	uint16_t frag_thresh, mwo_robust;
+	uint16_t channel;
+	uint16_t ap_density, rts_thresh;
+	uint16_t tx_rate_ctrl;
+	uint16_t pm_on, pm_mcast, pm_period, pm_timeout;
+	uint16_t preamble;
+
+	int promiscuous, allmulti, mc_count;
+
+#ifdef WIRELESS_SPY
+	int			spy_number;
+	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
+	struct iw_quality	spy_stat[IW_MAX_SPY];
+#endif
+
+	/* /proc based debugging stuff */
+	struct proc_dir_entry *dir_dev;
+	struct proc_dir_entry *dir_regs;
+	struct proc_dir_entry *dir_recs;
+} dldwd_priv_t;
+
+/*====================================================================*/
+
+extern int dldwd_debug;
+extern struct list_head dldwd_instances;
+
+#ifdef ORINOCO_DEBUG
+#define DEBUG(n, args...) if (dldwd_debug>(n)) printk(KERN_DEBUG args)
+#define DEBUGMORE(n, args...) do { if (dldwd_debug>(n)) printk(args); } while (0)
+#else
+#define DEBUG(n, args...) do { } while (0)
+#define DEBUGMORE(n, args...) do { } while (0)
+#endif	/* ORINOCO_DEBUG */
+
+#define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
+#define TRACE_EXIT(devname)  DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
+
+#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+
+#define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) )
+
+/* struct net_device methods */
+extern int dldwd_init(struct net_device *dev);
+extern int dldwd_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void dldwd_tx_timeout(struct net_device *dev);
+
+extern int dldwd_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+extern int dldwd_change_mtu(struct net_device *dev, int new_mtu);
+extern void dldwd_set_multicast_list(struct net_device *dev);
+
+/* utility routines */
+extern void dldwd_shutdown(dldwd_priv_t *dev);
+extern int dldwd_reset(dldwd_priv_t *dev);
+extern int dldwd_setup(dldwd_priv_t* priv);
+extern int dldwd_proc_dev_init(dldwd_priv_t *dev);
+extern void dldwd_proc_dev_cleanup(dldwd_priv_t *priv);
+extern void dldwd_interrupt(int irq, void * dev_id, struct pt_regs *regs);
+
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/orinoco_cs.c linux/drivers/net/wireless/orinoco_cs.c
--- v2.4.4/linux/drivers/net/wireless/orinoco_cs.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/orinoco_cs.c	Mon May  7 19:42:14 2001
@@ -0,0 +1,789 @@
+/* orinoco_cs.c 0.05	- (formerly known as dldwd_cs.c)
+ *
+ * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
+ * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
+ * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
+ * It should also be usable on various Prism II based cards such as the
+ * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
+ * cards such as the 3Com AirConnect and Ericsson WLAN.
+ * 
+ * Copyright notice & release notes in file orinoco.c
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/list.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/bus_ops.h>
+
+#include "hermes.h"
+#include "orinoco.h"
+
+/* Pcmcia specific structure */
+typedef struct dldwd_card {
+	dev_link_t link;
+	dev_node_t node;
+	int instance;
+
+	/* Common structure (fully included), see orinoco.h */
+	struct dldwd_priv  priv;
+} dldwd_card_t;
+
+static char *version = "orinoco_cs.c 0.05 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* The old way: bit map of interrupts to choose from */
+/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
+static uint irq_mask = 0xdeb8;
+/* Newer, simpler way of listing specific interrupts */
+static int irq_list[4] = { -1 };
+/* Do a Pcmcia soft reset (may help some cards) */
+static int reset_cor = 0;
+/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
+ * don't have any CIS entry for it. This workaround it... */
+static int ignore_cis_vcc = 0;
+
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+MODULE_PARM(reset_cor, "i");
+MODULE_PARM(ignore_cis_vcc, "i");
+
+/*
+ * Function prototypes
+ */
+
+/* struct net_device methods */
+static int dldwd_cs_open(struct net_device *dev);
+static int dldwd_cs_stop(struct net_device *dev);
+
+/* PCMCIA gumpf */
+static void dldwd_cs_config(dev_link_t * link);
+static void dldwd_cs_release(u_long arg);
+static int dldwd_cs_event(event_t event, int priority,
+		       event_callback_args_t * args);
+
+static dev_link_t *dldwd_cs_attach(void);
+static void dldwd_cs_detach(dev_link_t *);
+
+/*
+   The dev_info variable is the "key" that is used to match up this
+   device driver with appropriate cards, through the card configuration
+   database.
+*/
+
+static dev_info_t dev_info = "orinoco_cs";
+
+/*
+   A linked list of "instances" of the dummy device.  Each actual
+   PCMCIA card corresponds to one device instance, and is described
+   by one dev_link_t structure (defined in ds.h).
+
+   You may not want to use a linked list for this -- for example, the
+   memory card driver uses an array of dev_link_t pointers, where minor
+   device numbers are used to derive the corresponding array index.
+*/
+
+static dev_link_t *dev_list = NULL;
+static int num_instances = 0;
+
+/*====================================================================*/
+
+static void
+cs_error(client_handle_t handle, int func, int ret)
+{
+	error_info_t err = { func, ret };
+	CardServices(ReportError, handle, &err);
+}
+
+static int
+dldwd_cs_open(struct net_device *dev)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	dldwd_card_t* card = (dldwd_card_t *)priv->card;
+	dev_link_t *link = &card->link;
+	int err;
+	
+	TRACE_ENTER(priv->ndev.name);
+
+	link->open++;
+	netif_device_attach(dev);
+	
+	err = dldwd_reset(priv);
+	if (err)
+		dldwd_cs_stop(dev);
+	else
+		netif_start_queue(dev);
+
+	TRACE_EXIT(priv->ndev.name);
+
+	return err;
+}
+
+static int
+dldwd_cs_stop(struct net_device *dev)
+{
+	dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv;
+	dldwd_card_t* card = (dldwd_card_t *)priv->card;
+	dev_link_t *link = &card->link;
+
+	TRACE_ENTER(priv->ndev.name);
+
+	netif_stop_queue(dev);
+
+	dldwd_shutdown(priv);
+	
+	link->open--;
+
+	if (link->state & DEV_STALE_CONFIG)
+		mod_timer(&link->release, jiffies + HZ/20);
+	
+	TRACE_EXIT(priv->ndev.name);
+	
+	return 0;
+}
+
+/*======================================================================
+  dldwd_cs_attach() creates an "instance" of the driver, allocating
+  local data structures for one device.  The device is registered
+  with Card Services.
+  
+  The dev_link structure is initialized, but we don't actually
+  configure the card at this point -- we wait until we receive a
+  card insertion event.
+  ======================================================================*/
+
+static dev_link_t *
+dldwd_cs_attach(void)
+{
+	dldwd_card_t *card;
+	dldwd_priv_t *priv;
+	dev_link_t *link;
+	struct net_device *ndev;
+	client_reg_t client_reg;
+	int ret, i;
+
+	TRACE_ENTER("dldwd");
+
+	/* Allocate space for private device-specific data */
+	card = kmalloc(sizeof(*card), GFP_KERNEL);
+	if (! card) {
+		link = NULL;
+		goto out;
+	}
+	memset(card, 0, sizeof(*card));
+
+	/* Link both structure together */
+	priv = &(card->priv);
+	priv->card = card;
+	card->instance = num_instances++; /* FIXME: Racy? */
+	link = &card->link;
+	ndev = &priv->ndev;
+	link->priv = priv;
+
+	/* Initialize the dev_link_t structure */
+	link->release.function = &dldwd_cs_release;
+	link->release.data = (u_long) link;
+
+	/* Interrupt setup */
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+	link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+	if (irq_list[0] == -1)
+		link->irq.IRQInfo2 = irq_mask;
+	else
+		for (i = 0; i < 4; i++)
+			link->irq.IRQInfo2 |= 1 << irq_list[i];
+	link->irq.Handler = NULL;
+
+	/*
+	   General socket configuration defaults can go here.  In this
+	   client, we assume very little, and rely on the CIS for almost
+	   everything.  In most clients, many details (i.e., number, sizes,
+	   and attributes of IO windows) are fixed by the nature of the
+	   device, and can be hard-wired here.
+	 */
+	link->conf.Attributes = 0;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+
+	/* Setup the common part */
+	if(dldwd_setup(priv) < 0) {
+		kfree(card);
+		return NULL;
+	}
+
+	/* Overrides */
+	ndev->open = dldwd_cs_open;
+	ndev->stop = dldwd_cs_stop;
+
+	/* Register with Card Services */
+	link->next = dev_list;
+	dev_list = link;
+	client_reg.dev_info = &dev_info;
+	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+	client_reg.EventMask =
+	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+	client_reg.event_handler = &dldwd_cs_event;
+	client_reg.Version = 0x0210;
+	client_reg.event_callback_args.client_data = link;
+	ret = CardServices(RegisterClient, &link->handle, &client_reg);
+	if (ret != CS_SUCCESS) {
+		cs_error(link->handle, RegisterClient, ret);
+		dldwd_cs_detach(link);
+		link = NULL;
+		goto out;
+	}
+
+ out:
+	TRACE_EXIT("dldwd");
+	return link;
+}				/* dldwd_cs_attach */
+
+/*======================================================================
+  This deletes a driver "instance".  The device is de-registered
+  with Card Services.  If it has been released, all local data
+  structures are freed.  Otherwise, the structures will be freed
+  when the device is released.
+  ======================================================================*/
+
+static void
+dldwd_cs_detach(dev_link_t * link)
+{
+	dev_link_t **linkp;
+	dldwd_priv_t *priv = link->priv;
+
+	TRACE_ENTER("dldwd");
+
+	/* Locate device structure */
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link)
+			break;
+	if (*linkp == NULL)
+		goto out;
+
+	/*
+	   If the device is currently configured and active, we won't
+	   actually delete it yet.  Instead, it is marked so that when
+	   the release() function is called, that will trigger a proper
+	   detach().
+	 */
+	if (link->state & DEV_CONFIG) {
+#ifdef PCMCIA_DEBUG
+		printk(KERN_DEBUG "orinoco_cs: detach postponed, '%s' "
+		       "still locked\n", link->dev->dev_name);
+#endif
+		link->state |= DEV_STALE_LINK;
+		goto out;
+	}
+
+	/* Break the link with Card Services */
+	if (link->handle)
+		CardServices(DeregisterClient, link->handle);
+
+	/* Unlink device structure, and free it */
+	*linkp = link->next;
+	DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev);
+	if (link->dev) {
+		DEBUG(0, "orinoco_cs: About to unregister net device %p\n",
+		      &priv->ndev);
+		unregister_netdev(&priv->ndev);
+	}
+	kfree(priv->card);
+
+	num_instances--; /* FIXME: Racy? */
+
+ out:
+	TRACE_EXIT("dldwd");
+}				/* dldwd_cs_detach */
+
+/*
+ * Do a soft reset of the Pcmcia card using the Configuration Option Register
+ * Can't do any harm, and actually may do some good on some cards...
+ */
+static int
+dldwd_cs_cor_reset(dev_link_t *link)
+{
+	conf_reg_t reg;
+	u_long default_cor; 
+
+	/* Save original COR value */
+	reg.Function = 0;
+	reg.Action = CS_READ;
+	reg.Offset = CISREG_COR;
+	reg.Value = 0;
+	CardServices(AccessConfigurationRegister, link->handle, &reg);
+	default_cor = reg.Value;
+
+	DEBUG(2, "dldwd : dldwd_cs_cor_reset() : cor=0x%lX\n", default_cor);
+
+	/* Soft-Reset card */
+	reg.Action = CS_WRITE;
+	reg.Offset = CISREG_COR;
+	reg.Value = (default_cor | COR_SOFT_RESET);
+	CardServices(AccessConfigurationRegister, link->handle, &reg);
+
+	/* Wait until the card has acknowledged our reset */
+	mdelay(1);
+
+	/* Restore original COR configuration index */
+	reg.Value = (default_cor & COR_CONFIG_MASK);
+	CardServices(AccessConfigurationRegister, link->handle, &reg);
+
+	/* Wait until the card has finished restarting */
+	mdelay(1);
+
+	return(0);
+}
+
+/*======================================================================
+  dldwd_cs_config() is scheduled to run after a CARD_INSERTION event
+  is received, to configure the PCMCIA socket, and to make the
+  device available to the system.
+  ======================================================================*/
+
+#define CS_CHECK(fn, args...) \
+while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
+
+#define CFG_CHECK(fn, args...) \
+if (CardServices(fn, args) != 0) goto next_entry
+
+static void
+dldwd_cs_config(dev_link_t * link)
+{
+	client_handle_t handle = link->handle;
+	dldwd_priv_t *priv = link->priv;
+	dldwd_card_t *card = (dldwd_card_t *)priv->card;
+	hermes_t *hw = &priv->hw;
+	struct net_device *ndev = &priv->ndev;
+	tuple_t tuple;
+	cisparse_t parse;
+	int last_fn, last_ret;
+	u_char buf[64];
+	config_info_t conf;
+	cistpl_cftable_entry_t dflt = { 0 };
+	cisinfo_t info;
+
+	TRACE_ENTER("dldwd");
+
+	CS_CHECK(ValidateCIS, handle, &info);
+
+	/*
+	   This reads the card's CONFIG tuple to find its configuration
+	   registers.
+	 */
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	tuple.Attributes = 0;
+	tuple.TupleData = buf;
+	tuple.TupleDataMax = sizeof(buf);
+	tuple.TupleOffset = 0;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	CS_CHECK(GetTupleData, handle, &tuple);
+	CS_CHECK(ParseTuple, handle, &tuple, &parse);
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+
+	/* Configure card */
+	link->state |= DEV_CONFIG;
+
+	/* Look up the current Vcc */
+	CS_CHECK(GetConfigurationInfo, handle, &conf);
+	link->conf.Vcc = conf.Vcc;
+
+	DEBUG(0, "dldwd_cs_config: ConfigBase = 0x%x link->conf.Vcc = %d\n", 
+	      link->conf.ConfigBase, link->conf.Vcc);
+
+	/*
+	   In this loop, we scan the CIS for configuration table entries,
+	   each of which describes a valid card configuration, including
+	   voltage, IO window, memory window, and interrupt settings.
+
+	   We make no assumptions about the card to be configured: we use
+	   just the information available in the CIS.  In an ideal world,
+	   this would work for any PCMCIA card, but it requires a complete
+	   and accurate CIS.  In practice, a driver usually "knows" most of
+	   these things without consulting the CIS, and most client drivers
+	   will only use the CIS to fill in implementation-defined details.
+	 */
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	CS_CHECK(GetFirstTuple, handle, &tuple);
+	while (1) {
+		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+		CFG_CHECK(GetTupleData, handle, &tuple);
+		CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+
+		DEBUG(0, "dldwd_cs_config: index = 0x%x, flags = 0x%x\n",
+		      cfg->index, cfg->flags);
+
+		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+			dflt = *cfg;
+		if (cfg->index == 0)
+			goto next_entry;
+		link->conf.ConfigIndex = cfg->index;
+
+		/* Does this card need audio output? */
+		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+			link->conf.Attributes |= CONF_ENABLE_SPKR;
+			link->conf.Status = CCSR_AUDIO_ENA;
+		}
+
+		/* Use power settings for Vcc and Vpp if present */
+		/*  Note that the CIS values need to be rescaled */
+		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (conf.Vcc !=
+			    cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+				DEBUG(2, "dldwd_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+				if(!ignore_cis_vcc)
+					goto next_entry;
+			}
+		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (conf.Vcc !=
+			    dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
+				DEBUG(2, "dldwd_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+				if(!ignore_cis_vcc)
+					goto next_entry;
+			}
+		}
+
+		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 =
+			    cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 =
+			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		
+		DEBUG(0, "dldwd_cs_config: We seem to have configured Vcc and Vpp\n");
+
+		/* Do we need to allocate an interrupt? */
+		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
+			link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+		/* IO window settings */
+		link->io.NumPorts1 = link->io.NumPorts2 = 0;
+		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+			cistpl_io_t *io =
+			    (cfg->io.nwin) ? &cfg->io : &dflt.io;
+			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+			if (!(io->flags & CISTPL_IO_8BIT))
+				link->io.Attributes1 =
+				    IO_DATA_PATH_WIDTH_16;
+			if (!(io->flags & CISTPL_IO_16BIT))
+				link->io.Attributes1 =
+				    IO_DATA_PATH_WIDTH_8;
+			link->io.IOAddrLines =
+			    io->flags & CISTPL_IO_LINES_MASK;
+			link->io.BasePort1 = io->win[0].base;
+			link->io.NumPorts1 = io->win[0].len;
+			if (io->nwin > 1) {
+				link->io.Attributes2 =
+				    link->io.Attributes1;
+				link->io.BasePort2 = io->win[1].base;
+				link->io.NumPorts2 = io->win[1].len;
+			}
+
+			/* This reserves IO space but doesn't actually enable it */
+			CFG_CHECK(RequestIO, link->handle, &link->io);
+		}
+
+
+		/* If we got this far, we're cool! */
+
+		break;
+		
+	next_entry:
+		if (link->io.NumPorts1)
+			CardServices(ReleaseIO, link->handle, &link->io);
+		CS_CHECK(GetNextTuple, handle, &tuple);
+	}
+
+	/*
+	   Allocate an interrupt line.  Note that this does not assign a
+	   handler to the interrupt, unless the 'Handler' member of the
+	   irq structure is initialized.
+	 */
+	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
+		int i;
+
+		link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+		link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+		if (irq_list[0] == -1)
+			link->irq.IRQInfo2 = irq_mask;
+		else
+			for (i=0; i<4; i++)
+				link->irq.IRQInfo2 |= 1 << irq_list[i];
+		
+  		link->irq.Handler = dldwd_interrupt; 
+  		link->irq.Instance = priv; 
+		
+		CS_CHECK(RequestIRQ, link->handle, &link->irq);
+	}
+
+	/* We initialize the hermes structure before completing PCMCIA
+	   configuration just in case the interrupt handler gets
+	   called. */
+	hermes_struct_init(hw, link->io.BasePort1);
+
+	/*
+	   This actually configures the PCMCIA socket -- setting up
+	   the I/O windows and the interrupt mapping, and putting the
+	   card and host interface into "Memory and IO" mode.
+	 */
+	CS_CHECK(RequestConfiguration, link->handle, &link->conf);
+
+	ndev->base_addr = link->io.BasePort1;
+	ndev->irq = link->irq.AssignedIRQ;
+
+	/* Do a Pcmcia soft reset of the card (optional) */
+	if(reset_cor)
+		dldwd_cs_cor_reset(link);
+
+	/* register_netdev will give us an ethX name */
+	ndev->name[0] = '\0';
+	/* Tell the stack we exist */
+	if (register_netdev(ndev) != 0) {
+		printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");
+		goto failed;
+	}
+	strcpy(card->node.dev_name, ndev->name);
+
+	/* Finally, report what we've done */
+	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
+	       ndev->name, link->conf.ConfigIndex,
+	       link->conf.Vcc / 10, link->conf.Vcc % 10);
+	if (link->conf.Vpp1)
+		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
+		       link->conf.Vpp1 % 10);
+	if (link->conf.Attributes & CONF_ENABLE_IRQ)
+		printk(", irq %d", link->irq.AssignedIRQ);
+	if (link->io.NumPorts1)
+		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+		       link->io.BasePort1 + link->io.NumPorts1 - 1);
+	if (link->io.NumPorts2)
+		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	printk("\n");
+
+	/* Allow /proc & ioctls to act */
+	priv->hw_ready = 1;
+	
+	/* And give us the proc nodes for debugging */
+	if (dldwd_proc_dev_init(priv) != 0) {
+		printk(KERN_ERR "orinoco_cs: Failed to create /proc node for %s\n",
+		       ndev->name);
+		goto failed;
+	}
+	
+	/* Note to myself : this replace MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT */
+	SET_MODULE_OWNER(ndev);
+	
+	/*
+	   At this point, the dev_node_t structure(s) need to be
+	   initialized and arranged in a linked list at link->dev.
+	 */
+	card->node.major = card->node.minor = 0;
+	link->dev = &card->node;
+	link->state &= ~DEV_CONFIG_PENDING;
+
+	TRACE_EXIT("dldwd");
+
+	return;
+
+ cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+ failed:
+	dldwd_cs_release((u_long) link);
+
+	TRACE_EXIT("dldwd");
+}				/* dldwd_cs_config */
+
+/*======================================================================
+  After a card is removed, dldwd_cs_release() will unregister the
+  device, and release the PCMCIA configuration.  If the device is
+  still open, this will be postponed until it is closed.
+  ======================================================================*/
+
+static void
+dldwd_cs_release(u_long arg)
+{
+	dev_link_t *link = (dev_link_t *) arg;
+	dldwd_priv_t *priv = link->priv;
+
+	TRACE_ENTER(link->dev->dev_name);
+
+	/*
+	   If the device is currently in use, we won't release until it
+	   is actually closed, because until then, we can't be sure that
+	   no one will try to access the device or its data structures.
+	 */
+	if (link->open) {
+		DEBUG(0, "orinoco_cs: release postponed, '%s' still open\n",
+		      link->dev->dev_name);
+		link->state |= DEV_STALE_CONFIG;
+		return;
+	}
+
+	/* Unregister proc entry */
+	dldwd_proc_dev_cleanup(priv);
+
+	/* Don't bother checking to see if these succeed or not */
+	CardServices(ReleaseConfiguration, link->handle);
+	if (link->io.NumPorts1)
+		CardServices(ReleaseIO, link->handle, &link->io);
+	if (link->irq.AssignedIRQ)
+		CardServices(ReleaseIRQ, link->handle, &link->irq);
+	link->state &= ~DEV_CONFIG;
+
+	TRACE_EXIT(link->dev->dev_name);
+}				/* dldwd_cs_release */
+
+/*======================================================================
+  The card status event handler.  Mostly, this schedules other
+  stuff to run after an event is received.
+
+  When a CARD_REMOVAL event is received, we immediately set a
+  private flag to block future accesses to this device.  All the
+  functions that actually access the device should check this flag
+  to make sure the card is still present.
+  ======================================================================*/
+
+static int
+dldwd_cs_event(event_t event, int priority,
+		       event_callback_args_t * args)
+{
+	dev_link_t *link = args->client_data;
+	dldwd_priv_t *priv = (dldwd_priv_t *)link->priv;
+	struct net_device *dev = &priv->ndev;
+
+	TRACE_ENTER("dldwd");
+
+	switch (event) {
+	case CS_EVENT_CARD_REMOVAL:
+		priv->hw_ready = 0;
+		dldwd_shutdown(priv);
+		link->state &= ~DEV_PRESENT;
+		if (link->state & DEV_CONFIG) {
+			netif_stop_queue(dev);
+			netif_device_detach(dev);
+			mod_timer(&link->release, jiffies + HZ / 20);
+		}
+		break;
+	case CS_EVENT_CARD_INSERTION:
+		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+		dldwd_cs_config(link);
+		break;
+	case CS_EVENT_PM_SUSPEND:
+
+		link->state |= DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+		dldwd_shutdown(priv);
+		/* Mark the device as stopped, to block IO until later */
+
+		if (link->state & DEV_CONFIG) {
+			if (link->open) {
+				netif_stop_queue(dev);
+				netif_device_detach(dev);
+			}
+			CardServices(ReleaseConfiguration, link->handle);
+		}
+		break;
+	case CS_EVENT_PM_RESUME:
+		link->state &= ~DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_CARD_RESET:
+		if (link->state & DEV_CONFIG) {
+			CardServices(RequestConfiguration, link->handle,
+				     &link->conf);
+
+			if (link->open) {
+				if (dldwd_reset(priv) == 0) {
+					netif_device_attach(dev);
+					netif_start_queue(dev);
+				} else {
+					printk(KERN_ERR "%s: Error resetting device on PCMCIA event\n",
+					       dev->name);
+					dldwd_cs_stop(dev);
+				}
+			}
+		}
+		/*
+		   In a normal driver, additional code may go here to restore
+		   the device state and restart IO. 
+		 */
+		break;
+	}
+
+	TRACE_EXIT("dldwd");
+
+	return 0;
+}				/* dldwd_cs_event */
+
+static int __init
+init_dldwd_cs(void)
+{
+	servinfo_t serv;
+
+	TRACE_ENTER("dldwd");
+
+	printk(KERN_INFO "dldwd: David's Less Dodgy WaveLAN/IEEE Driver\n");
+
+	DEBUG(0, "%s\n", version);
+
+	CardServices(GetCardServicesInfo, &serv);
+	if (serv.Revision != CS_RELEASE_CODE) {
+		printk(KERN_NOTICE "orinoco_cs: Card Services release "
+		       "does not match!\n");
+		return -1;
+	}
+
+	register_pccard_driver(&dev_info, &dldwd_cs_attach, &dldwd_cs_detach);
+
+
+	TRACE_EXIT("dldwd");
+	return 0;
+}
+
+static void __exit
+exit_dldwd_cs(void)
+{
+	TRACE_ENTER("dldwd");
+
+	unregister_pccard_driver(&dev_info);
+
+	if (dev_list)
+		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
+	while (dev_list != NULL) {
+		del_timer(&dev_list->release);
+		if (dev_list->state & DEV_CONFIG)
+			dldwd_cs_release((u_long) dev_list);
+		dldwd_cs_detach(dev_list);
+	}
+
+	TRACE_EXIT("dldwd");
+}
+
+module_init(init_dldwd_cs);
+module_exit(exit_dldwd_cs);
diff -u --recursive --new-file v2.4.4/linux/drivers/net/wireless/todo.txt linux/drivers/net/wireless/todo.txt
--- v2.4.4/linux/drivers/net/wireless/todo.txt	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/todo.txt	Mon May  7 19:42:14 2001
@@ -0,0 +1,24 @@
+	Wireless Todo
+	-------------
+
+1) Bring other kernel Wireless LAN drivers here
+	Already done :
+	 o hermes.c/orinoco.c	-> Wavelan IEEE driver + Airport driver
+	Drivers I have control over :
+	 o wavelan.c		-> old Wavelan ISA driver
+	 o wavelan_cs.c		-> old Wavelan Pcmcia driver (warning : header)
+	 o netwave_cs.c		-> Netwave Pcmcia driver
+	Drivers likely to go :
+	 o ray_cs.c		-> Raytheon/Aviator driver (maintainer MIA)
+	Drivers I have absolutely no control over :
+	 o arlan.c		-> old Aironet Arlan 655 (need to ask Elmer)
+	 o aironet4500_xxx.c	-> Elmer's Aironet driver (need to ask Elmer)
+	 o airo.c/airo_cs.c	-> Ben's Aironet driver (not yet in kernel)
+	 o strip.c		-> Metricom's stuff. Not a wlan. Hum...
+
+	ETA : Kernel 2.5.X
+
+2) Bring new Wireless LAN driver not yet in the kernel there
+	See my web page for details
+
+	Jean II
diff -u --recursive --new-file v2.4.4/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.4.4/linux/drivers/net/yellowfin.c	Fri Apr 20 11:54:23 2001
+++ linux/drivers/net/yellowfin.c	Wed May 16 10:25:39 2001
@@ -29,6 +29,11 @@
 	LK1.1.2 (jgarzik):
 	* Merge in becker version 1.05
 
+	LK1.1.3 (jgarzik):
+	* Various cleanups
+	* Update yellowfin_timer to correctly calculate duplex.
+	(suggested by Manfred Spraul)
+	
 */
 
 /* The user-configurable values.
@@ -99,6 +104,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -111,7 +117,7 @@
 static char version[] __devinitdata =
 KERN_INFO "yellowfin.c:v1.05  1/09/2001  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO "  http://www.scyld.com/network/yellowfin.html\n"
-KERN_INFO "  (unofficial 2.4.x port, LK1.1.2, January 11, 2001)\n";
+KERN_INFO "  (unofficial 2.4.x port, LK1.1.3, May 10, 2001)\n";
 
 /* Condensed operations for readability. */
 #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
@@ -652,22 +658,19 @@
 	}
 
 	if (yp->mii_cnt) {
-		int mii_reg1 = mdio_read(ioaddr, yp->phys[0], 1);
-		int mii_reg5 = mdio_read(ioaddr, yp->phys[0], 5);
-		int negotiated = mii_reg5 & yp->advertising;
+		int bmsr = mdio_read(ioaddr, yp->phys[0], MII_BMSR);
+		int lpa = mdio_read(ioaddr, yp->phys[0], MII_LPA);
+		int negotiated = lpa & yp->advertising;
 		if (yellowfin_debug > 1)
 			printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "
 				   "link partner capability %4.4x.\n",
-				   dev->name, yp->phys[0], mii_reg1, mii_reg5);
+				   dev->name, yp->phys[0], bmsr, lpa);
 
-		if ( ! yp->duplex_lock &&
-			 ((negotiated & 0x0300) == 0x0100
-			  || (negotiated & 0x00C0) == 0x0040)) {
-			yp->full_duplex = 1;
-		}
+		yp->full_duplex = mii_duplex(yp->duplex_lock, negotiated);
+			
 		outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
 
-		if (mii_reg1 & 0x0004)
+		if (bmsr & BMSR_LSTATUS)
 			next_tick = 60*HZ;
 		else
 			next_tick = 3*HZ;
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/BUGS-parport linux/drivers/parport/BUGS-parport
--- v2.4.4/linux/drivers/parport/BUGS-parport	Mon Jun 19 13:42:38 2000
+++ linux/drivers/parport/BUGS-parport	Sat May 19 18:07:04 2001
@@ -3,4 +3,7 @@
 o lp doesn't allow you to read status while printing is in progress (is
   this still true?).
 
+o parport_pc_ecp_read_block_pio() is broken.  parport will revert to the
+  software-driven mode in ieee1284_ops.c
+
 See <URL:http://people.redhat.com/twaugh/parport/>.
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- v2.4.4/linux/drivers/parport/ChangeLog	Fri Apr 20 16:23:12 2001
+++ linux/drivers/parport/ChangeLog	Tue May 22 19:54:04 2001
@@ -1,3 +1,43 @@
+2001-05-22  Juan Quintela  <quintela@mandrakesoft.com>
+
+	* parport_amiga.c: Set printk levels.
+	* parport_gsc.c: Likewise.
+	* parport_mfc3.c: Likewise.
+	* parport_pc.c: Likewise.
+	* parport_sunbpp.c: Likewise.
+	* probe.c: Likewise.
+	* share.c: Likewise.
+
+2001-05-10  Fred Barnes  <frmb2@ukc.ac.uk>
+
+       * parport_pc.c (parport_pc_epp_read_data): added support for
+       reading from a w91284pic peripheral, flag is PARPORT_W91284PIC.
+
+2001-05-07  Fred Barnes  <frmb2@ukc.ac.uk>
+ 
+ 	* parport_pc.c (parport_pc_epp_read_data,
+	parport_pc_epp_write_data, parport_pc_epp_read_addr,
+	parport_pc_epp_write_addr): support for fast reads/writes using
+	the PARPORT_EPP_FAST flag.
+ 
+ 	* ieee1284.c (parport_read, parport_write): added code to handle
+	software EPP mode (IEEE1284_MODE_EPPSWE).  Added code to allow
+	BYTE mode reverse transfers (previously always went for NIBBLE
+	mode).
+ 
+ 	* ieee1284_ops.c (parport_ieee1284_epp_read_data,
+	parport_ieee1284_epp_write_data): fixed various polarity problems.
+	Also (theoretically) fixed address versions (.._addr), but no
+	hardware to test this on.
+ 
+ 	* parport_pc.h: added parport_dump_state() function for debugging.
+ 	Needs to have DEBUG_PARPORT to be defined for it to be included.
+ 
+2001-05-03  Tim Waugh  <twaugh@redhat.com>
+
+	* parport_pc.c: Fix the compile problem I introduce from the last
+	change.
+
 2001-04-20  Paul Gortmaker  <p_gortmaker@yahoo.com>
 
 	* parport_pc.c: Cut down the size quite a bit (more than 4k off
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c
--- v2.4.4/linux/drivers/parport/ieee1284.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/parport/ieee1284.c	Sat May 19 18:07:04 2001
@@ -12,6 +12,8 @@
  * Any part of this program may be used in documents licensed under
  * the GNU Free Documentation License, Version 1.1 or any later version
  * published by the Free Software Foundation.
+ *
+ * Various hacks, Fred Barnes <frmb2@ukc.ac.uk>, 04/2000
  */
 
 #include <linux/config.h>
@@ -523,9 +525,10 @@
 		r = parport_wait_peripheral (port,
 					     PARPORT_STATUS_PAPEROUT,
 					     PARPORT_STATUS_PAPEROUT);
-		if (r)
+		if (r) {
 			DPRINTK (KERN_INFO "%s: Timeout at event 31\n",
-				 port->name);
+				port->name);
+		}
 
 		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 		DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
@@ -614,6 +617,7 @@
 	/* Use the mode we're in. */
 	switch (mode) {
 	case IEEE1284_MODE_NIBBLE:
+	case IEEE1284_MODE_BYTE:
 		parport_negotiate (port, IEEE1284_MODE_COMPAT);
 	case IEEE1284_MODE_COMPAT:
 		DPRINTK (KERN_DEBUG "%s: Using compatibility mode\n",
@@ -623,19 +627,29 @@
 
 	case IEEE1284_MODE_EPP:
 		DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name);
-		if (addr)
+		if (addr) {
 			fn = port->ops->epp_write_addr;
-		else
+		} else {
 			fn = port->ops->epp_write_data;
+		}
+		break;
+	case IEEE1284_MODE_EPPSWE:
+		DPRINTK (KERN_DEBUG "%s: Using software-emulated EPP mode\n",
+			port->name);
+		if (addr) {
+			fn = parport_ieee1284_epp_write_addr;
+		} else {
+			fn = parport_ieee1284_epp_write_data;
+		}
 		break;
-
 	case IEEE1284_MODE_ECP:
 	case IEEE1284_MODE_ECPRLE:
 		DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name);
-		if (addr)
+		if (addr) {
 			fn = port->ops->ecp_write_addr;
-		else
+		} else {
 			fn = port->ops->ecp_write_data;
+		}
 		break;
 
 	case IEEE1284_MODE_ECPSWE:
@@ -643,10 +657,11 @@
 			 port->name);
 		/* The caller has specified that it must be emulated,
 		 * even if we have ECP hardware! */
-		if (addr)
+		if (addr) {
 			fn = parport_ieee1284_ecp_write_addr;
-		else
+		} else {
 			fn = parport_ieee1284_ecp_write_data;
+		}
 		break;
 
 	default:
@@ -656,8 +671,7 @@
 	}
 
 	retval = (*fn) (port, buffer, len, 0);
-	DPRINTK (KERN_DEBUG "%s: wrote %d/%d bytes\n", port->name, retval,
-		 len);
+	DPRINTK (KERN_DEBUG "%s: wrote %d/%d bytes\n", port->name, retval, len);
 	return retval;
 #endif /* IEEE1284 support */
 }
@@ -696,8 +710,22 @@
 	/* Use the mode we're in. */
 	switch (mode) {
 	case IEEE1284_MODE_COMPAT:
-		if (parport_negotiate (port, IEEE1284_MODE_NIBBLE))
+		/* if we can tri-state use BYTE mode instead of NIBBLE mode,
+		 * if that fails, revert to NIBBLE mode -- ought to store somewhere
+		 * the device's ability to do BYTE mode reverse transfers, so we don't
+		 * end up needlessly calling negotiate(BYTE) repeately..  (fb)
+		 */
+		if ((port->physport->modes & PARPORT_MODE_TRISTATE) &&
+		    !parport_negotiate (port, IEEE1284_MODE_BYTE)) {
+			/* got into BYTE mode OK */
+			DPRINTK (KERN_DEBUG "%s: Using byte mode\n", port->name);
+			fn = port->ops->byte_read_data;
+			break;
+		}
+		if (parport_negotiate (port, IEEE1284_MODE_NIBBLE)) {
 			return -EIO;
+		}
+		/* fall through to NIBBLE */
 	case IEEE1284_MODE_NIBBLE:
 		DPRINTK (KERN_DEBUG "%s: Using nibble mode\n", port->name);
 		fn = port->ops->nibble_read_data;
@@ -710,12 +738,21 @@
 
 	case IEEE1284_MODE_EPP:
 		DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name);
-		if (addr)
+		if (addr) {
 			fn = port->ops->epp_read_addr;
-		else
+		} else {
 			fn = port->ops->epp_read_data;
+		}
+		break;
+	case IEEE1284_MODE_EPPSWE:
+		DPRINTK (KERN_DEBUG "%s: Using software-emulated EPP mode\n",
+			port->name);
+		if (addr) {
+			fn = parport_ieee1284_epp_read_addr;
+		} else {
+			fn = parport_ieee1284_epp_read_data;
+		}
 		break;
-
 	case IEEE1284_MODE_ECP:
 	case IEEE1284_MODE_ECPRLE:
 		DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name);
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- v2.4.4/linux/drivers/parport/ieee1284_ops.c	Fri Mar  2 18:43:03 2001
+++ linux/drivers/parport/ieee1284_ops.c	Sat May 19 18:07:04 2001
@@ -10,6 +10,7 @@
  *
  * Author: Tim Waugh <tim@cyberelk.demon.co.uk>
  * Fixed AUTOFD polarity in ecp_forward_to_reverse().  Fred Barnes, 1999
+ * Software emulated EPP fixes, Fred Barnes, 04/2001.
  */
 
 
@@ -18,7 +19,7 @@
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 
-#define DEBUG /* undef me for production */
+#undef DEBUG /* undef me for production */
 
 #ifdef CONFIG_LP_CONSOLE
 #undef DEBUG /* Don't want a garbled console */
@@ -725,31 +726,32 @@
 					const void *buffer, size_t len,
 					int flags)
 {
-	/* This is untested */
 	unsigned char *bp = (unsigned char *) buffer;
 	size_t ret = 0;
 
+	/* set EPP idle state (just to make sure) with strobe low */
 	parport_frob_control (port,
 			      PARPORT_CONTROL_STROBE |
 			      PARPORT_CONTROL_AUTOFD |
-			      PARPORT_CONTROL_SELECT,
+			      PARPORT_CONTROL_SELECT |
+			      PARPORT_CONTROL_INIT,
 			      PARPORT_CONTROL_STROBE |
-			      PARPORT_CONTROL_SELECT);
+			      PARPORT_CONTROL_INIT);
 	port->ops->data_forward (port);
 	for (; len > 0; len--, bp++) {
-		/* Event 62: Write data and strobe data */
+		/* Event 62: Write data and set autofd low */
 		parport_write_data (port, *bp);
 		parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
 				      PARPORT_CONTROL_AUTOFD);
 
-		/* Event 58 */
+		/* Event 58: wait for busy (nWait) to go high */
 		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
 			break;
 
-		/* Event 63 */
+		/* Event 63: set nAutoFd (nDStrb) high */
 		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
 
-		/* Event 60 */
+		/* Event 60: wait for busy (nWait) to go low */
 		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
 					     PARPORT_STATUS_BUSY, 5))
 			break;
@@ -757,7 +759,7 @@
 		ret++;
 	}
 
-	/* Event 61 */
+	/* Event 61: set strobe (nWrite) high */
 	parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
 
 	return ret;
@@ -768,29 +770,37 @@
 				       void *buffer, size_t len,
 				       int flags)
 {
-	/* This is untested. */
 	unsigned char *bp = (unsigned char *) buffer;
 	unsigned ret = 0;
 
+	/* set EPP idle state (just to make sure) with strobe high */
 	parport_frob_control (port,
 			      PARPORT_CONTROL_STROBE |
-			      PARPORT_CONTROL_SELECT, 0);
+			      PARPORT_CONTROL_AUTOFD |
+			      PARPORT_CONTROL_SELECT |
+			      PARPORT_CONTROL_INIT,
+			      PARPORT_CONTROL_INIT);
 	port->ops->data_reverse (port);
 	for (; len > 0; len--, bp++) {
-		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
-		/* Event 58 */
-		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY, 10))
+		/* Event 67: set nAutoFd (nDStrb) low */
+		parport_frob_control (port,
+				      PARPORT_CONTROL_AUTOFD,
+				      PARPORT_CONTROL_AUTOFD);
+		/* Event 58: wait for Busy to go high */
+		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) {
 			break;
+		}
 
 		*bp = parport_read_data (port);
 
-		parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
-				      PARPORT_CONTROL_AUTOFD);
+		/* Event 63: set nAutoFd (nDStrb) high */
+		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
 
-		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+		/* Event 60: wait for Busy to go low */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+					     PARPORT_STATUS_BUSY, 5)) {
 			break;
+		}
 
 		ret++;
 	}
@@ -873,3 +883,5 @@
 
 	return ret;
 }
+
+
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/init.c linux/drivers/parport/init.c
--- v2.4.4/linux/drivers/parport/init.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/parport/init.c	Wed May 16 10:25:39 2001
@@ -165,6 +165,8 @@
 	return 0;
 }
 
+__initcall(parport_init);
+
 #endif
 
 /* Exported symbols for modules. */
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/parport_amiga.c linux/drivers/parport/parport_amiga.c
--- v2.4.4/linux/drivers/parport/parport_amiga.c	Mon Nov 27 17:11:26 2000
+++ linux/drivers/parport/parport_amiga.c	Tue May 22 19:54:04 2001
@@ -34,7 +34,7 @@
 
 static void amiga_write_data(struct parport *p, unsigned char data)
 {
-	DPRINTK("write_data %c\n",data);
+	DPRINTK(KERN_DEBUG "write_data %c\n",data);
 	/* Triggers also /STROBE. This behavior cannot be changed */
 	ciaa.prb = data;
 	mb();
@@ -73,13 +73,13 @@
 
 static void amiga_write_control(struct parport *p, unsigned char control)
 {
-	DPRINTK("write_control %02x\n",control);
+	DPRINTK(KERN_DEBUG "write_control %02x\n",control);
 	/* No implementation possible */
 }
 	
 static unsigned char amiga_read_control( struct parport *p)
 {
-	DPRINTK("read_control \n");
+	DPRINTK(KERN_DEBUG "read_control \n");
 	return control_amiga_to_pc(0);
 }
 
@@ -87,7 +87,7 @@
 {
 	unsigned char old;
 
-	DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
+	DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val);
 	old = amiga_read_control(p);
 	amiga_write_control(p, (old & ~mask) ^ val);
 	return old;
@@ -132,7 +132,7 @@
 	unsigned char status;
 
 	status = status_amiga_to_pc(ciab.pra & 7);
-	DPRINTK("read_status %02x\n", status);
+	DPRINTK(KERN_DEBUG "read_status %02x\n", status);
 	return status;
 }
 
@@ -154,14 +154,14 @@
 
 static void amiga_data_forward(struct parport *p)
 {
-	DPRINTK("forward\n");
+	DPRINTK(KERN_DEBUG "forward\n");
 	ciaa.ddrb = 0xff; /* all pins output */
 	mb();
 }
 
 static void amiga_data_reverse(struct parport *p)
 {
-	DPRINTK("reverse\n");
+	DPRINTK(KERN_DEBUG "reverse\n");
 	ciaa.ddrb = 0; /* all pins input */
 	mb();
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/parport_gsc.c linux/drivers/parport/parport_gsc.c
--- v2.4.4/linux/drivers/parport/parport_gsc.c	Tue Mar  6 19:44:37 2001
+++ linux/drivers/parport/parport_gsc.c	Tue May 22 19:54:04 2001
@@ -473,7 +473,7 @@
 	irq = busdevice_alloc_irq(d); 
 
 	if (!irq) {
-	    printk("IRQ not found for parallel device at 0x%p\n", d->hpa);
+	    printk(KERN_DEBUG "IRQ not found for parallel device at 0x%p\n", d->hpa);
 	    return -ENODEV;
 	}
 
@@ -484,10 +484,10 @@
 	*/
 	if (!pdc_add_valid( (void *)(port+4))) {
 	    /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */
-	    printk("%s: initialize bidirectional-mode.\n", __FUNCTION__);
+	    printk(KERN_DEBUG "%s: initialize bidirectional-mode.\n", __FUNCTION__);
 	    parport_writeb ( (0x10 + 0x20), port + 4);
 	} else {
-	    printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__);
+	    printk(KERN_DEBUG "%s: enhanced parport-modes not supported.\n", __FUNCTION__);
 	}
 	
 	if (parport_gsc_probe_port(port, 0, 
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/parport_mfc3.c linux/drivers/parport/parport_mfc3.c
--- v2.4.4/linux/drivers/parport/parport_mfc3.c	Mon Nov 27 17:11:26 2000
+++ linux/drivers/parport/parport_mfc3.c	Tue May 22 19:54:04 2001
@@ -82,7 +82,7 @@
 
 static void mfc3_write_data(struct parport *p, unsigned char data)
 {
-DPRINTK("write_data %c\n",data);
+DPRINTK(KERN_DEBUG "write_data %c\n",data);
 
 	dummy = pia(p)->pprb; /* clears irq bit */
 	/* Triggers also /STROBE.*/
@@ -91,7 +91,7 @@
 
 static unsigned char mfc3_read_data(struct parport *p)
 {
-	/* clears interupt bit. Triggers also /STROBE. */
+	/* clears interrupt bit. Triggers also /STROBE. */
 	return pia(p)->pprb;
 }
 
@@ -126,13 +126,13 @@
 
 static void mfc3_write_control(struct parport *p, unsigned char control)
 {
-DPRINTK("write_control %02x\n",control);
+DPRINTK(KERN_DEBUG "write_control %02x\n",control);
 	pia(p)->ppra = (pia(p)->ppra & 0x1f) | control_pc_to_mfc3(control);
 }
 	
 static unsigned char mfc3_read_control( struct parport *p)
 {
-DPRINTK("read_control \n");
+DPRINTK(KERN_DEBUG "read_control \n");
 	return control_mfc3_to_pc(pia(p)->ppra & 0xe0);
 }
 
@@ -140,7 +140,7 @@
 {
 	unsigned char old;
 
-DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
+DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val);
 	old = mfc3_read_control(p);
 	mfc3_write_control(p, (old & ~mask) ^ val);
 	return old;
@@ -186,7 +186,7 @@
 #if 0 /* currently unused */
 static void mfc3_write_status( struct parport *p, unsigned char status)
 {
-DPRINTK("write_status %02x\n",status);
+DPRINTK(KERN_DEBUG "write_status %02x\n",status);
 	pia(p)->ppra = (pia(p)->ppra & 0xe0) | status_pc_to_mfc3(status);
 }
 #endif
@@ -196,7 +196,7 @@
 	unsigned char status;
 
 	status = status_mfc3_to_pc(pia(p)->ppra & 0x1f);
-DPRINTK("read_status %02x\n", status);
+DPRINTK(KERN_DEBUG "read_status %02x\n", status);
 	return status;
 }
 
@@ -234,7 +234,7 @@
 
 static void mfc3_data_forward(struct parport *p)
 {
-	DPRINTK("forward\n");
+	DPRINTK(KERN_DEBUG "forward\n");
 	pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */
 	pia(p)->pddrb = 255; /* all pins output */
 	pia(p)->crb |= PIA_DDR; /* make data register visible - default */
@@ -242,7 +242,7 @@
 
 static void mfc3_data_reverse(struct parport *p)
 {
-	DPRINTK("reverse\n");
+	DPRINTK(KERN_DEBUG "reverse\n");
 	pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */
 	pia(p)->pddrb = 0; /* all pins input */
 	pia(p)->crb |= PIA_DDR; /* make data register visible - default */
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.4.4/linux/drivers/parport/parport_pc.c	Fri Apr 20 16:23:12 2001
+++ linux/drivers/parport/parport_pc.c	Tue May 22 19:54:04 2001
@@ -12,6 +12,7 @@
  * DMA support - Bert De Jonghe <bert@sophis.be>
  * Many ECP bugs fixed.  Fred Barnes & Jamie Lokier, 1999
  * More PCI support now conditional on CONFIG_PCI, 03/2001, Paul G. 
+ * Various hacks, Fred Barnes, 04/2001
  */
 
 /* This driver should work with any hardware that is broadly compatible
@@ -117,7 +118,7 @@
 	unsigned char oecr;
 	int mode;
 
-	DPRINTK("parport change_mode ECP-ISA to mode 0x%02x\n",m);
+	DPRINTK(KERN_INFO "parport change_mode ECP-ISA to mode 0x%02x\n",m);
 
 	if (!priv->ecr) {
 		printk (KERN_DEBUG "change_mode: but there's no ECR!\n");
@@ -211,6 +212,7 @@
 	/* Back to PS2 mode. */
 	frob_econtrol (p, 0xe0, ECR_PS2 << 5);
 
+	DPRINTK (KERN_DEBUG "*** get_fifo_residue: done residue collecting (ecr = 0x%2.2x)\n", inb (ECONTROL (p)));
 	return residue;
 }
 #endif /* IEEE 1284 support */
@@ -367,9 +369,60 @@
 					size_t length, int flags)
 {
 	size_t got = 0;
+
+	if (flags & PARPORT_W91284PIC) {
+		unsigned char status;
+		size_t left = length;
+
+		/* use knowledge about data lines..:
+		 *  nFault is 0 if there is at least 1 byte in the Warp's FIFO
+		 *  pError is 1 if there are 16 bytes in the Warp's FIFO
+		 */
+		status = inb (STATUS (port));
+
+		while (!(status & 0x08) && (got < length)) {
+			if ((left >= 16) && (status & 0x20) && !(status & 0x08)) {
+				/* can grab 16 bytes from warp fifo */
+				if (!((long)buf & 0x03)) {
+					insl (EPPDATA (port), buf, 4);
+				} else {
+					insb (EPPDATA (port), buf, 16);
+				}
+				buf += 16;
+				got += 16;
+				left -= 16;
+			} else {
+				/* grab single byte from the warp fifo */
+				*((char *)buf)++ = inb (EPPDATA (port));
+				got++;
+				left--;
+			}
+			status = inb (STATUS (port));
+			if (status & 0x01) {
+				/* EPP timeout should never occur... */
+				printk (KERN_DEBUG "%s: EPP timeout occured while talking to "
+					"w91284pic (should not have done)\n", port->name);
+				clear_epp_timeout (port);
+			}
+		}
+		return got;
+	}
+	if ((flags & PARPORT_EPP_FAST) && (length > 1)) {
+		if (!(((long)buf | length) & 0x03)) {
+			insl (EPPDATA (port), buf, (length >> 2));
+		} else {
+			insb (EPPDATA (port), buf, length);
+		}
+		if (inb (STATUS (port)) & 0x01) {
+			clear_epp_timeout (port);
+			return -EIO;
+		}
+		return length;
+	}
 	for (; got < length; got++) {
 		*((char*)buf)++ = inb (EPPDATA(port));
-		if (inb (STATUS(port)) & 0x01) {
+		if (inb (STATUS (port)) & 0x01) {
+			/* EPP timeout */
 			clear_epp_timeout (port);
 			break;
 		}
@@ -382,6 +435,19 @@
 					 size_t length, int flags)
 {
 	size_t written = 0;
+
+	if ((flags & PARPORT_EPP_FAST) && (length > 1)) {
+		if (!(((long)buf | length) & 0x03)) {
+			outsl (EPPDATA (port), buf, (length >> 2));
+		} else {
+			outsb (EPPDATA (port), buf, length);
+		}
+		if (inb (STATUS (port)) & 0x01) {
+			clear_epp_timeout (port);
+			return -EIO;
+		}
+		return length;
+	}
 	for (; written < length; written++) {
 		outb (*((char*)buf)++, EPPDATA(port));
 		if (inb (STATUS(port)) & 0x01) {
@@ -397,6 +463,15 @@
 					size_t length, int flags)
 {
 	size_t got = 0;
+
+	if ((flags & PARPORT_EPP_FAST) && (length > 1)) {
+		insb (EPPADDR (port), buf, length);
+		if (inb (STATUS (port)) & 0x01) {
+			clear_epp_timeout (port);
+			return -EIO;
+		}
+		return length;
+	}
 	for (; got < length; got++) {
 		*((char*)buf)++ = inb (EPPADDR (port));
 		if (inb (STATUS (port)) & 0x01) {
@@ -413,6 +488,15 @@
 					 int flags)
 {
 	size_t written = 0;
+
+	if ((flags & PARPORT_EPP_FAST) && (length > 1)) {
+		outsb (EPPADDR (port), buf, length);
+		if (inb (STATUS (port)) & 0x01) {
+			clear_epp_timeout (port);
+			return -EIO;
+		}
+		return length;
+	}
 	for (; written < length; written++) {
 		outb (*((char*)buf)++, EPPADDR (port));
 		if (inb (STATUS (port)) & 0x01) {
@@ -500,7 +584,8 @@
 
 	/* We don't want to be interrupted every character. */
 	parport_pc_disable_irq (port);
-	frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */
+	/* set nErrIntrEn and serviceIntr */
+	frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2));
 
 	/* Forward mode. */
 	parport_pc_data_forward (port); /* Must be in PS2 mode */
@@ -575,6 +660,7 @@
 		left--;
         }
 
+dump_parport_state ("leave fifo_write_block_dma", port);
 	return length - left;
 }
 
@@ -590,6 +676,7 @@
 	unsigned long start = (unsigned long) buf;
 	unsigned long end = (unsigned long) buf + length - 1;
 
+dump_parport_state ("enter fifo_write_block_dma", port);
 	if (end < MAX_DMA_ADDRESS) {
 		/* If it would cross a 64k boundary, cap it at the end. */
 		if ((start ^ end) & ~0xffffUL)
@@ -608,7 +695,8 @@
 
 	/* We don't want to be interrupted every character. */
 	parport_pc_disable_irq (port);
-	frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */
+	/* set nErrIntrEn and serviceIntr */
+	frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2));
 
 	/* Forward mode. */
 	parport_pc_data_forward (port); /* Must be in PS2 mode */
@@ -698,6 +786,7 @@
 	if (dma_handle)
 		pci_unmap_single(priv->dev, dma_handle, length, PCI_DMA_TODEVICE);
 
+dump_parport_state ("leave fifo_write_block_dma", port);
 	return length - left;
 }
 
@@ -740,10 +829,10 @@
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
-			if (inb (ECONTROL (port)) & 0x2)
+			if (inb (ECONTROL (port)) & 0x2) {
 				/* Full up. */
 				break;
-
+			}
 			outb (0, FIFO (port));
 		}
 
@@ -791,9 +880,10 @@
 		r = parport_wait_peripheral (port,
 					     PARPORT_STATUS_PAPEROUT,
 					     PARPORT_STATUS_PAPEROUT);
-		if (r)
+		if (r) {
 			printk (KERN_DEBUG "%s: PError timeout (%d) "
 				"in ecp_write_block_pio\n", port->name, r);
+		}
 	}
 
 	/* Set up ECP parallel port mode.*/
@@ -824,10 +914,10 @@
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
-			if (inb (ECONTROL (port)) & 0x2)
+			if (inb (ECONTROL (port)) & 0x2) {
 				/* Full up. */
 				break;
-
+			}
 			outb (0, FIFO (port));
 		}
 
@@ -879,58 +969,99 @@
 	char *bufp = buf;
 
 	port = port->physport;
+DPRINTK (KERN_DEBUG "parport_pc: parport_pc_ecp_read_block_pio\n");
+dump_parport_state ("enter fcn", port);
 
 	/* Special case: a timeout of zero means we cannot call schedule(). */
 	if (!port->cad->timeout)
 		return parport_ieee1284_ecp_read_data (port, buf,
 						       length, flags);
 
-	fifofull = fifo_depth;
-	if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE)
+	if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE) {
 		/* If the peripheral is allowed to send RLE compressed
 		 * data, it is possible for a byte to expand to 128
 		 * bytes in the FIFO. */
 		fifofull = 128;
+	} else {
+		fifofull = fifo_depth;
+	}
 
 	/* If the caller wants less than a full FIFO's worth of data,
-	 * go through software emulation.  Otherwise we may have to through
+	 * go through software emulation.  Otherwise we may have to throw
 	 * away data. */
 	if (length < fifofull)
 		return parport_ieee1284_ecp_read_data (port, buf,
 						       length, flags);
 
-	/* Switch to reverse mode if necessary. */
-	if ((port->ieee1284.phase != IEEE1284_PH_REV_IDLE) &&
-	    (port->ieee1284.phase != IEEE1284_PH_REV_DATA)) {
-		/* Event 38: Set nAutoFd low */
+	if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {
+		/* change to reverse-idle phase (must be in forward-idle) */
+
+		/* Event 38: Set nAutoFd low (also make sure nStrobe is high) */
 		parport_frob_control (port,
-				      PARPORT_CONTROL_AUTOFD,
+				      PARPORT_CONTROL_AUTOFD
+				      | PARPORT_CONTROL_STROBE,
 				      PARPORT_CONTROL_AUTOFD);
 		parport_pc_data_reverse (port); /* Must be in PS2 mode */
 		udelay (5);
-
 		/* Event 39: Set nInit low to initiate bus reversal */
 		parport_frob_control (port,
 				      PARPORT_CONTROL_INIT,
 				      0);
-
-		/* Event 40: PError goes low */
+		/* Event 40: Wait for  nAckReverse (PError) to go low */
 		r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
-                if (r)
+                if (r) {
                         printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) "
 				"in ecp_read_block_pio\n", port->name, r);
+			return 0;
+		}
 	}
 
 	/* Set up ECP FIFO mode.*/
-	parport_pc_data_reverse (port); /* Must be in PS2 mode */
-	parport_pc_frob_control (port,
+/*	parport_pc_frob_control (port,
 				 PARPORT_CONTROL_STROBE |
 				 PARPORT_CONTROL_AUTOFD,
-				 0);
+				 PARPORT_CONTROL_AUTOFD); */
 	r = change_mode (port, ECR_ECP); /* ECP FIFO */
 	if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name);
+
 	port->ieee1284.phase = IEEE1284_PH_REV_DATA;
 
+	/* the first byte must be collected manually */
+dump_parport_state ("pre 43", port);
+	/* Event 43: Wait for nAck to go low */
+	r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0);
+	if (r) {
+		/* timed out while reading -- no data */
+		printk (KERN_DEBUG "PIO read timed out (initial byte)\n");
+		goto out_no_data;
+	}
+	/* read byte */
+	*bufp++ = inb (DATA (port));
+	left--;
+dump_parport_state ("43-44", port);
+	/* Event 44: nAutoFd (HostAck) goes high to acknowledge */
+	parport_pc_frob_control (port,
+				 PARPORT_CONTROL_AUTOFD,
+				 0);
+dump_parport_state ("pre 45", port);
+	/* Event 45: Wait for nAck to go high */
+/*	r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK); */
+dump_parport_state ("post 45", port);
+r = 0;
+	if (r) {
+		/* timed out while waiting for peripheral to respond to ack */
+		printk (KERN_DEBUG "ECP PIO read timed out (waiting for nAck)\n");
+
+		/* keep hold of the byte we've got already */
+		goto out_no_data;
+	}
+	/* Event 46: nAutoFd (HostAck) goes low to accept more data */
+	parport_pc_frob_control (port,
+				 PARPORT_CONTROL_AUTOFD,
+				 PARPORT_CONTROL_AUTOFD);
+
+
+dump_parport_state ("rev idle", port);
 	/* Do the transfer. */
 	while (left > fifofull) {
 		int ret;
@@ -949,31 +1080,35 @@
 
 		if (ecrval & 0x01) {
 			/* FIFO is empty. Wait for interrupt. */
+dump_parport_state ("FIFO empty", port);
 
 			/* Anyone else waiting for the port? */
 			if (port->waithead) {
-				printk (KERN_DEBUG
-					"Somebody wants the port\n");
+				printk (KERN_DEBUG "Somebody wants the port\n");
 				break;
 			}
 
 			/* Clear serviceIntr */
 			outb (ecrval & ~(1<<2), ECONTROL (port));
 		false_alarm:
+dump_parport_state ("waiting", port);
 			ret = parport_wait_event (port, HZ);
-			if (ret < 0) break;
+DPRINTK (KERN_DEBUG "parport_wait_event returned %d\n", ret);
+			if (ret < 0)
+				break;
 			ret = 0;
 			if (!time_before (jiffies, expire)) {
 				/* Timed out. */
+dump_parport_state ("timeout", port);
 				printk (KERN_DEBUG "PIO read timed out\n");
 				break;
 			}
 			ecrval = inb (ECONTROL (port));
 			if (!(ecrval & (1<<2))) {
 				if (current->need_resched &&
-				    time_before (jiffies, expire))
+				    time_before (jiffies, expire)) {
 					schedule ();
-
+				}
 				goto false_alarm;
 			}
 
@@ -986,12 +1121,15 @@
 
 		if (ecrval & 0x02) {
 			/* FIFO is full. */
+dump_parport_state ("FIFO full", port);
 			insb (fifo, bufp, fifo_depth);
 			bufp += fifo_depth;
 			left -= fifo_depth;
 			continue;
 		}
 
+DPRINTK (KERN_DEBUG "*** ecp_read_block_pio: reading one byte from the FIFO\n");
+
 		/* FIFO not filled.  We will cycle this loop for a while
                  * and either the peripheral will fill it faster,
                  * tripping a fast empty with insb, or we empty it. */
@@ -999,17 +1137,29 @@
 		left--;
 	}
 
+	/* scoop up anything left in the FIFO */
+	while (left && !(inb (ECONTROL (port) & 0x01))) {
+		*bufp++ = inb (fifo);
+		left--;
+	}
+
 	port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+dump_parport_state ("rev idle2", port);
+
+out_no_data:
+
+	/* Go to forward idle mode to shut the peripheral up (event 47). */
+	parport_frob_control (port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT);
 
-	/* Go to forward idle mode to shut the peripheral up. */
-	parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
+	/* event 49: PError goes high */
 	r = parport_wait_peripheral (port,
 				     PARPORT_STATUS_PAPEROUT,
 				     PARPORT_STATUS_PAPEROUT);
-	if (r)
+	if (r) {
 		printk (KERN_DEBUG
 			"%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n",
 			port->name, r);
+	}
 
 	port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 
@@ -1022,13 +1172,21 @@
 				port->name, lost);
 	}
 
+dump_parport_state ("fwd idle", port);
 	return length - left;
 }
 
 #endif /* IEEE 1284 support */
-
 #endif /* Allowed to use FIFO/DMA */
 
+
+/*
+ *	******************************************
+ *	INITIALISATION AND MODULE STUFF BELOW HERE
+ *	******************************************
+ */
+
+
 void parport_pc_inc_use_count(void)
 {
 #ifdef MODULE
@@ -1107,20 +1265,20 @@
 	cr27=inb(io+1);
 	outb(0xaa,io);
 
-	printk ("SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, "
+	printk (KERN_INFO "SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, "
 		"A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n",
 		cr1,cr4,cra,cr23,cr26,cr27);
 
 	/* The documentation calls DMA and IRQ-Lines by letters, so
 	   the board maker can/will wire them
 	   appropriately/randomly...  G=reserved H=IDE-irq, */
-	printk ("SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, "
+	printk (KERN_INFO "SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, "
 		"fifo threshold=%d\n", cr23*4,
 		(cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-',
 		(cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cra & 0x0f);
-	printk("SMSC LPT Config: enabled=%s power=%s\n",
+	printk(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n",
 	       (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no");
-	printk("SMSC LPT Config: Port mode=%s, EPP version =%s\n",
+	printk(KERN_INFO "SMSC LPT Config: Port mode=%s, EPP version =%s\n",
 	       (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03], 
 	       (cr4 & 0x40) ? "1.7" : "1.9");
 
@@ -1132,7 +1290,7 @@
 		while((superios[i].io!= 0) && (i<NR_SUPERIOS))
 			i++;
 		if(i==NR_SUPERIOS)
-			printk("Super-IO: too many chips!\n");
+			printk(KERN_INFO "Super-IO: too many chips!\n");
 		else {
 			int d;
 			switch (cr23*4) {
@@ -1192,23 +1350,23 @@
 	crf0=inb(io+1);
 	outb(0xaa,io);
 
-	printk("Winbond LPT Config: cr_30=%02x 60,61=%02x%02x "
+	printk(KERN_INFO "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x "
 	       "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0);
-	printk("Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", 
+	printk(KERN_INFO "Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", 
 	       (cr30 & 0x01) ? "yes":"no", cr60,cr61,cr70&0x0f );
 	if ((cr74 & 0x07) > 3)
 		printk("dma=none\n");
 	else
 		printk("dma=%d\n",cr74 & 0x07);
-	printk("Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n",
+	printk(KERN_INFO "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n",
 	       irqtypes[crf0>>7], (crf0>>3)&0x0f);
-	printk("Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]);
+	printk(KERN_INFO "Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]);
 
 	if(cr30 & 0x01) { /* the settings can be interrogated later ... */
 		while((superios[i].io!= 0) && (i<NR_SUPERIOS))
 			i++;
 		if(i==NR_SUPERIOS) 
-			printk("Super-IO: too many chips!\n");
+			printk(KERN_INFO "Super-IO: too many chips!\n");
 		else {
 			superios[i].io = (cr60<<8)|cr61;
 			superios[i].irq = cr70&0x0f;
@@ -1228,7 +1386,7 @@
                    non-winbond register */
 		return;
 
-	printk("Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x "
+	printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x "
 	       "oldid=%02x\n", efer,key,devid,devrev,oldid);
 	id=(devid<<8) | devrev;
 
@@ -1248,9 +1406,9 @@
 	else progif=0;
 
 	if(type==NULL) 
-		printk("Winbond unknown chip type\n");
+		printk(KERN_INFO "Winbond unknown chip type\n");
 	else	
-	 	printk("Winbond chip type %s\n",type);
+	 	printk(KERN_INFO "Winbond chip type %s\n",type);
 
 	if(progif==2)
 		show_parconfig_winbond(efer,key);
@@ -1269,7 +1427,7 @@
 		return;
 
 	func=NULL;
-        printk("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n",
+        printk(KERN_INFO "SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n",
 	       efer,key,devid,devrev);
         id=(devid<<8) | devrev;
 
@@ -1279,9 +1437,9 @@
 	else if	(devid==0x66) type="37c666GT";
 
 	if(type==NULL)
-                printk("SMSC unknown chip type\n");
+                printk(KERN_INFO "SMSC unknown chip type\n");
         else
-                printk("SMSC chip type %s\n",type);
+                printk(KERN_INFO "SMSC chip type %s\n",type);
 
 	if(func) (func)(efer,key);
 	return;
@@ -1382,7 +1540,7 @@
 
 static void __devinit detect_and_report_winbond (void)
 { 
-	printk("Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n");
+	printk(KERN_DEBUG "Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n");
 
 	winbond_check(0x3f0,0x87);
 	winbond_check(0x370,0x87);
@@ -1395,7 +1553,7 @@
 
 static void __devinit detect_and_report_smsc (void)
 {
-	printk("SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n");
+	printk(KERN_DEBUG "SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n");
 	smsc_check(0x3f0,0x55);
 	smsc_check(0x370,0x55);
 	smsc_check(0x3f0,0x44);
@@ -1705,7 +1863,7 @@
 		printk("%d",intrline[(configb >>3) & 0x07]);
 	else
 		printk("<none or set by other means>");
-	printk ( " dma=");
+	printk (" dma=");
 	if( (configb & 0x03 ) == 0x00)
 		printk("<none or set by other means>\n");
 	else
@@ -1756,17 +1914,19 @@
 	 */
 
 	/* If EPP timeout bit clear then EPP available */
-	if (!clear_epp_timeout(pb))
+	if (!clear_epp_timeout(pb)) {
 		return 0;  /* No way to clear timeout */
+	}
 
 	/* Check for Intel bug. */
 	if (priv->ecr) {
 		unsigned char i;
 		for (i = 0x00; i < 0x80; i += 0x20) {
 			outb (i, ECONTROL (pb));
-			if (clear_epp_timeout (pb))
+			if (clear_epp_timeout (pb)) {
 				/* Phony EPP in ECP. */
 				return 0;
+			}
 		}
 	}
 
@@ -1787,8 +1947,9 @@
 	int result;
 	unsigned char oecr;
 
-	if (!priv->ecr)
+	if (!priv->ecr) {
 		return 0;
+	}
 
 	oecr = inb (ECONTROL (pb));
 	/* Search for SMC style EPP+ECP mode */
@@ -1930,10 +2091,11 @@
 		pb->irq = programmable_irq_support(pb);
 	}
 
-	if (pb->modes & PARPORT_MODE_ECP)
+	if (pb->modes & PARPORT_MODE_ECP) {
 		pb->irq = irq_probe_ECP(pb);
+	}
 
-	if (pb->irq == PARPORT_IRQ_NONE && priv->ecr &&
+	if ((pb->irq == PARPORT_IRQ_NONE) && priv->ecr &&
 	    (pb->modes & PARPORT_MODE_EPP))
 		pb->irq = irq_probe_EPP(pb);
 
@@ -1978,11 +2140,12 @@
 	const struct parport_pc_private *priv = p->private_data;
 	if (priv->ecr)
 		p->dma = programmable_dma_support(p); /* ask ECP chipset first */
-	if (p->dma == PARPORT_DMA_NONE)
+	if (p->dma == PARPORT_DMA_NONE) {
 		/* ask known Super-IO chips proper, although these
 		   claim ECP compatible, some don't report their DMA
 		   conforming to ECP standards */
 		p->dma = get_superio_dma(p);
+	}
 
 	return p->dma;
 }
@@ -2092,6 +2255,8 @@
 		p->ops->compat_write_data = parport_pc_compat_write_block_pio;
 #ifdef CONFIG_PARPORT_1284
 		p->ops->ecp_write_data = parport_pc_ecp_write_block_pio;
+		/* currently broken, but working on it.. (FB) */
+		/* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */
 #endif /* IEEE 1284 support */
 		if (p->dma != PARPORT_DMA_NONE) {
 			printk(", dma %d", p->dma);
@@ -2576,7 +2741,7 @@
 }
 #else
 static struct pci_driver parport_pc_pci_driver;
-static int __init parport_pc_init_superio(void) {return 0;}
+static int __init parport_pc_init_superio(int autoirq, int autodma) {return 0;}
 #endif /* CONFIG_PCI */
 
 /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c
--- v2.4.4/linux/drivers/parport/parport_sunbpp.c	Sun Feb 18 19:49:54 2001
+++ linux/drivers/parport/parport_sunbpp.c	Tue May 22 19:54:04 2001
@@ -74,7 +74,7 @@
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
 
 	sbus_writeb(d, &regs->p_dr);
-	dprintk(("wrote 0x%x\n", d));
+	dprintk((KERN_DEBUG "wrote 0x%x\n", d));
 }
 
 static unsigned char parport_sunbpp_read_data(struct parport *p)
@@ -123,8 +123,8 @@
 	if (!(value_tcr & P_TCR_BUSY))
 		bits |= PARPORT_STATUS_BUSY;
 
-	dprintk(("tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir));
-	dprintk(("read status 0x%x\n", bits));
+	dprintk((KERN_DEBUG "tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir));
+	dprintk((KERN_DEBUG "read status 0x%x\n", bits));
 	return bits;
 }
 
@@ -144,8 +144,8 @@
 	if (value_or & P_OR_SLCT_IN)
 		bits |= PARPORT_CONTROL_SELECT;
 
-	dprintk(("tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
-	dprintk(("read control 0x%x\n", bits));
+	dprintk((KERN_DEBUG "tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
+	dprintk((KERN_DEBUG "read control 0x%x\n", bits));
 	return bits;
 }
 
@@ -162,7 +162,7 @@
 	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
 	unsigned char value_or = sbus_readb(&regs->p_or);
 
-	dprintk(("frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
+	dprintk((KERN_DEBUG "frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
 	if (mask & PARPORT_CONTROL_STROBE) {
 		if (val & PARPORT_CONTROL_STROBE) {
 			value_tcr &= ~P_TCR_DS;
@@ -194,7 +194,7 @@
 
 	sbus_writeb(value_or, &regs->p_or);
 	sbus_writeb(value_tcr, &regs->p_tcr);
-	dprintk(("frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
+	dprintk((KERN_DEBUG "frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
 	return parport_sunbpp_read_control(p);
 }
 
@@ -218,7 +218,7 @@
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
 	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
 
-	dprintk(("forward\n"));
+	dprintk((KERN_DEBUG "forward\n"));
 	value_tcr &= ~P_TCR_DIR;
 	sbus_writeb(value_tcr, &regs->p_tcr);
 }
@@ -228,7 +228,7 @@
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
 	u8 val = sbus_readb(&regs->p_tcr);
 
-	dprintk(("reverse\n"));
+	dprintk((KERN_DEBUG "reverse\n"));
 	val |= P_TCR_DIR;
 	sbus_writeb(val, &regs->p_tcr);
 }
@@ -311,7 +311,7 @@
 	struct bpp_regs *regs;
 	unsigned char value_tcr;
 
-	dprintk(("init_one_port(%p): ranges, alloc_io, ", sdev));
+	dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
 	irq = sdev->irqs[0];
 	base = sbus_ioremap(&sdev->resource[0], 0,
 			    sdev->reg_addrs[0].reg_size, 
@@ -328,7 +328,7 @@
 
         memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
 
-	dprintk(("register_port, "));
+	dprintk(("register_port\n"));
 	if (!(p = parport_register_port(base, irq, dma, ops))) {
 		kfree(ops);
 		sbus_iounmap(base, size);
@@ -337,7 +337,7 @@
 
 	p->size = size;
 
-	dprintk(("init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
+	dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
 		p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p));
 	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
 			       SA_SHIRQ, p->name, p)) != 0) {
@@ -352,7 +352,7 @@
 	}
 
 	regs = (struct bpp_regs *)p->base;
-	dprintk(("forward\n"));
+	dprintk((KERN_DEBUG "forward\n"));
 	value_tcr = sbus_readb(&regs->p_tcr);
 	value_tcr &= ~P_TCR_DIR;
 	sbus_writeb(value_tcr, &regs->p_tcr);
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/probe.c linux/drivers/parport/probe.c
--- v2.4.4/linux/drivers/parport/probe.c	Sat Feb  3 12:43:37 2001
+++ linux/drivers/parport/probe.c	Tue May 22 19:54:04 2001
@@ -62,7 +62,7 @@
 	struct parport_device_info *info = &port->probe_info[device + 1];
 
 	if (!txt) {
-		printk("%s probe: memory squeeze\n", port->name);
+		printk(KERN_WARNING "%s probe: memory squeeze\n", port->name);
 		return;
 	}
 	strcpy(txt, str);
diff -u --recursive --new-file v2.4.4/linux/drivers/parport/share.c linux/drivers/parport/share.c
--- v2.4.4/linux/drivers/parport/share.c	Mon Mar 26 15:41:19 2001
+++ linux/drivers/parport/share.c	Tue May 22 19:54:04 2001
@@ -1103,7 +1103,7 @@
 			if (ep != str[i])
 				val[i] = r;
 			else {
-				printk("parport: bad specifier `%s'\n", str[i]);
+				printk(KERN_ERR "parport: bad specifier `%s'\n", str[i]);
 				return -1;
 			}
 		}
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.4.4/linux/drivers/pci/Makefile	Fri Apr 13 20:31:32 2001
+++ linux/drivers/pci/Makefile	Sat May 19 17:49:14 2001
@@ -22,6 +22,7 @@
 obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
 obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
 obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
+obj-$(CONFIG_ALL_PPC) += setup-bus.o
 
 ifndef CONFIG_X86
 obj-y += syscall.o
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.4.4/linux/drivers/pci/pci.c	Thu Apr 19 08:38:48 2001
+++ linux/drivers/pci/pci.c	Sat May 19 17:43:06 2001
@@ -843,7 +843,7 @@
 		 * Ugh. We don't know enough about this bridge. Just assume
 		 * that it's entirely transparent.
 		 */
-		printk("Unknown bridge resource %d: assuming transparent\n", 0);
+		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 0);
 		child->resource[0] = child->parent->resource[0];
 	}
 
@@ -859,7 +859,7 @@
 		res->name = child->name;
 	} else {
 		/* See comment above. Same thing */
-		printk("Unknown bridge resource %d: assuming transparent\n", 1);
+		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 1);
 		child->resource[1] = child->parent->resource[1];
 	}
 
@@ -886,7 +886,7 @@
 		res->name = child->name;
 	} else {
 		/* See comments above */
-		printk("Unknown bridge resource %d: assuming transparent\n", 2);
+		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 2);
 		child->resource[2] = child->parent->resource[2];
 	}
 }
@@ -1484,7 +1484,7 @@
 	page->vaddr = pci_alloc_consistent (pool->dev,
 				pool->allocation, &page->dma);
 	if (page->vaddr) {
-		memset (page->bitmap, ~0, mapsize);	// bit set == free
+		memset (page->bitmap, 0xff, mapsize);	// bit set == free
 		if (pool->flags & SLAB_POISON)
 			memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
 		list_add (&page->page_list, &pool->page_list);
@@ -1500,7 +1500,7 @@
 is_page_busy (int blocks, unsigned long *bitmap)
 {
 	while (blocks > 0) {
-		if (*bitmap++ != ~0)
+		if (*bitmap++ != ~0UL)
 			return 1;
 		blocks -= BITS_PER_LONG;
 	}
@@ -1589,9 +1589,8 @@
 				i += BITS_PER_LONG, map++) {
 			if (page->bitmap [map] == 0)
 				continue;
-			block = ffs (page->bitmap [map]);
-			if ((i + block) <= pool->blocks_per_page) {
-				block--;
+			block = ffz (~ page->bitmap [map]);
+			if ((i + block) < pool->blocks_per_page) {
 				clear_bit (block, &page->bitmap [map]);
 				offset = (BITS_PER_LONG * map) + block;
 				offset *= pool->size;
@@ -1687,7 +1686,7 @@
 	block %= BITS_PER_LONG;
 
 #ifdef	CONFIG_PCIPOOL_DEBUG
-	if (page->bitmap [map] & (1 << block)) {
+	if (page->bitmap [map] & (1UL << block)) {
 		printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
 			pool->dev ? pool->dev->slot_name : NULL,
 			pool->name, dma);
@@ -1701,8 +1700,11 @@
 	set_bit (block, &page->bitmap [map]);
 	if (waitqueue_active (&pool->waitq))
 		wake_up (&pool->waitq);
-	else if (!is_page_busy (pool->blocks_per_page, page->bitmap))
-		pool_free_page (pool, page);
+	/*
+	 * Resist a temptation to do
+	 *    if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
+	 * it is not interrupt safe. Better have empty pages hang around.
+	 */
 	spin_unlock_irqrestore (&pool->lock, flags);
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.4.4/linux/drivers/pci/pci.ids	Sun Mar 25 18:14:20 2001
+++ linux/drivers/pci/pci.ids	Sat May 19 17:49:14 2001
@@ -1069,6 +1069,13 @@
 	000e  Hydra Mac I/O
 	0010  Heathrow Mac I/O
 	0017  Paddington Mac I/O
+	0018  UniNorth FireWire
+	0019  KeyLargo USB
+	001e  UniNorth PCI
+	001f  UniNorth PCI
+	0020  UniNorth AGP
+	0021  UniNorth GMAC
+	0022  KeyLargo Mac I/O
 106c  Hyundai Electronics America
 	8801  Dual Pentium ISA/PCI Motherboard
 	8802  PowerPC ISA/PCI Motherboard
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.4.4/linux/drivers/pci/proc.c	Fri Nov 17 16:51:47 2000
+++ linux/drivers/pci/proc.c	Sat May 19 12:48:33 2001
@@ -191,10 +191,109 @@
 	return nbytes;
 }
 
+struct pci_filp_private {
+	enum pci_mmap_state mmap_state;
+	int write_combine;
+};
+
+static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+#ifdef HAVE_PCI_MMAP
+	struct pci_filp_private *fpriv = file->private_data;
+#endif /* HAVE_PCI_MMAP */
+	int ret = 0;
+
+	switch (cmd) {
+	case PCIIOC_CONTROLLER:
+		ret = pci_controller_num(dev);
+		break;
+
+#ifdef HAVE_PCI_MMAP
+	case PCIIOC_MMAP_IS_IO:
+		fpriv->mmap_state = pci_mmap_io;
+		break;
+
+	case PCIIOC_MMAP_IS_MEM:
+		fpriv->mmap_state = pci_mmap_mem;
+		break;
+
+	case PCIIOC_WRITE_COMBINE:
+		if (arg)
+			fpriv->write_combine = 1;
+		else
+			fpriv->write_combine = 0;
+		break;
+
+#endif /* HAVE_PCI_MMAP */
+
+	default:
+		ret = -EINVAL;
+		break;
+	};
+
+	return ret;
+}
+
+#ifdef HAVE_PCI_MMAP
+static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+	struct pci_filp_private *fpriv = file->private_data;
+	int ret;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	ret = pci_mmap_page_range(dev, vma,
+				  fpriv->mmap_state,
+				  fpriv->write_combine);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int proc_bus_pci_open(struct inode *inode, struct file *file)
+{
+	struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
+
+	if (!fpriv)
+		return -ENOMEM;
+
+	fpriv->mmap_state = pci_mmap_io;
+	fpriv->write_combine = 0;
+
+	file->private_data = fpriv;
+
+	return 0;
+}
+
+static int proc_bus_pci_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	file->private_data = NULL;
+
+	return 0;
+}
+#endif /* HAVE_PCI_MMAP */
+
 static struct file_operations proc_bus_pci_operations = {
-	llseek:	proc_bus_pci_lseek,
-	read:	proc_bus_pci_read,
-	write:	proc_bus_pci_write,
+	llseek:		proc_bus_pci_lseek,
+	read:		proc_bus_pci_read,
+	write:		proc_bus_pci_write,
+	ioctl:		proc_bus_pci_ioctl,
+#ifdef HAVE_PCI_MMAP
+	open:		proc_bus_pci_open,
+	release:	proc_bus_pci_release,
+	mmap:		proc_bus_pci_mmap,
+#ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+	get_unmapped_area: get_pci_unmapped_area,
+#endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
+#endif /* HAVE_PCI_MMAP */
 };
 
 #if BITS_PER_LONG == 32
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- v2.4.4/linux/drivers/pci/quirks.c	Thu Apr 19 22:57:06 2001
+++ linux/drivers/pci/quirks.c	Sat May 19 17:43:06 2001
@@ -12,6 +12,7 @@
  *  use the PowerTweak utility (see http://powertweak.sourceforge.net).
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -31,7 +32,7 @@
 	while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
 		pci_read_config_byte(d, 0x82, &dlc);
 		if (!(dlc & 1<<1)) {
-			printk("PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name);
+			printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name);
 			dlc |= 1<<1;
 			pci_write_config_byte(d, 0x82, dlc);
 		}
@@ -88,23 +89,44 @@
  *	VIA Apollo KT133 needs PCI latency patch
  *	Made according to a windows driver based patch by George E. Breese
  *	see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
+ *      Also see http://home.tiscalinet.de/au-ja/review-kt133a-1-en.html for
+ *      the info on which Mr Breese based his work.
  */
 static void __init quirk_vialatency(struct pci_dev *dev)
 {
 	u8 r70;
-
-	printk(KERN_INFO "Applying VIA PCI latency patch.\n");
-	/*
-	 *    In register 0x70, mask off bit 2 (PCI Master read caching)
-	 *    and 1 (Delay Transaction)
-	 */
-	pci_read_config_byte(dev, 0x70, &r70);
-	r70 &= 0xf9;
-	pci_write_config_byte(dev, 0x70, r70);
-	/*
-	 *    Turn off PCI Latency timeout (set to 0 clocks)
+	u8 rev;
+	struct pci_dev *vt82c686;
+   
+   
+	/* we want to look for a VT82C686 south bridge, and then apply the via latency
+	 * patch if we find that it's a 686B (by revision) <cpbotha@ieee.org>
 	 */
-	pci_write_config_byte(dev, 0x75, 0x80);
+	vt82c686 = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
+	if (vt82c686)   
+     	{
+		pci_read_config_byte(vt82c686, PCI_CLASS_REVISION, &rev);
+        	/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
+		if (rev >= 0x40 && rev <= 0x4f)
+		{
+        		printk(KERN_INFO "Applying VIA PCI latency patch (found VT82C686B).\n");
+			/*
+	 		 *    In register 0x70, mask off bit 2 (PCI Master read caching)
+	 		 *    and 1 (Delay Transaction)
+	 		 */
+			pci_read_config_byte(dev, 0x70, &r70);
+			r70 &= 0xf9;
+			pci_write_config_byte(dev, 0x70, r70);
+			/*
+	 	 	 *    Turn off PCI Latency timeout (set to 0 clocks)
+	 	 	 */
+			pci_write_config_byte(dev, 0x75, 0x80);
+		}
+		else
+		{
+			printk(KERN_INFO "Found VT82C686A, not applying VIA latency patch.\n");
+		}
+	} /* if (vt82c686) ... */
 }
 
 /*
@@ -238,6 +260,30 @@
 	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
 }
 
+
+#ifdef CONFIG_X86_IO_APIC 
+extern int nr_ioapics;
+
+/*
+ * VIA 686A/B: If an IO-APIC is active, we need to route all on-chip
+ * devices to the external APIC.
+ */
+static void __init quirk_via_ioapic(struct pci_dev *dev)
+{
+	u8 tmp;
+	
+	if (nr_ioapics < 1)
+		tmp = 0;    /* nothing routed to external APIC */
+	else
+		tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
+		
+	/* Offset 0x58: External APIC IRQ output control */
+	pci_write_config_byte (dev, 0x58, tmp);
+}
+
+#endif /* CONFIG_X86_IO_APIC */
+
+
 /*
  * PIIX3 USB: We have to disable USB interrupts that are
  * hardwired to PIRQD# and may be shared with an
@@ -322,6 +368,11 @@
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb },
 	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy },
+
+#ifdef CONFIG_X86_IO_APIC 
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic },
+#endif
+
 	{ 0 }
 };
 
@@ -333,7 +384,7 @@
  		    (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
 #ifdef DEBUG
-			printk("PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);
+			printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);
 #endif
 			f->hook(dev);
 		}
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/setup-bus.c linux/drivers/pci/setup-bus.c
--- v2.4.4/linux/drivers/pci/setup-bus.c	Mon Dec 11 13:46:26 2000
+++ linux/drivers/pci/setup-bus.c	Sat May 19 17:43:06 2001
@@ -136,9 +136,9 @@
 	ranges.mem_end = bus->resource[1]->end;
 	pcibios_fixup_pbus_ranges(bus, &ranges);
 
-	DBGC(("PCI: Bus %d, bridge: %s\n", bus->number, bridge->name));
-	DBGC(("  IO window: %04lx-%04lx\n", ranges.io_start, ranges.io_end));
-	DBGC(("  MEM window: %08lx-%08lx\n", ranges.mem_start, ranges.mem_end));
+	DBGC((KERN_ERR "PCI: Bus %d, bridge: %s\n", bus->number, bridge->name));
+	DBGC((KERN_ERR "  IO window: %04lx-%04lx\n", ranges.io_start, ranges.io_end));
+	DBGC((KERN_ERR "  MEM window: %08lx-%08lx\n", ranges.mem_start, ranges.mem_end));
 
 	/* Set up the top and bottom of the PCI I/O segment for this bus. */
 	pci_read_config_dword(bridge, PCI_IO_BASE, &l);
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/setup-irq.c linux/drivers/pci/setup-irq.c
--- v2.4.4/linux/drivers/pci/setup-irq.c	Tue Jan 11 14:22:31 2000
+++ linux/drivers/pci/setup-irq.c	Sat May 19 17:43:06 2001
@@ -53,7 +53,7 @@
 		irq = 0;
 	dev->irq = irq;
 
-	DBGC(("PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
+	DBGC((KERN_ERR "PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
 
 	/* Always tell the device, so the driver knows what is
 	   the real IRQ to use; the device does not use it. */
diff -u --recursive --new-file v2.4.4/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
--- v2.4.4/linux/drivers/pci/setup-res.c	Fri Apr  6 10:51:19 2001
+++ linux/drivers/pci/setup-res.c	Sat May 19 17:43:06 2001
@@ -115,12 +115,13 @@
 		 * window (it will just not perform as well).
 		 */
 		if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
-			printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", i, dev->name);
+			printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
+			       i, res->start, res->end, dev->slot_name);
 			return -EBUSY;
 		}
 	}
 
-	DBGC(("  got res[%lx:%lx] for resource %d of %s\n", res->start,
+	DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n", res->start,
 						res->end, i, dev->name));
 
 	return 0;
@@ -164,7 +165,7 @@
 			if (r_size > size) {
 				tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
 				if (!tmp) {
-					printk("pdev_sort_resources(): kmalloc() failed!\n");
+					printk(KERN_ERR "pdev_sort_resources(): kmalloc() failed!\n");
 					continue;
 				}
 				tmp->next = ln;
@@ -184,7 +185,7 @@
 	u16 cmd;
 	int i;
 
-	DBGC(("PCI enable device: (%s)\n", dev->name));
+	DBGC((KERN_ERR "PCI enable device: (%s)\n", dev->name));
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 
@@ -229,5 +230,5 @@
 	/* Enable the appropriate bits in the PCI command register.  */
 	pci_write_config_word(dev, PCI_COMMAND, cmd);
 
-	DBGC(("  cmd reg 0x%x\n", cmd));
+	DBGC((KERN_ERR "  cmd reg 0x%x\n", cmd));
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.4.4/linux/drivers/pcmcia/i82365.c	Sat Mar  3 10:50:29 2001
+++ linux/drivers/pcmcia/i82365.c	Tue May  1 16:05:00 2001
@@ -257,23 +257,31 @@
 
 /*====================================================================*/
 
+static spinlock_t bus_lock = SPIN_LOCK_UNLOCKED;
+
 static u_char i365_get(u_short sock, u_short reg)
 {
+    unsigned long flags;
+    spin_lock_irqsave(&bus_lock,flags);
     {
 	ioaddr_t port = socket[sock].ioaddr;
 	u_char val;
 	reg = I365_REG(socket[sock].psock, reg);
 	outb(reg, port); val = inb(port+1);
+	spin_unlock_irqrestore(&bus_lock,flags);
 	return val;
     }
 }
 
 static void i365_set(u_short sock, u_short reg, u_char data)
 {
+    unsigned long flags;
+    spin_lock_irqsave(&bus_lock,flags);
     {
 	ioaddr_t port = socket[sock].ioaddr;
 	u_char val = I365_REG(socket[sock].psock, reg);
 	outb(val, port); outb(data, port+1);
+	spin_unlock_irqrestore(&bus_lock,flags);
     }
 }
 
@@ -872,6 +880,13 @@
 		events = pending_events[i];
 		pending_events[i] = 0;
 		spin_unlock_irq(&pending_event_lock);
+		/* 
+		SS_DETECT events need a small delay here. The reason for this is that 
+		the "is there a card" electronics need time to see the card after the
+		"we have a card coming in" electronics have seen it. 
+		*/
+		if (events & SS_DETECT) 
+			mdelay(2);
 		if (socket[i].handler)
 			socket[i].handler(socket[i].info, events);
 	}
@@ -881,6 +896,8 @@
 	routine:	pcic_bh
 };
 
+static unsigned long last_detect_jiffies;
+
 static void pcic_interrupt(int irq, void *dev,
 				    struct pt_regs *regs)
 {
@@ -906,6 +923,20 @@
 		continue;
 	    }
 	    events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
+	    
+	    
+	    /* Several sockets will send multiple "new card detected"
+	       events in rapid succession. However, the rest of the pcmcia expects 
+	       only one such event. We just ignore these events by having a
+               timeout */
+
+	    if (events) {
+	    	if ((jiffies - last_detect_jiffies)<(HZ/20)) 
+	    		events = 0;
+	    	last_detect_jiffies = jiffies;
+	    	
+	    }
+	
 	    if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
 		events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
 	    else {
@@ -970,6 +1001,7 @@
     status = i365_get(sock, I365_STATUS);
     *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
 	? SS_DETECT : 0;
+	
     if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
 	*value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
     else {
@@ -1247,7 +1279,7 @@
     i = i365_get_pair(sock, base+I365_W_START);
     mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
     mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
-    mem->sys_start += ((u_long)(i & 0x0fff) << 12);
+    mem->sys_start = ((u_long)(i & 0x0fff) << 12);
     
     i = i365_get_pair(sock, base+I365_W_STOP);
     mem->speed  = (i & I365_MEM_WS0) ? 1 : 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- v2.4.4/linux/drivers/s390/block/dasd.c	Wed Apr 11 19:02:28 2001
+++ linux/drivers/s390/block/dasd.c	Tue May 15 01:29:34 2001
@@ -2892,7 +2892,7 @@
 static ssize_t
 dasd_devices_write (struct file *file, const char *user_buf, size_t user_len, loff_t * offset)
 {
-	char *buffer = vmalloc (user_len);
+	char *buffer = vmalloc (user_len+1);
 	int off = 0;
 	char *temp;
         int irq;
diff -u --recursive --new-file v2.4.4/linux/drivers/s390/char/hwc_tty.c linux/drivers/s390/char/hwc_tty.c
--- v2.4.4/linux/drivers/s390/char/hwc_tty.c	Thu Apr 12 12:16:35 2001
+++ linux/drivers/s390/char/hwc_tty.c	Tue May 22 10:23:16 2001
@@ -217,7 +217,7 @@
 void 
 hwc_tty_init (void)
 {
-#ifdef CONFIG_3215
+#if defined(CONFIG_3215_CONSOLE) || defined(CONFIG_3270_CONSOLE)
 	if (MACHINE_IS_VM)
 		return;
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- v2.4.4/linux/drivers/sbus/char/aurora.c	Sun Mar 25 18:14:20 2001
+++ linux/drivers/sbus/char/aurora.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/*	$Id: aurora.c,v 1.11 2001/03/08 01:43:30 davem Exp $
+/*	$Id: aurora.c,v 1.13 2001/05/10 01:45:38 davem Exp $
  *	linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
  *
  *	Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -1632,33 +1632,55 @@
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 
-	if (from_user)
-		down(&tmp_buf_sem);
-
 	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0)
+				break;
 
-		if (from_user) {
-			copy_from_user(tmp_buf, buf, c);
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-		} else
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&tmp_buf_sem);
+
+	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->SRER & SRER_TXRDY)) {
 		port->SRER |= SRER_TXRDY;
diff -u --recursive --new-file v2.4.4/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.4.4/linux/drivers/sbus/char/pcikbd.c	Sun Mar 25 18:14:20 2001
+++ linux/drivers/sbus/char/pcikbd.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.53 2001/03/21 00:28:33 davem Exp $
+/* $Id: pcikbd.c,v 1.54 2001/05/11 07:46:28 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -28,6 +28,9 @@
 #include <linux/init.h>
 
 #include <asm/ebus.h>
+#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)
+#include <asm/isa.h>
+#endif
 #include <asm/oplib.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -451,6 +454,47 @@
 	}
 	restore_flags(flags);
 }
+
+#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)
+static void isa_kd_nosound(unsigned long __unused)
+{
+	/* disable counter 2 */
+	outb(inb(pcibeep_iobase + 0x61)&0xFC, pcibeep_iobase + 0x61);
+	return;
+}
+
+static void isa_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+	static struct timer_list sound_timer = { function: isa_kd_nosound };
+	unsigned int count = 0;
+	unsigned long flags;
+
+	if (hz > 20 && hz < 32767)
+		count = 1193180 / hz;
+	
+	save_flags(flags);
+	cli();
+	del_timer(&sound_timer);
+	if (count) {
+		/* enable counter 2 */
+		outb(inb(pcibeep_iobase + 0x61)|3, pcibeep_iobase + 0x61);
+		/* set command for counter 2, 2 byte write */
+		outb(0xB6, pcibeep_iobase + 0x43);
+		/* select desired HZ */
+		outb(count & 0xff, pcibeep_iobase + 0x42);
+		outb((count >> 8) & 0xff, pcibeep_iobase + 0x42);
+
+		if (ticks) {
+			sound_timer.expires = jiffies+ticks;
+			add_timer(&sound_timer);
+		}
+	} else
+		isa_kd_nosound(0);
+	restore_flags(flags);
+	return;
+}
+#endif
+
 #endif
 
 static void nop_kd_mksound(unsigned int hz, unsigned int ticks)
@@ -550,6 +594,30 @@
 				}
 			}
 		}
+
+#ifdef CONFIG_SPARC64
+		/* Maybe we have one inside the ALI southbridge? */
+		{
+			struct isa_bridge *isa_br;
+			struct isa_device *isa_dev;
+			for_each_isa(isa_br) {
+				for_each_isadev(isa_dev, isa_br) {
+					/* This is a hack, the 'dma' device node has
+					 * the base of the I/O port space for that PBM
+					 * as it's resource, so we use that. -DaveM
+					 */
+					if (!strcmp(isa_dev->prom_name, "dma")) {
+						pcibeep_iobase = isa_dev->resource.start;
+						kd_mksound = isa_kd_mksound;
+						printk("isa(speaker): iobase[%016lx:%016lx]\n",
+						       pcibeep_iobase + 0x42,
+						       pcibeep_iobase + 0x61);
+						return;
+					}
+				}
+			}
+		}
+#endif
 
 		/* No beeper found, ok complain. */
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.4.4/linux/drivers/sbus/char/su.c	Thu Apr 26 22:17:26 2001
+++ linux/drivers/sbus/char/su.c	Sat May 19 12:48:33 2001
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.47 2001/04/18 21:06:15 davem Exp $
+/* $Id: su.c,v 1.50 2001/05/16 08:37:03 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -75,6 +75,9 @@
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/ebus.h>
+#ifdef CONFIG_SPARC64
+#include <asm/isa.h>
+#endif
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -1411,6 +1414,41 @@
  */
 
 /*
+ * get_serial_info - handle TIOCGSERIAL ioctl()
+ *
+ * Purpose: Return standard serial struct information about
+ *          a serial port handled by this driver.
+ *
+ * Added:   11-May-2001 Lars Kellogg-Stedman <lars@larsshack.org>
+ */
+static int get_serial_info(struct su_struct * info,
+			   struct serial_struct * retinfo)
+{
+	struct serial_struct	tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+
+	tmp.type		= info->type;
+	tmp.line		= info->line;
+	tmp.port		= info->port;
+	tmp.irq			= info->irq;
+	tmp.flags		= info->flags;
+	tmp.xmit_fifo_size	= info->xmit_fifo_size;
+	tmp.baud_base		= info->baud_base;
+	tmp.close_delay		= info->close_delay;
+	tmp.closing_wait	= info->closing_wait;
+	tmp.custom_divisor	= info->custom_divisor;
+	tmp.hub6		= 0;
+
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
  * get_lsr_info - get line status register info
  *
  * Purpose: Let user call ioctl() to get info when the UART physically
@@ -1568,6 +1606,9 @@
 		case TIOCMSET:
 			return set_modem_info(info, cmd, (unsigned int *) arg);
 
+		case TIOCGSERIAL:
+			return get_serial_info(info, (struct serial_struct *)arg);
+
 		case TIOCSERGETLSR: /* Get line status register */
 			return get_lsr_info(info, (unsigned int *) arg);
 
@@ -2220,7 +2261,7 @@
  */
 static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.47 $";
+	char *revision = "$Revision: 1.50 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2243,6 +2284,10 @@
 	unsigned char status1, status2, scratch, scratch2;
 	struct linux_ebus_device *dev = 0;
 	struct linux_ebus *ebus;
+#ifdef CONFIG_SPARC64
+	struct isa_bridge *isa_br;
+	struct isa_device *isa_dev;
+#endif
 #ifndef __sparc_v9__
 	struct linux_prom_registers reg0;
 #endif
@@ -2263,6 +2308,18 @@
 			}
 		}
 	}
+
+#ifdef CONFIG_SPARC64
+	for_each_isa(isa_br) {
+		for_each_isadev(isa_dev, isa_br) {
+			if (isa_dev->prom_node == info->port_node) {
+				info->port = isa_dev->resource.start;
+				info->irq = isa_dev->irq;
+				goto ebus_done;
+			}
+		}
+	}
+#endif
 
 #ifdef __sparc_v9__
 	/*
diff -u --recursive --new-file v2.4.4/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- v2.4.4/linux/drivers/sbus/char/zs.c	Thu Apr 26 22:17:26 2001
+++ linux/drivers/sbus/char/zs.c	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.63 2001/04/17 06:30:36 davem Exp $
+/* $Id: zs.c,v 1.65 2001/05/09 07:00:10 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1156,28 +1156,51 @@
 		return 0;
 
 	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
-
-		if (from_user) {
-			down(&tmp_buf_sem);
-			copy_from_user(tmp_buf, buf, c);
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-			up(&tmp_buf_sem);
-		} else
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE - 1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		info->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE - 1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
 
 	cli();		
@@ -1922,7 +1945,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.63 $";
+	char *revision = "$Revision: 1.65 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/ChangeLog.ips linux/drivers/scsi/ChangeLog.ips
--- v2.4.4/linux/drivers/scsi/ChangeLog.ips	Tue Sep 19 08:01:34 2000
+++ linux/drivers/scsi/ChangeLog.ips	Sat May 19 17:43:06 2001
@@ -1,5 +1,25 @@
 IBM ServeRAID driver Change Log
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+        4.72.00  - Allow for a Scatter-Gather Element to exceed MAX_XFER Size     
+        
+        4.71.00  - Change all memory allocations to not use GFP_DMA flag 
+                   Code Clean-Up for 2.4.x kernel      
+        
+        4.70.15  - Fix Breakup for very large ( non-SG ) requests
+        
+        4.70.13  - Don't release HA Lock in ips_next() until SC taken off queue  
+                 - Unregister SCSI device in ips_release()                        
+                 - Don't Send CDB's if we already know the device is not present  
+                 
+        4.70.12  - Corrective actions for bad controller ( during initialization )
+        
+        4.70.09  - Use a Common ( Large Buffer ) for Flashing from the JCRM CD    
+                 - Add IPSSEND Flash Support                                      
+                 - Set Sense Data for Unknown SCSI Command                        
+                 - Use Slot Number from NVRAM Page 5 
+                 - Restore caller's DCDB Structure
+                                       
         4.20.14  - Update patch files for kernel 2.4.0-test5
 
         4.20.13  - Fix some failure cases / reset code
@@ -66,3 +86,4 @@
                 - Fixed read/write errors when the adapter is using an
                   8K stripe size.
 
+
\ No newline at end of file
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.4.4/linux/drivers/scsi/Makefile	Mon Mar 26 15:36:30 2001
+++ linux/drivers/scsi/Makefile	Fri May  4 15:16:28 2001
@@ -6,6 +6,12 @@
 #
 # 20 Sep 2000, Torben Mathiasen <tmm@image.dk>
 # Changed link order to reflect new scsi initialization.
+#
+# *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
+# The link order must be, SCSI Core, SCSI HBA drivers, and
+# lastly SCSI peripheral drivers (disk/tape/cdrom/etc.) to
+# satisfy certain initialization assumptions in the SCSI layer.
+# *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
 
 O_TARGET := scsidrv.o
 
@@ -64,6 +70,9 @@
 obj-$(CONFIG_SCSI_AHA152X)	+= aha152x.o
 obj-$(CONFIG_SCSI_AHA1542)	+= aha1542.o
 obj-$(CONFIG_SCSI_AHA1740)	+= aha1740.o
+ifeq ($(CONFIG_SCSI_AIC7XXX),y)
+obj-$(CONFIG_SCSI_AIC7XXX)	+= aic7xxx/aic7xxx_drv.o
+endif
 obj-$(CONFIG_SCSI_AIC7XXX_OLD)	+= aic7xxx_old.o
 obj-$(CONFIG_SCSI_IPS)		+= ips.o
 obj-$(CONFIG_SCSI_FD_MCS)	+= fd_mcs.o
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c
--- v2.4.4/linux/drivers/scsi/NCR53c406a.c	Fri Mar  2 11:12:11 2001
+++ linux/drivers/scsi/NCR53c406a.c	Tue May 22 10:23:16 2001
@@ -508,6 +508,7 @@
                     VDEB(printk("port_base=%x\n", port_base));
                     break;
                 }
+                release_region(ports[i], 0x10);
             }
         }
     }
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/README.ibmmca linux/drivers/scsi/README.ibmmca
--- v2.4.4/linux/drivers/scsi/README.ibmmca	Thu Jan  4 12:37:14 2001
+++ linux/drivers/scsi/README.ibmmca	Tue May 22 10:23:16 2001
@@ -736,7 +736,7 @@
       
    Feb 20, 1999 (v3.1e)
    1) I took the warning from the Linux Kernel Hackers Guide serious and 
-      checked the cmd->result return value to the done-function very carefuly.
+      checked the cmd->result return value to the done-function very carefully.
       It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
       some error appeared, else it is undefined. Now, this is fixed. Before
       any SCB command gets queued, the tsb.dev_status is set to 0, so the 
@@ -1382,7 +1382,7 @@
    
    9 Disclaimer
    ------------
-   Beside the GNU public license and the dependant disclaimers and disclaimers
+   Beside the GNU General Public License and the dependant disclaimers and disclaimers
    concerning the Linux-kernel in special, this SCSI-driver comes without any
    warranty. Its functionality is tested as good as possible on certain 
    machines and combinations of computer hardware, which does not exclude,
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v2.4.4/linux/drivers/scsi/aha1542.c	Tue Mar  6 19:44:37 2001
+++ linux/drivers/scsi/aha1542.c	Tue May  1 16:05:00 2001
@@ -254,7 +254,7 @@
 /* Only used at boot time, so we do not need to worry about latency as much
    here */
 
-static int aha1542_in(unsigned int base, unchar * cmdp, int len)
+static int __init aha1542_in(unsigned int base, unchar * cmdp, int len)
 {
 	unsigned long flags;
 
@@ -276,7 +276,7 @@
 /* Similar to aha1542_in, except that we wait a very short period of time.
    We use this if we know the board is alive and awake, but we are not sure
    if the board will respond to the command we are about to send or not */
-static int aha1542_in1(unsigned int base, unchar * cmdp, int len)
+static int __init aha1542_in1(unsigned int base, unchar * cmdp, int len)
 {
 	unsigned long flags;
 
@@ -886,7 +886,7 @@
 /* This function should only be called for 1542C boards - we can detect
    the special firmware settings and unlock the board */
 
-static int aha1542_mbenable(int base)
+static int __init aha1542_mbenable(int base)
 {
 	static unchar mbenable_cmd[3];
 	static unchar mbenable_result[2];
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/Config.in linux/drivers/scsi/aic7xxx/Config.in
--- v2.4.4/linux/drivers/scsi/aic7xxx/Config.in	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/Config.in	Fri May  4 15:16:28 2001
@@ -2,6 +2,7 @@
    dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
    if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
       int  '  Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 253
-      int  '  Initial bus reset delay in milli-seconds' CONFIG_AIC7XXX_RESET_DELAY 5000
+      int  '  Initial bus reset delay in milli-seconds' CONFIG_AIC7XXX_RESET_DELAY_MS 15000
+      bool  '  Build Adapter Firmware with Kernel Build' CONFIG_AIC7XXX_BUILD_FIRMWARE
    fi
 fi
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/Makefile linux/drivers/scsi/aic7xxx/Makefile
--- v2.4.4/linux/drivers/scsi/aic7xxx/Makefile	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/Makefile	Fri May  4 15:16:28 2001
@@ -4,7 +4,7 @@
 # Makefile for the Linux aic7xxx SCSI driver.
 #
 
-O_TARGET = aic7xxx_drv.o
+O_TARGET := aic7xxx_drv.o
 
 list-multi	:= aic7xxx_mod.o
 
@@ -25,8 +25,13 @@
 aic7xxx_mod.o: aic7xxx_seq.h aic7xxx_reg.h $(AIC7XXX_OBJS)
 	$(LD) $(LD_RFLAG) -r -o $@ $(AIC7XXX_OBJS)
 
+ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
 aic7xxx_seq.h aic7xxx_reg.h: aic7xxx.seq aic7xxx.reg aicasm/aicasm
 	aicasm/aicasm -I. -r aic7xxx_reg.h -o aic7xxx_seq.h aic7xxx.seq
+else
+aic7xxx_seq.h aic7xxx_reg.h: aic7xxx.seq aic7xxx.reg
+	echo "Warning, generated aic7xxx firmware files may be out of date!\n"
+endif
 
 aicasm/aicasm: aicasm/*.[chyl]
 	$(MAKE) -C aicasm
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7770.c linux/drivers/scsi/aic7xxx/aic7770.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7770.c	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7770.c	Fri May  4 15:16:28 2001
@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7770.c#6 $
+ * $Id: //depot/src/aic7xxx/aic7770.c#11 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7770.c,v 1.1 2000/09/16 20:02:27 gibbs Exp $
  */
@@ -95,8 +95,6 @@
 	u_int	hostconf;
 	u_int   irq;
 	u_int	intdef;
-	u_int	hcntrl;
-	int	shared;
 
 	ahc_init_probe_config(&probe_config);
 	error = entry->setup(ahc->dev_softc, &probe_config);
@@ -107,15 +105,15 @@
 	if (error != 0)
 		return (error);
 
-	/* Pause the card preseving the IRQ type */
-	hcntrl = ahc_inb(ahc, HCNTRL) & IRQMS;
-	ahc_outb(ahc, HCNTRL, hcntrl | PAUSE);
-	while ((ahc_inb(ahc, HCNTRL) & PAUSE) == 0)
-		;
+	probe_config.description = entry->name;
+	error = ahc_softc_init(ahc, &probe_config);
+
+	error = ahc_reset(ahc);
+	if (error != 0)
+		return (error);
 
 	/* Make sure we have a valid interrupt vector */
 	intdef = ahc_inb(ahc, INTDEF);
-	shared = (intdef & EDGE_TRIG) ? 0 : 1;
 	irq = intdef & VECTOR;
 	switch (irq) {
 	case 9:
@@ -130,16 +128,8 @@
 		return (ENXIO);
 	}
 
-	probe_config.description = entry->name;
-	error = ahc_softc_init(ahc, &probe_config);
-
-	error = aic7770_map_int(ahc, irq, shared);
-	if (error != 0)
-		return (error);
-
-	error = ahc_reset(ahc);
-	if (error != 0)
-		return (error);
+	if ((intdef & EDGE_TRIG) != 0)
+		ahc->flags |= AHC_EDGE_INTERRUPT;
 
 	switch (probe_config.chip & (AHC_EISA|AHC_VL)) {
 	case AHC_EISA:
@@ -154,7 +144,7 @@
 
 		/* Get the primary channel information */
 		if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
-			ahc->flags |= AHC_CHANNEL_B_PRIMARY;
+			ahc->flags |= 1;
 
 		if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
 			ahc->flags |= AHC_USEDEFAULTS;
@@ -210,10 +200,19 @@
 	 */
 	ahc_softc_insert(ahc);
 
+	error = aic7770_map_int(ahc, irq);
+	if (error != 0)
+		return (error);
+
 	/*
 	 * Enable the board's BUS drivers
 	 */
 	ahc_outb(ahc, BCTL, ENABLE);
+
+	/*
+	 * Allow interrupts.
+	 */
+	ahc_intr_enable(ahc, TRUE);
 
 	return (0);
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7770_linux.c linux/drivers/scsi/aic7xxx/aic7770_linux.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7770_linux.c	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7770_linux.c	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7770_linux.c#5 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7770_linux.c#7 $
  */
 
 #include "aic7xxx_osm.h"
@@ -128,19 +128,18 @@
 }
 
 int
-aic7770_map_int(struct ahc_softc *ahc, u_int irq, int shared)
+aic7770_map_int(struct ahc_softc *ahc, u_int irq)
 {
 	int error;
+	int shared;
 
-	if (shared)
+	shared = 0;
+	if ((ahc->flags & AHC_EDGE_INTERRUPT) == 0)
 		shared = SA_SHIRQ;
 
 	ahc->platform_data->irq = irq;
-	error = request_irq(ahc->platform_data->irq, aic7xxx_isr,
-			    SA_INTERRUPT|shared, "aic7xxx", ahc);
-	if (error < 0)
-		error = request_irq(ahc->platform_data->irq, aic7xxx_isr,
-				    shared, "aic7xxx", ahc);
+	error = request_irq(ahc->platform_data->irq, ahc_linux_isr,
+			    shared, "aic7xxx", ahc);
 	
 	return (-error);
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.c linux/drivers/scsi/aic7xxx/aic7xxx.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.c	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx.c	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx.c#32 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#39 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.61 2000/11/13 03:35:43 gibbs Exp $
  */
@@ -58,9 +58,17 @@
 	"aic7892",
 	"aic7899"
 };
-const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
+static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
 
-struct hard_error_entry hard_error[] = {
+/*
+ * Hardware error codes.
+ */
+struct ahc_hard_error_entry {
+        uint8_t errno;
+	char *errmesg;
+};
+
+static struct ahc_hard_error_entry ahc_hard_errors[] = {
 	{ ILLHADDR,	"Illegal Host Access" },
 	{ ILLSADDR,	"Illegal Sequencer Address referrenced" },
 	{ ILLOPCODE,	"Illegal Opcode in sequencer program" },
@@ -70,9 +78,9 @@
 	{ PCIERRSTAT,	"PCI Error detected" },
 	{ CIOPARERR,	"CIOBUS Parity Error" },
 };
-const u_int num_errors = NUM_ELEMENTS(hard_error);
+static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors);
 
-struct phase_table_entry phase_table[] =
+static struct ahc_phase_table_entry ahc_phase_table[] =
 {
 	{ P_DATAOUT,	MSG_NOOP,		"in Data-out phase"	},
 	{ P_DATAIN,	MSG_INITIATOR_DET_ERR,	"in Data-in phase"	},
@@ -90,14 +98,14 @@
  * In most cases we only wish to itterate over real phases, so
  * exclude the last element from the count.
  */
-const u_int num_phases = NUM_ELEMENTS(phase_table) - 1;
+static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1;
 
 /*
  * Valid SCSIRATE values.  (p. 3-17)
  * Provides a mapping of tranfer periods in ns to the proper value to
  * stick in the scsixfer reg.
  */
-struct ahc_syncrate ahc_syncrates[] =
+static struct ahc_syncrate ahc_syncrates[] =
 {
       /* ultra2    fast/ultra  period     rate */
 	{ 0x42,      0x000,      9,      "80.0" },
@@ -121,7 +129,7 @@
 #include "aic7xxx_seq.h"
 
 /**************************** Function Declarations ***************************/
-static struct tmode_tstate*
+static struct ahc_tmode_tstate*
 			ahc_alloc_tstate(struct ahc_softc *ahc,
 					 u_int scsi_id, char channel);
 #ifdef AHC_TARGET_MODE
@@ -134,12 +142,13 @@
 						u_int *period,
 						u_int *ppr_options,
 						role_t role);
-static void		ahc_update_pending_syncrates(struct ahc_softc *ahc);
+static void		ahc_update_pending_scbs(struct ahc_softc *ahc);
 static void		ahc_fetch_devinfo(struct ahc_softc *ahc,
 					  struct ahc_devinfo *devinfo);
 static void		ahc_scb_devinfo(struct ahc_softc *ahc,
 					struct ahc_devinfo *devinfo,
 					struct scb *scb);
+static void		ahc_assert_atn(struct ahc_softc *ahc);
 static void		ahc_setup_initiator_msgout(struct ahc_softc *ahc,
 						   struct ahc_devinfo *devinfo,
 						   struct scb *scb);
@@ -174,6 +183,11 @@
 					    struct ahc_devinfo *devinfo,
 					    cam_status status, char *message,
 					    int verbose_level);
+#if AHC_TARGET_MODE
+static void		ahc_setup_target_msgin(struct ahc_softc *ahc,
+					       struct ahc_devinfo *devinfo,
+					       struct scb *scb);
+#endif
 
 static bus_dmamap_callback_t	ahc_dmamap_cb; 
 static void			ahc_build_free_scb_list(struct ahc_softc *ahc);
@@ -192,7 +206,6 @@
 				       char channel, int lun, u_int tag,
 				       role_t role, uint32_t status);
 static void		ahc_reset_current_bus(struct ahc_softc *ahc);
-static void		ahc_calc_residual(struct scb *scb);
 #ifdef AHC_DUMP_SEQ
 static void		ahc_dumpseq(struct ahc_softc *ahc);
 #endif
@@ -204,7 +217,7 @@
 					   u_int instrptr, uint8_t *dconsts);
 #ifdef AHC_TARGET_MODE
 static void		ahc_queue_lstate_event(struct ahc_softc *ahc,
-					       struct tmode_lstate *lstate,
+					       struct ahc_tmode_lstate *lstate,
 					       u_int initiator_id,
 					       u_int event_type,
 					       u_int event_arg);
@@ -218,10 +231,10 @@
  * Restart the sequencer program from address zero
  */
 void
-restart_sequencer(struct ahc_softc *ahc)
+ahc_restart(struct ahc_softc *ahc)
 {
 
-	pause_sequencer(ahc);
+	ahc_pause(ahc);
 
 	ahc_outb(ahc, SCSISIGO, 0);		/* De-assert BSY */
 	ahc_outb(ahc, MSG_OUT, MSG_NOOP);	/* No message to send */
@@ -259,7 +272,7 @@
 	ahc_outb(ahc, SEQCTL, FASTMODE);
 	ahc_outb(ahc, SEQADDR0, 0);
 	ahc_outb(ahc, SEQADDR1, 0);
-	unpause_sequencer(ahc);
+	ahc_unpause(ahc);
 }
 
 /************************* Input/Output Queues ********************************/
@@ -300,10 +313,7 @@
 		 * Save off the residual
 		 * if there is one.
 		 */
-		if (ahc_check_residual(scb) != 0)
-			ahc_calc_residual(scb);
-		else
-			ahc_set_residual(scb, 0);
+		ahc_update_residual(scb);
 		ahc_done(ahc, scb);
 	}
 }
@@ -340,14 +350,14 @@
 	 * We upset the sequencer :-(
 	 * Lookup the error message
 	 */
-	int i, error, num_errors;
+	int i;
+	int error;
 
 	error = ahc_inb(ahc, ERROR);
-	num_errors =  sizeof(hard_error)/sizeof(hard_error[0]);
 	for (i = 0; error != 1 && i < num_errors; i++)
 		error >>= 1;
 	printf("%s: brkadrint, %s at seqaddr = 0x%x\n",
-	       ahc_name(ahc), hard_error[i].errmesg,
+	       ahc_name(ahc), ahc_hard_errors[i].errmesg,
 	       ahc_inb(ahc, SEQADDR0) |
 	       (ahc_inb(ahc, SEQADDR1) << 8));
 
@@ -436,6 +446,12 @@
 			break;
 		case SCSI_STATUS_CMD_TERMINATED:
 		case SCSI_STATUS_CHECK_COND:
+		{
+			struct ahc_dma_seg *sg;
+			struct scsi_sense *sc;
+			struct ahc_initiator_tinfo *targ_info;
+			struct ahc_tmode_tstate *tstate;
+			struct ahc_transinfo *tinfo;
 #ifdef AHC_DEBUG
 			if (ahc_debug & AHC_SHOWSENSE) {
 				ahc_print_path(ahc, scb);
@@ -444,99 +460,94 @@
 			}
 #endif
 
-			if (ahc_perform_autosense(scb)) {
-				struct ahc_dma_seg *sg;
-				struct scsi_sense *sc;
-				struct ahc_initiator_tinfo *targ_info;
-				struct tmode_tstate *tstate;
-				struct ahc_transinfo *tinfo;
+			if (ahc_perform_autosense(scb) == 0)
+				break;
 
-				targ_info =
-				    ahc_fetch_transinfo(ahc,
+			targ_info = ahc_fetch_transinfo(ahc,
 							devinfo.channel,
 							devinfo.our_scsiid,
 							devinfo.target,
 							&tstate);
-				tinfo = &targ_info->current;
-				sg = scb->sg_list;
-				sc = (struct scsi_sense *)
-				     (&hscb->shared_data.cdb); 
-				/*
-				 * Save off the residual if there is one.
-				 */
-				if (ahc_check_residual(scb))
-					ahc_calc_residual(scb);
-				else
-					ahc_set_residual(scb, 0);
+			tinfo = &targ_info->curr;
+			sg = scb->sg_list;
+			sc = (struct scsi_sense *)(&hscb->shared_data.cdb); 
+			/*
+			 * Save off the residual if there is one.
+			 */
+			ahc_update_residual(scb);
 #ifdef AHC_DEBUG
-				if (ahc_debug & AHC_SHOWSENSE) {
-					ahc_print_path(ahc, scb);
-					printf("Sending Sense\n");
-				}
+			if (ahc_debug & AHC_SHOWSENSE) {
+				ahc_print_path(ahc, scb);
+				printf("Sending Sense\n");
+			}
 #endif
-				sg->addr = ahc_get_sense_bufaddr(ahc, scb);
-				sg->len = ahc_get_sense_bufsize(ahc, scb);
-				sg->len |= AHC_DMA_LAST_SEG;
-
-				/* Fixup byte order */
-				sg->addr = ahc_htole32(sg->addr);
-				sg->len = ahc_htole32(sg->len);
-
-				sc->opcode = REQUEST_SENSE;
-				sc->byte2 = 0;
-				if (tinfo->protocol_version <= SCSI_REV_2
-				 && SCB_GET_LUN(scb) < 8)
-					sc->byte2 = SCB_GET_LUN(scb) << 5;
-				sc->unused[0] = 0;
-				sc->unused[1] = 0;
-				sc->length = sg->len;
-				sc->control = 0;
+			sg->addr = ahc_get_sense_bufaddr(ahc, scb);
+			sg->len = ahc_get_sense_bufsize(ahc, scb);
+			sg->len |= AHC_DMA_LAST_SEG;
+
+			/* Fixup byte order */
+			sg->addr = ahc_htole32(sg->addr);
+			sg->len = ahc_htole32(sg->len);
+
+			sc->opcode = REQUEST_SENSE;
+			sc->byte2 = 0;
+			if (tinfo->protocol_version <= SCSI_REV_2
+			 && SCB_GET_LUN(scb) < 8)
+				sc->byte2 = SCB_GET_LUN(scb) << 5;
+			sc->unused[0] = 0;
+			sc->unused[1] = 0;
+			sc->length = sg->len;
+			sc->control = 0;
 
-				/*
-				 * XXX Still true???
-				 * Would be nice to preserve DISCENB here,
-				 * but due to the way we manage busy targets,
-				 * we can't.
-				 */
-				hscb->control = 0;
+			/*
+			 * We can't allow the target to disconnect.
+			 * This will be an untagged transaction and
+			 * having the target disconnect will make this
+			 * transaction indestinguishable from outstanding
+			 * tagged transactions.
+			 */
+			hscb->control = 0;
 
-				/*
-				 * This request sense could be because the
-				 * the device lost power or in some other
-				 * way has lost our transfer negotiations.
-				 * Renegotiate if appropriate.  Unit attention
-				 * errors will be reported before any data
-				 * phases occur.
-				 */
-				if (ahc_get_residual(scb) 
-				 == ahc_get_transfer_length(scb)) {
-					ahc_update_target_msg_request(ahc,
-							      &devinfo,
-							      targ_info,
-							      /*force*/TRUE,
-							      /*paused*/TRUE);
-				}
-				hscb->cdb_len = sizeof(*sc);
-				hscb->dataptr = sg->addr; 
-				hscb->datacnt = sg->len;
-				hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
-				hscb->sgptr = ahc_htole32(hscb->sgptr);
-				scb->sg_count = 1;
-				scb->flags |= SCB_SENSE;
-				ahc_qinfifo_requeue_tail(ahc, scb);
-				ahc_outb(ahc, RETURN_1, SEND_SENSE);
+			/*
+			 * This request sense could be because the
+			 * the device lost power or in some other
+			 * way has lost our transfer negotiations.
+			 * Renegotiate if appropriate.  Unit attention
+			 * errors will be reported before any data
+			 * phases occur.
+			 */
+			if (ahc_get_residual(scb) 
+			 == ahc_get_transfer_length(scb)) {
+				ahc_update_neg_request(ahc, &devinfo,
+						       tstate, targ_info,
+						       /*force*/TRUE);
+			}
+			if (tstate->auto_negotiate & devinfo.target_mask) {
+				hscb->control |= MK_MESSAGE;
+				scb->flags &= ~SCB_NEGOTIATE;
+				scb->flags |= SCB_AUTO_NEGOTIATE;
+			}
+			hscb->cdb_len = sizeof(*sc);
+			hscb->dataptr = sg->addr; 
+			hscb->datacnt = sg->len;
+			hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
+			hscb->sgptr = ahc_htole32(hscb->sgptr);
+			scb->sg_count = 1;
+			scb->flags |= SCB_SENSE;
+			ahc_qinfifo_requeue_tail(ahc, scb);
+			ahc_outb(ahc, RETURN_1, SEND_SENSE);
 #ifdef __FreeBSD__
-				/*
-				 * Ensure we have enough time to actually
-				 * retrieve the sense.
-				 */
-				untimeout(ahc_timeout, (caddr_t)scb,
-					  scb->io_ctx->ccb_h.timeout_ch);
-				scb->io_ctx->ccb_h.timeout_ch =
-				    timeout(ahc_timeout, (caddr_t)scb, 5 * hz);
+			/*
+			 * Ensure we have enough time to actually
+			 * retrieve the sense.
+			 */
+			untimeout(ahc_timeout, (caddr_t)scb,
+				  scb->io_ctx->ccb_h.timeout_ch);
+			scb->io_ctx->ccb_h.timeout_ch =
+			    timeout(ahc_timeout, (caddr_t)scb, 5 * hz);
 #endif
-			}
 			break;
+		}
 		default:
 			break;
 		}
@@ -577,7 +588,7 @@
 		ahc->msgout_index = 0;
 		ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
 		ahc_outb(ahc, MSG_OUT, HOST_MSG);
-		ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, LASTPHASE) | ATNO);
+		ahc_assert_atn(ahc);
 		break;
 	}
 	case SEND_REJECT: 
@@ -633,7 +644,7 @@
 		       "Lastphase = 0x%x, Curphase = 0x%x\n",
 		       ahc_name(ahc), devinfo.channel, devinfo.target,
 		       lastphase, ahc_inb(ahc, SCSISIGI));
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 		return;
 	}
 	case HOST_MSG_LOOP:
@@ -650,6 +661,8 @@
 		 * loop.
 		 */
 		if (ahc->msg_type == MSG_TYPE_NONE) {
+			struct scb *scb;
+			u_int scb_index;
 			u_int bus_phase;
 
 			bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
@@ -663,17 +676,13 @@
 				 * we got here.  Just punt the message.
 				 */
 				ahc_clear_intstat(ahc);
-				restart_sequencer(ahc);
+				ahc_restart(ahc);
 				return;
 			}
 
+			scb_index = ahc_inb(ahc, SCB_TAG);
+			scb = ahc_lookup_scb(ahc, scb_index);
 			if (devinfo.role == ROLE_INITIATOR) {
-				struct scb *scb;
-				u_int scb_index;
-
-				scb_index = ahc_inb(ahc, SCB_TAG);
-				scb = ahc_lookup_scb(ahc, scb_index);
-
 				if (scb == NULL)
 					panic("HOST_MSG_LOOP with "
 					      "invalid SCB %x\n", scb_index);
@@ -695,7 +704,9 @@
 				}
 #if AHC_TARGET_MODE
 				else 
-					ahc_setup_target_msgin(ahc, &devinfo);
+					ahc_setup_target_msgin(ahc,
+							       &devinfo,
+							       scb);
 #endif
 			}
 		}
@@ -718,17 +729,20 @@
 		 */
 		if ((intstat & SCSIINT) == 0
 		 && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) {
-			u_int curphase;
 
-			/*
-			 * The hardware will only let you ack bytes
-			 * if the expected phase in SCSISIGO matches
-			 * the current phase.  Make sure this is
-			 * currently the case.
-			 */
-			curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
-			ahc_outb(ahc, LASTPHASE, curphase);
-			ahc_outb(ahc, SCSISIGO, curphase);
+			if ((ahc->features & AHC_DT) == 0) {
+				u_int curphase;
+
+				/*
+				 * The hardware will only let you ack bytes
+				 * if the expected phase in SCSISIGO matches
+				 * the current phase.  Make sure this is
+				 * currently the case.
+				 */
+				curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
+				ahc_outb(ahc, LASTPHASE, curphase);
+				ahc_outb(ahc, SCSISIGO, curphase);
+			}
 			ahc_inb(ahc, SCSIDATL);
 		}
 		break;
@@ -749,13 +763,13 @@
 
 		scb = ahc_lookup_scb(ahc, scbindex);
 		for (i = 0; i < num_phases; i++) {
-			if (lastphase == phase_table[i].phase)
+			if (lastphase == ahc_phase_table[i].phase)
 				break;
 		}
 		ahc_print_path(ahc, scb);
 		printf("data overrun detected %s."
 		       "  Tag == 0x%x.\n",
-		       phase_table[i].phasemsg,
+		       ahc_phase_table[i].phasemsg,
   		       scb->hscb->tag);
 		ahc_print_path(ahc, scb);
 		printf("%s seen Data Phase.  Length = %ld.  NumSGs = %d.\n",
@@ -858,7 +872,7 @@
 	 *  a SEQINT, so we should restart it when
 	 *  we're done.
 	 */
-	unpause_sequencer(ahc);
+	ahc_unpause(ahc);
 }
 
 void
@@ -897,7 +911,7 @@
 		if (status == 0) {
 			printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc));
 			ahc_outb(ahc, CLRINT, CLRSCSIINT);
-			unpause_sequencer(ahc);
+			ahc_unpause(ahc);
 			return;
 		}
 	}
@@ -975,10 +989,10 @@
 			errorphase = lastphase;
 
 		for (i = 0; i < num_phases; i++) {
-			if (errorphase == phase_table[i].phase)
+			if (errorphase == ahc_phase_table[i].phase)
 				break;
 		}
-		mesg_out = phase_table[i].mesg_out;
+		mesg_out = ahc_phase_table[i].mesg_out;
 		if (scb != NULL)
 			ahc_print_path(ahc, scb);
 		else
@@ -987,7 +1001,7 @@
 		scsirate = ahc_inb(ahc, SCSIRATE);
 		printf("parity error detected %s. "
 		       "SEQADDR(0x%x) SCSIRATE(0x%x)\n",
-		       phase_table[i].phasemsg,
+		       ahc_phase_table[i].phasemsg,
 		       ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8),
 		       scsirate);
 
@@ -1018,7 +1032,45 @@
 				ahc_outb(ahc, MSG_OUT, mesg_out);
 		}
 		ahc_outb(ahc, CLRINT, CLRSCSIINT);
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
+	} else if ((status & SELTO) != 0) {
+		u_int scbptr;
+
+		/* Stop the selection */
+		ahc_outb(ahc, SCSISEQ, 0);
+
+		/* No more pending messages */
+		ahc_clear_msg_state(ahc);
+
+		/* Clear interrupt state */
+		ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
+		ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
+
+		/*
+		 * Although the driver does not care about the
+		 * 'Selection in Progress' status bit, the busy
+		 * LED does.  SELINGO is only cleared by a sucessful
+		 * selection, so we must manually clear it to insure
+		 * the LED turns off just incase no future successful
+		 * selections occur (e.g. no devices on the bus).
+		 */
+		ahc_outb(ahc, CLRSINT0, CLRSELINGO);
+
+		scbptr = ahc_inb(ahc, WAITING_SCBH);
+		ahc_outb(ahc, SCBPTR, scbptr);
+		scb_index = ahc_inb(ahc, SCB_TAG);
+
+		scb = ahc_lookup_scb(ahc, scb_index);
+		if (scb == NULL) {
+			printf("%s: ahc_intr - referenced scb not "
+			       "valid during SELTO scb(%d, %d)\n",
+			       ahc_name(ahc), scbptr, scb_index);
+		} else {
+			ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
+			ahc_freeze_devq(ahc, scb);
+		}
+		ahc_outb(ahc, CLRINT, CLRSCSIINT);
+		ahc_restart(ahc);
 	} else if ((status & BUSFREE) != 0
 		&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
 		u_int lastphase;
@@ -1113,7 +1165,7 @@
 			} else if (ahc_sent_msg(ahc, AHCMSG_EXT,
 						MSG_EXT_PPR, FALSE)) {
 				struct ahc_initiator_tinfo *tinfo;
-				struct tmode_tstate *tstate;
+				struct ahc_tmode_tstate *tstate;
 
 				/*
 				 * PPR Rejected.  Try non-ppr negotiation
@@ -1124,7 +1176,7 @@
 							    devinfo.our_scsiid,
 							    devinfo.target,
 							    &tstate);
-				tinfo->current.transport_version = 2;
+				tinfo->curr.transport_version = 2;
 				tinfo->goal.transport_version = 2;
 				tinfo->goal.ppr_options = 0;
 				ahc_qinfifo_requeue_tail(ahc, scb);
@@ -1174,54 +1226,18 @@
 				printf("%s: ", ahc_name(ahc));
 			}
 			for (i = 0; i < num_phases; i++) {
-				if (lastphase == phase_table[i].phase)
+				if (lastphase == ahc_phase_table[i].phase)
 					break;
 			}
 			printf("Unexpected busfree %s\n"
 			       "SEQADDR == 0x%x\n",
-			       phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0)
+			       ahc_phase_table[i].phasemsg,
+			       ahc_inb(ahc, SEQADDR0)
 				| (ahc_inb(ahc, SEQADDR1) << 8));
 		}
 		ahc_clear_msg_state(ahc);
 		ahc_outb(ahc, CLRINT, CLRSCSIINT);
-		restart_sequencer(ahc);
-	} else if ((status & SELTO) != 0) {
-		u_int scbptr;
-
-		/* Stop the selection */
-		ahc_outb(ahc, SCSISEQ, 0);
-
-		/* No more pending messages */
-		ahc_clear_msg_state(ahc);
-
-		/* Clear interrupt state */
-		ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
-
-		/*
-		 * Although the driver does not care about the
-		 * 'Selection in Progress' status bit, the busy
-		 * LED does.  SELINGO is only cleared by a sucessful
-		 * selection, so we must manually clear it to insure
-		 * the LED turns off just incase no future successful
-		 * selections occur (e.g. no devices on the bus).
-		 */
-		ahc_outb(ahc, CLRSINT0, CLRSELINGO);
-
-		scbptr = ahc_inb(ahc, WAITING_SCBH);
-		ahc_outb(ahc, SCBPTR, scbptr);
-		scb_index = ahc_inb(ahc, SCB_TAG);
-
-		scb = ahc_lookup_scb(ahc, scb_index);
-		if (scb == NULL) {
-			printf("%s: ahc_intr - referenced scb not "
-			       "valid during SELTO scb(%d, %d)\n",
-			       ahc_name(ahc), scbptr, scb_index);
-		} else {
-			ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
-			ahc_freeze_devq(ahc, scb);
-		}
-		ahc_outb(ahc, CLRINT, CLRSCSIINT);
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 	} else {
 		printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",
 		       ahc_name(ahc), status);
@@ -1290,7 +1306,7 @@
 		ahc_outb(ahc, HCNTRL, ahc->unpause);
 		do {
 			ahc_delay(200);
-		} while (!sequencer_paused(ahc));
+		} while (!ahc_is_paused(ahc));
 	}
 	if (stepping) {
 		ahc_outb(ahc, SIMODE0, simode0);
@@ -1363,11 +1379,11 @@
  * Allocate per target mode instance (ID we respond to as a target)
  * transfer negotiation data structures.
  */
-static struct tmode_tstate *
+static struct ahc_tmode_tstate *
 ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
 {
-	struct tmode_tstate *master_tstate;
-	struct tmode_tstate *tstate;
+	struct ahc_tmode_tstate *master_tstate;
+	struct ahc_tmode_tstate *tstate;
 	int i;
 
 	master_tstate = ahc->enabled_targets[ahc->our_id];
@@ -1394,8 +1410,8 @@
 		memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
 		tstate->ultraenb = 0;
 		for (i = 0; i < 16; i++) {
-			memset(&tstate->transinfo[i].current, 0,
-			      sizeof(tstate->transinfo[i].current));
+			memset(&tstate->transinfo[i].curr, 0,
+			      sizeof(tstate->transinfo[i].curr));
 			memset(&tstate->transinfo[i].goal, 0,
 			      sizeof(tstate->transinfo[i].goal));
 		}
@@ -1413,11 +1429,13 @@
 static void
 ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
 {
-	struct tmode_tstate *tstate;
+	struct ahc_tmode_tstate *tstate;
 
-	/* Don't clean up the entry for our initiator role */
-	if ((ahc->flags & AHC_INITIATORROLE) != 0
-	 && ((channel == 'B' && scsi_id == ahc->our_id_b)
+	/*
+	 * Don't clean up our "master" tstate.
+	 * It has our default user settings.
+	 */
+	if (((channel == 'B' && scsi_id == ahc->our_id_b)
 	  || (channel == 'A' && scsi_id == ahc->our_id))
 	 && force == FALSE)
 		return;
@@ -1496,6 +1514,11 @@
 
 	if ((ahc->features & AHC_DT) == 0)
 		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
+
+	/* Skip all DT only entries if DT is not available */
+	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
+	 && maxsync < AHC_SYNCRATE_ULTRA2)
+		maxsync = AHC_SYNCRATE_ULTRA2;
 	
 	for (syncrate = &ahc_syncrates[maxsync];
 	     syncrate->rate != NULL;
@@ -1509,11 +1532,6 @@
 		 && (syncrate->sxfr_u2 == 0))
 			break;
 
-		/* Skip any DT entries if DT is not available */
-		if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
-		 && (syncrate->sxfr_u2 & DT_SXFR) != 0)
-			continue;
-
 		if (*period <= syncrate->period) {
 			/*
 			 * When responding to a target that requests
@@ -1647,44 +1665,31 @@
  * means the next time we send the initial identify messages for
  * a new transaction.
  */
-void
-ahc_update_target_msg_request(struct ahc_softc *ahc,
-			      struct ahc_devinfo *devinfo,
-			      struct ahc_initiator_tinfo *tinfo,
-			      int force, int paused)
-{
-	u_int targ_msg_req_orig;
-
-	targ_msg_req_orig = ahc->targ_msg_req;
-	if (tinfo->current.period != tinfo->goal.period
-	 || tinfo->current.width != tinfo->goal.width
-	 || tinfo->current.offset != tinfo->goal.offset
-	 || tinfo->current.ppr_options != tinfo->goal.ppr_options
+int
+ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+		       struct ahc_tmode_tstate *tstate,
+		       struct ahc_initiator_tinfo *tinfo, int force)
+{
+	u_int auto_negotiate_orig;
+
+	auto_negotiate_orig = tstate->auto_negotiate;
+	if (tinfo->curr.period != tinfo->goal.period
+	 || tinfo->curr.width != tinfo->goal.width
+	 || tinfo->curr.offset != tinfo->goal.offset
+	 || tinfo->curr.ppr_options != tinfo->goal.ppr_options
 	 || (force
 	  && (tinfo->goal.period != 0
 	   || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
 	   || tinfo->goal.ppr_options != 0)))
-		ahc->targ_msg_req |= devinfo->target_mask;
+		tstate->auto_negotiate |= devinfo->target_mask;
 	else
-		ahc->targ_msg_req &= ~devinfo->target_mask;
+		tstate->auto_negotiate &= ~devinfo->target_mask;
 
-	if (ahc->targ_msg_req != targ_msg_req_orig) {
-		/* Update the message request bit for this target */
-		if (!paused)
-			pause_sequencer(ahc);
-
-		ahc_outb(ahc, TARGET_MSG_REQUEST,
-			 ahc->targ_msg_req & 0xFF);
-		ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
-			 (ahc->targ_msg_req >> 8) & 0xFF);
-
-		if (!paused)
-			unpause_sequencer(ahc);
-	}
+	return (auto_negotiate_orig != tstate->auto_negotiate);
 }
 
 /*
- * Update the user/goal/current tables of synchronous negotiation
+ * Update the user/goal/curr tables of synchronous negotiation
  * parameters as well as, in the case of a current or active update,
  * any data structures on the host controller.  In the case of an
  * active update, the specified target is currently talking to us on
@@ -1697,11 +1702,15 @@
 		 u_int offset, u_int ppr_options, u_int type, int paused)
 {
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	u_int	old_period;
 	u_int	old_offset;
 	u_int	old_ppr;
-	int	active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	int	active;
+	int	update_needed;
+
+	active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	update_needed = 0;
 
 	if (syncrate == NULL) {
 		period = 0;
@@ -1723,9 +1732,9 @@
 		tinfo->goal.ppr_options = ppr_options;
 	}
 
-	old_period = tinfo->current.period;
-	old_offset = tinfo->current.offset;
-	old_ppr	   = tinfo->current.ppr_options;
+	old_period = tinfo->curr.period;
+	old_offset = tinfo->curr.offset;
+	old_ppr	   = tinfo->curr.ppr_options;
 
 	if ((type & AHC_TRANS_CUR) != 0
 	 && (old_period != period
@@ -1733,6 +1742,7 @@
 	  || old_ppr != ppr_options)) {
 		u_int	scsirate;
 
+		update_needed++;
 		scsirate = tinfo->scsirate;
 		if ((ahc->features & AHC_ULTRA2) != 0) {
 
@@ -1777,15 +1787,12 @@
 		}
 
 		tinfo->scsirate = scsirate;
-		tinfo->current.period = period;
-		tinfo->current.offset = offset;
-		tinfo->current.ppr_options = ppr_options;
-
-		/* Update the syncrates in any pending scbs */
-		ahc_update_pending_syncrates(ahc);
+		tinfo->curr.period = period;
+		tinfo->curr.offset = offset;
+		tinfo->curr.ppr_options = ppr_options;
 
 		ahc_send_async(ahc, devinfo->channel, devinfo->target,
-			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
+			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
 		if (bootverbose) {
 			if (offset != 0) {
 				printf("%s: target %d synchronous at %sMHz%s, "
@@ -1801,13 +1808,15 @@
 		}
 	}
 
-	ahc_update_target_msg_request(ahc, devinfo, tinfo,
-				      /*force*/FALSE,
-				      paused);
+	update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
+						tinfo, /*force*/FALSE);
+
+	if (update_needed)
+		ahc_update_pending_scbs(ahc);
 }
 
 /*
- * Update the user/goal/current tables of wide negotiation
+ * Update the user/goal/curr tables of wide negotiation
  * parameters as well as, in the case of a current or active update,
  * any data structures on the host controller.  In the case of an
  * active update, the specified target is currently talking to us on
@@ -1818,11 +1827,14 @@
 ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
 	      u_int width, u_int type, int paused)
 {
-	struct ahc_initiator_tinfo *tinfo;
-	struct tmode_tstate *tstate;
-	u_int  oldwidth;
-	int    active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	struct	ahc_initiator_tinfo *tinfo;
+	struct	ahc_tmode_tstate *tstate;
+	u_int	oldwidth;
+	int	active;
+	int	update_needed;
 
+	active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+	update_needed = 0;
 	tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
 				    devinfo->target, &tstate);
 
@@ -1832,10 +1844,11 @@
 	if ((type & AHC_TRANS_GOAL) != 0)
 		tinfo->goal.width = width;
 
-	oldwidth = tinfo->current.width;
+	oldwidth = tinfo->curr.width;
 	if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) {
 		u_int	scsirate;
 
+		update_needed++;
 		scsirate =  tinfo->scsirate;
 		scsirate &= ~WIDEXFER;
 		if (width == MSG_EXT_WDTR_BUS_16_BIT)
@@ -1846,10 +1859,10 @@
 		if (active)
 			ahc_outb(ahc, SCSIRATE, scsirate);
 
-		tinfo->current.width = width;
+		tinfo->curr.width = width;
 
 		ahc_send_async(ahc, devinfo->channel, devinfo->target,
-			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
+			       CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
 		if (bootverbose) {
 			printf("%s: target %d using %dbit transfers\n",
 			       ahc_name(ahc), devinfo->target,
@@ -1857,35 +1870,22 @@
 		}
 	}
 
-	ahc_update_target_msg_request(ahc, devinfo, tinfo,
-				      /*force*/FALSE, paused);
+	update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
+						tinfo, /*force*/FALSE);
+	if (update_needed)
+		ahc_update_pending_scbs(ahc);
 }
 
 /*
  * Update the current state of tagged queuing for a given target.
  */
 void
-ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable)
+ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+	     ahc_queue_alg alg)
 {
-	struct ahc_initiator_tinfo *tinfo;
-	struct tmode_tstate *tstate;
-	uint16_t orig_tagenable;
-
-	tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
-				    devinfo->target, &tstate);
-
-	orig_tagenable = tstate->tagenable;
-	if (enable)
-		tstate->tagenable |= devinfo->target_mask;
-	else
-		tstate->tagenable &= ~devinfo->target_mask;
-
-	if (orig_tagenable != tstate->tagenable) {
-		ahc_platform_set_tags(ahc, devinfo, enable);
-		ahc_send_async(ahc, devinfo->channel, devinfo->target,
-			       devinfo->lun, AC_TRANSFER_NEG);
-	}
-
+ 	ahc_platform_set_tags(ahc, devinfo, alg);
+ 	ahc_send_async(ahc, devinfo->channel, devinfo->target,
+ 		       devinfo->lun, AC_TRANSFER_NEG, &alg);
 }
 
 /*
@@ -1894,11 +1894,12 @@
  * be set correctly during future (re)selections.
  */
 static void
-ahc_update_pending_syncrates(struct ahc_softc *ahc)
+ahc_update_pending_scbs(struct ahc_softc *ahc)
 {
 	struct	scb *pending_scb;
 	int	pending_scb_count;
 	int	i;
+	int	paused;
 	u_int	saved_scbptr;
 
 	/*
@@ -1910,7 +1911,7 @@
 		struct ahc_devinfo devinfo;
 		struct hardware_scb *pending_hscb;
 		struct ahc_initiator_tinfo *tinfo;
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 		
 		ahc_scb_devinfo(ahc, &devinfo, pending_scb);
 		tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
@@ -1921,13 +1922,25 @@
 		if ((tstate->ultraenb & devinfo.target_mask) != 0)
 			pending_hscb->control |= ULTRAENB;
 		pending_hscb->scsirate = tinfo->scsirate;
-		pending_hscb->scsioffset = tinfo->current.offset;
+		pending_hscb->scsioffset = tinfo->curr.offset;
+		if ((tstate->auto_negotiate & devinfo.target_mask) == 0
+		 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
+			pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
+			pending_hscb->control &= ~MK_MESSAGE;
+		}
 		pending_scb_count++;
 	}
 
 	if (pending_scb_count == 0)
 		return;
 
+	if (ahc_is_paused(ahc)) {
+		paused = 1;
+	} else {
+		paused = 0;
+		ahc_pause(ahc);
+	}
+
 	saved_scbptr = ahc_inb(ahc, SCBPTR);
 	/* Ensure that the hscbs down on the card match the new information */
 	for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
@@ -1943,14 +1956,16 @@
 
 		pending_hscb = pending_scb->hscb;
 		control = ahc_inb(ahc, SCB_CONTROL);
-		control &= ~ULTRAENB;
-		if ((pending_hscb->control & ULTRAENB) != 0)
-			control |= ULTRAENB;
+		control &= ~(ULTRAENB|MK_MESSAGE);
+		control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE);
 		ahc_outb(ahc, SCB_CONTROL, control);
 		ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate);
 		ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset);
 	}
 	ahc_outb(ahc, SCBPTR, saved_scbptr);
+
+	if (paused == 0)
+		ahc_unpause(ahc);
 }
 
 /**************************** Pathing Information *****************************/
@@ -1985,6 +2000,24 @@
 			    role);
 }
 
+struct ahc_phase_table_entry*
+ahc_lookup_phase_entry(int phase)
+{
+	struct ahc_phase_table_entry *entry;
+	struct ahc_phase_table_entry *last_entry;
+
+	/*
+	 * num_phases doesn't include the default entry which
+	 * will be returned if the phase doesn't match.
+	 */
+	last_entry = &ahc_phase_table[num_phases];
+	for (entry = ahc_phase_table; entry < last_entry; entry++) {
+		if (phase == entry->phase)
+			break;
+	}
+	return (entry);
+}
+
 void
 ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target,
 		    u_int lun, char channel, role_t role)
@@ -2017,6 +2050,17 @@
 
 
 /************************ Message Phase Processing ****************************/
+static void
+ahc_assert_atn(struct ahc_softc *ahc)
+{
+	u_int scsisigo;
+
+	scsisigo = ATNO;
+	if ((ahc->features & AHC_DT) == 0)
+		scsisigo |= ahc_inb(ahc, SCSISIGI);
+	ahc_outb(ahc, SCSISIGO, scsisigo);
+}
+
 /*
  * When an initiator transaction with the MK_MESSAGE flag either reconnects
  * or enters the initial message out phase, we are interrupted.  Fill our
@@ -2083,8 +2127,7 @@
 		 * away.
 		 */
 		ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
-	} else if ((ahc->targ_msg_req & devinfo->target_mask) != 0
-		|| (scb->flags & SCB_NEGOTIATE) != 0) {
+	} else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
 		ahc_build_transfer_msg(ahc, devinfo);
 	} else {
 		printf("ahc_intr: AWAITING_MSG for an SCB that "
@@ -2101,6 +2144,7 @@
 	 * asked to send this message again.
 	 */
 	ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE);
+	scb->hscb->control &= ~MK_MESSAGE;
 	ahc->msgout_index = 0;
 	ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
 }
@@ -2118,7 +2162,7 @@
 	 * we want to renegotiate due to a check condition.
 	 */
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	struct	ahc_syncrate *rate;
 	int	dowide;
 	int	dosync;
@@ -2130,9 +2174,19 @@
 
 	tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
 				    devinfo->target, &tstate);
-	dowide = tinfo->current.width != tinfo->goal.width;
-	dosync = tinfo->current.period != tinfo->goal.period;
-	doppr = tinfo->current.ppr_options != tinfo->goal.ppr_options;
+	/*
+	 * Filter our period based on the current connection.
+	 * If we can't perform DT transfers on this segment (not in LVD
+	 * mode for instance), then our decision to issue a PPR message
+	 * may change.
+	 */
+	period = tinfo->goal.period;
+	ppr_options = tinfo->goal.ppr_options;
+	rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
+				       &ppr_options, devinfo->role);
+	dowide = tinfo->curr.width != tinfo->goal.width;
+	dosync = tinfo->curr.period != period;
+	doppr = tinfo->curr.ppr_options != ppr_options;
 
 	if (!dowide && !dosync && !doppr) {
 		dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
@@ -2145,7 +2199,7 @@
 		      "but no negotiation needed\n");	
 	}
 
-	use_ppr = (tinfo->current.transport_version >= 3) || doppr;
+	use_ppr = (tinfo->curr.transport_version >= 3) || doppr;
 	/* Target initiated PPR is not allowed in the SCSI spec */
 	if (devinfo->role == ROLE_TARGET)
 		use_ppr = 0;
@@ -2160,16 +2214,10 @@
 	 */
 	if (use_ppr || (dosync && !dowide)) {
 
-		period = tinfo->goal.period;
-		ppr_options = tinfo->goal.ppr_options;
-		if (use_ppr == 0)
-			ppr_options = 0;
-		rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
-					       &ppr_options, devinfo->role);
 		offset = tinfo->goal.offset;
 		ahc_validate_offset(ahc, tinfo, rate, &offset,
 				    use_ppr ? tinfo->goal.width
-					    : tinfo->current.width,
+					    : tinfo->curr.width,
 				    devinfo->role);
 		if (use_ppr) {
 			ahc_construct_ppr(ahc, devinfo, period, offset,
@@ -2258,7 +2306,7 @@
 	ahc->msgout_len = 0;
 	ahc->msgin_index = 0;
 	ahc->msg_type = MSG_TYPE_NONE;
-	if ((ahc_inb(ahc, SCSISIGI) & ATNI) == 0) {
+	if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) {
 		/*
 		 * The target didn't care to respond to our
 		 * message request, so clear ATN.
@@ -2327,7 +2375,7 @@
 			 * 0, and try again.
 			 */
 			ahc->msgout_index = 0;
-			ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+			ahc_assert_atn(ahc);
 		}
 
 		lastbyte = ahc->msgout_index == (ahc->msgout_len - 1);
@@ -2382,8 +2430,7 @@
 			 * message out phase.
 			 */
 			if (ahc->msgout_len != 0)
-				ahc_outb(ahc, SCSISIGO,
-					 ahc_inb(ahc, SCSISIGO) | ATNO);
+				ahc_assert_atn(ahc);
 		} else 
 			ahc->msgin_index++;
 
@@ -2548,7 +2595,7 @@
 					found = TRUE;
 			}
 			index = end_index;
-		} else if (ahc->msgout_buf[index] >= MSG_SIMPLE_Q_TAG
+		} else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK
 			&& ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
 
 			/* Skip tag type and tag id or residue param*/
@@ -2575,7 +2622,7 @@
 ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
 {
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	int	reject;
 	int	done;
 	int	response;
@@ -2674,7 +2721,8 @@
 				/*
 				 * Send our own SDTR in reply
 				 */
-				if (bootverbose) {
+				if (bootverbose
+				 && devinfo->role == ROLE_INITIATOR) {
 					printf("(%s:%c:%d:%d): Target "
 					       "Initiated SDTR\n",
 					       ahc_name(ahc), devinfo->channel,
@@ -2744,7 +2792,8 @@
 				/*
 				 * Send our own WDTR in reply
 				 */
-				if (bootverbose) {
+				if (bootverbose
+				 && devinfo->role == ROLE_INITIATOR) {
 					printf("(%s:%c:%d:%d): Target "
 					       "Initiated WDTR\n",
 					       ahc_name(ahc), devinfo->channel,
@@ -2879,7 +2928,7 @@
 				       "offset %x, options %x\n",
 				       ahc_name(ahc), devinfo->channel,
 				       devinfo->target, devinfo->lun,
-				       ahc->msgin_buf[3], saved_width,
+				       saved_width, ahc->msgin_buf[3],
 				       saved_offset, saved_ppr_options,
 				       bus_width, period, offset, ppr_options);
 			}
@@ -2906,7 +2955,7 @@
 				    CAM_BDR_SENT,
 				    "Bus Device Reset Received",
 				    /*verbose_level*/0);
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 		done = MSGLOOP_TERMINATED;
 		break;
 	case MSG_ABORT_TAG:
@@ -2927,7 +2976,7 @@
 
 		tstate = ahc->enabled_targets[devinfo->our_scsiid];
 		if (tstate != NULL) {
-			struct tmode_lstate* lstate;
+			struct ahc_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[devinfo->lun];
 			if (lstate != NULL) {
@@ -2979,7 +3028,7 @@
 	 */
 	struct scb *scb;
 	struct ahc_initiator_tinfo *tinfo;
-	struct tmode_tstate *tstate;
+	struct ahc_tmode_tstate *tstate;
 	u_int scb_index;
 	u_int last_msg;
 	int   response = 0;
@@ -3004,7 +3053,7 @@
 			       devinfo->target, devinfo->lun);
 		}
 		tinfo->goal.ppr_options = 0;
-		tinfo->current.transport_version = 2;
+		tinfo->curr.transport_version = 2;
 		tinfo->goal.transport_version = 2;
 		ahc->msgout_index = 0;
 		ahc->msgout_len = 0;
@@ -3046,24 +3095,39 @@
 		       "Using asynchronous transfers\n",
 		       ahc_name(ahc), devinfo->channel,
 		       devinfo->target, devinfo->lun);
-	} else if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0) {
-
-		printf("(%s:%c:%d:%d): refuses tagged commands.  Performing "
-		       "non-tagged I/O\n", ahc_name(ahc),
-		       devinfo->channel, devinfo->target, devinfo->lun);
-		ahc_set_tags(ahc, devinfo, FALSE);
+	} else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
+		int tag_type;
+		int mask;
+
+		tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
+
+		if (tag_type == MSG_SIMPLE_TASK) {
+			printf("(%s:%c:%d:%d): refuses tagged commands.  "
+			       "Performing non-tagged I/O\n", ahc_name(ahc),
+			       devinfo->channel, devinfo->target, devinfo->lun);
+			ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE);
+			mask = ~0x23;
+		} else {
+			printf("(%s:%c:%d:%d): refuses %s tagged commands.  "
+			       "Performing simple queue tagged I/O only\n",
+			       ahc_name(ahc), devinfo->channel, devinfo->target,
+			       devinfo->lun, tag_type == MSG_ORDERED_TASK
+			       ? "ordered" : "head of queue");
+			ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC);
+			mask = ~0x03;
+		}
 
 		/*
 		 * Resend the identify for this CCB as the target
 		 * may believe that the selection is invalid otherwise.
 		 */
 		ahc_outb(ahc, SCB_CONTROL,
-			 ahc_inb(ahc, SCB_CONTROL) & ~MSG_SIMPLE_Q_TAG);
-	 	scb->hscb->control &= ~MSG_SIMPLE_Q_TAG;
+			 ahc_inb(ahc, SCB_CONTROL) & mask);
+	 	scb->hscb->control &= mask;
 		ahc_set_transaction_tag(scb, /*enabled*/FALSE,
-					/*type*/MSG_SIMPLE_Q_TAG);
+					/*type*/MSG_SIMPLE_TASK);
 		ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG);
-		ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
+		ahc_assert_atn(ahc);
 
 		/*
 		 * This transaction is now at the head of
@@ -3225,7 +3289,7 @@
 		    cam_status status, char *message, int verbose_level)
 {
 #ifdef AHC_TARGET_MODE
-	struct tmode_tstate* tstate;
+	struct ahc_tmode_tstate* tstate;
 	u_int lun;
 #endif
 	int found;
@@ -3242,7 +3306,7 @@
 	tstate = ahc->enabled_targets[devinfo->our_scsiid];
 	if (tstate != NULL) {
 		for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-			struct tmode_lstate* lstate;
+			struct ahc_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[lun];
 			if (lstate == NULL)
@@ -3265,7 +3329,7 @@
 			 AHC_TRANS_CUR, /*paused*/TRUE);
 	
 	ahc_send_async(ahc, devinfo->channel, devinfo->target,
-		       CAM_LUN_WILDCARD, AC_SENT_BDR);
+		       CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
 
 	if (message != NULL
 	 && (verbose_level <= bootverbose))
@@ -3274,9 +3338,11 @@
 }
 
 #ifdef AHC_TARGET_MODE
-void
-ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+static void
+ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+		       struct scb *scb)
 {
+
 	/*              
 	 * To facilitate adding multiple messages together,
 	 * each routine should increment the index and len
@@ -3285,7 +3351,7 @@
 	ahc->msgout_index = 0;
 	ahc->msgout_len = 0;
 
-	if ((ahc->targ_msg_req & devinfo->target_mask) != 0)
+	if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
 		ahc_build_transfer_msg(ahc, devinfo);
 	else
 		panic("ahc_intr: AWAITING target message with no message");
@@ -3319,6 +3385,7 @@
 	LIST_INIT(&ahc->pending_scbs);
 	/* We don't know our unit number until the OSM sets it */
 	ahc->name = name;
+	ahc->unit = -1;
 	for (i = 0; i < 16; i++)
 		TAILQ_INIT(&ahc->untagged_queues[i]);
 	if (ahc_platform_alloc(ahc, platform_arg) != 0) {
@@ -3337,7 +3404,7 @@
 	ahc->bugs = config->bugs;
 	ahc->flags = config->flags;
 	ahc->channel = config->channel; 
-	ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
+	ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS);
 	ahc->description = config->description;
 	/* The IRQMS bit is only valid on VL and EISA chips */
 	if ((ahc->chip & AHC_PCI) != 0)
@@ -3360,29 +3427,37 @@
 {
 	struct ahc_softc *list_ahc;
 
-#ifdef AHC_SUPPORT_PCI
+#if AHC_PCI_CONFIG > 0
 	/*
 	 * Second Function PCI devices need to inherit some
-	 * settings from function 0.  We assume that function 0
-	 * will always be found prior to function 1.
+	 * settings from function 0.
 	 */
 	if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI
-	 && ahc_get_pci_function(ahc->dev_softc) == 1) {
+	 && (ahc->features & AHC_MULTI_FUNC) != 0) {
 		TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
 			ahc_dev_softc_t list_pci;
 			ahc_dev_softc_t pci;
 
 			list_pci = list_ahc->dev_softc;
 			pci = ahc->dev_softc;
-			if (ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)
-			 && ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
-			 && ahc_get_pci_function(list_pci) == 0) {
-				ahc->flags &= ~AHC_BIOS_ENABLED; 
-				ahc->flags |=
-				    list_ahc->flags & AHC_BIOS_ENABLED;
-				ahc->flags &= ~AHC_CHANNEL_B_PRIMARY; 
-				ahc->flags |=
-				    list_ahc->flags & AHC_CHANNEL_B_PRIMARY;
+			if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
+			 && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) {
+				struct ahc_softc *master;
+				struct ahc_softc *slave;
+
+				if (ahc_get_pci_function(list_pci) == 0) {
+					master = list_ahc;
+					slave = ahc;
+				} else {
+					master = ahc;
+					slave = list_ahc;
+				}
+				slave->flags &= ~AHC_BIOS_ENABLED; 
+				slave->flags |=
+				    master->flags & AHC_BIOS_ENABLED;
+				slave->flags &= ~AHC_PRIMARY_CHANNEL; 
+				slave->flags |=
+				    master->flags & AHC_PRIMARY_CHANNEL;
 				break;
 			}
 		}
@@ -3455,7 +3530,7 @@
 #endif
 	ahc_platform_free(ahc);
 	for (i = 0; i < AHC_NUM_TARGETS; i++) {
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 
 		tstate = ahc->enabled_targets[i];
 		if (tstate != NULL) {
@@ -3463,7 +3538,7 @@
 			int j;
 
 			for (j = 0; j < AHC_NUM_LUNS; j++) {
-				struct tmode_lstate *lstate;
+				struct ahc_tmode_lstate *lstate;
 
 				lstate = tstate->enabled_luns[j];
 				if (lstate != NULL) {
@@ -3523,7 +3598,7 @@
 	 * It contains settings that affect termination and we don't want
 	 * to disturb the integrity of the bus.
 	 */
-	pause_sequencer(ahc);
+	ahc_pause(ahc);
 	sxfrctl1_b = 0;
 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
 		u_int sblkctl;
@@ -3961,17 +4036,26 @@
  		len = sprintf(buf, "Twin Channel, A SCSI Id=%d, "
 			      "B SCSI Id=%d, primary %c, ",
 			      ahc->our_id, ahc->our_id_b,
-			      ahc->flags & AHC_CHANNEL_B_PRIMARY ? 'B': 'A');
+			      (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A');
 	else {
+		const char *speed;
 		const char *type;
 
+		speed = "";
+		if ((ahc->features & AHC_ULTRA) != 0) {
+			speed = "Ultra ";
+		} else if ((ahc->features & AHC_DT) != 0) {
+			speed = "Ultra160 ";
+		} else if ((ahc->features & AHC_ULTRA2) != 0) {
+			speed = "Ultra2 ";
+		}
 		if ((ahc->features & AHC_WIDE) != 0) {
 			type = "Wide";
 		} else {
 			type = "Single";
 		}
-		len = sprintf(buf, "%s Channel %c, SCSI Id=%d, ",
-			      type, ahc->channel, ahc->our_id);
+		len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ",
+			      speed, type, ahc->channel, ahc->our_id);
 	}
 	buf += len;
 
@@ -4124,16 +4208,16 @@
 	 * data for any target mode initiator.
 	 */
 	if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) {
-		printf("%s: unable to allocate tmode_tstate.  "
+		printf("%s: unable to allocate ahc_tmode_tstate.  "
 		       "Failing attach\n", ahc_name(ahc));
-		return (-1);
+		return (ENOMEM);
 	}
 
 	if ((ahc->features & AHC_TWIN) != 0) {
 		if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) {
-			printf("%s: unable to allocate tmode_tstate.  "
+			printf("%s: unable to allocate ahc_tmode_tstate.  "
 			       "Failing attach\n", ahc_name(ahc));
-			return (-1);
+			return (ENOMEM);
 		}
 	}
 
@@ -4231,7 +4315,7 @@
 
 	for (i = 0; i <= max_targ; i++) {
 		struct ahc_initiator_tinfo *tinfo;
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 		u_int our_id;
 		u_int target_id;
 		char channel;
@@ -4324,12 +4408,10 @@
 				tinfo->user.transport_version = 2;
 			tinfo->goal.protocol_version = 2;
 			tinfo->goal.transport_version = 2;
-			tinfo->current.protocol_version = 2;
-			tinfo->current.transport_version = 2;
+			tinfo->curr.protocol_version = 2;
+			tinfo->curr.transport_version = 2;
 		}
 		tstate->ultraenb = ultraenb;
-		tstate->discenable = discenable;
-		tstate->tagenable = 0; /* Wait until the XPT says its okay */
 	}
 	ahc->user_discenable = discenable;
 	ahc->user_tagenable = tagenable;
@@ -4395,10 +4477,6 @@
 	ahc_outb(ahc, QINPOS, 0);
 	ahc_outb(ahc, QOUTPOS, 0);
 
-	/* Don't have any special messages to send to targets */
-	ahc_outb(ahc, TARGET_MSG_REQUEST, 0);
-	ahc_outb(ahc, TARGET_MSG_REQUEST + 1, 0);
-
 	/*
 	 * Use the built in queue management registers
 	 * if they are available.
@@ -4450,16 +4528,33 @@
 		 * never settle, so don't complain if we
 		 * fail here.
 		 */
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		for (wait = 5000;
 		     (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
 		     wait--)
 			ahc_delay(100);
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 	}
 	return (0);
 }
 
+void
+ahc_intr_enable(struct ahc_softc *ahc, int enable)
+{
+	u_int hcntrl;
+
+	hcntrl = ahc_inb(ahc, HCNTRL);
+	hcntrl &= ~INTEN;
+	ahc->pause &= ~INTEN;
+	ahc->unpause &= ~INTEN;
+	if (enable) {
+		hcntrl |= INTEN;
+		ahc->pause |= INTEN;
+		ahc->unpause |= INTEN;
+	}
+	ahc_outb(ahc, HCNTRL, hcntrl);
+}
+
 /*
  * Ensure that the card is paused in a location
  * outside of all critical sections and that all
@@ -4478,7 +4573,7 @@
 	intstat = 0;
 	do {
 		ahc_intr(ahc);
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		ahc_clear_critical_section(ahc);
 		if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
 			break;
@@ -5409,7 +5504,7 @@
 			    CAM_TARGET_WILDCARD,
 			    CAM_LUN_WILDCARD,
 			    channel, ROLE_UNKNOWN);
-	pause_sequencer(ahc);
+	ahc_pause(ahc);
 
 	/* Make sure the sequencer is in a safe location. */
 	ahc_clear_critical_section(ahc);
@@ -5478,14 +5573,14 @@
 	 * drivers affected by this action.
 	 */
 	for (target = 0; target <= max_scsiid; target++) {
-		struct tmode_tstate* tstate;
+		struct ahc_tmode_tstate* tstate;
 		u_int lun;
 
 		tstate = ahc->enabled_targets[target];
 		if (tstate == NULL)
 			continue;
 		for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-			struct tmode_lstate* lstate;
+			struct ahc_tmode_lstate* lstate;
 
 			lstate = tstate->enabled_luns[lun];
 			if (lstate == NULL)
@@ -5499,7 +5594,7 @@
 #endif
 	/* Notify the XPT that a bus reset occurred */
 	ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD,
-		       CAM_LUN_WILDCARD, AC_BUS_RESET);
+		       CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
 
 	/*
 	 * Revert to async/narrow transfers until we renegotiate.
@@ -5524,9 +5619,9 @@
 	}
 
 	if (restart_needed)
-		restart_sequencer(ahc);
+		ahc_restart(ahc);
 	else
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 	return found;
 }
 
@@ -5535,7 +5630,7 @@
 /*
  * Calculate the residual for a just completed SCB.
  */
-static void
+void
 ahc_calc_residual(struct scb *scb)
 {
 	struct hardware_scb *hscb;
@@ -5623,7 +5718,7 @@
  * Add a target mode event to this lun's queue
  */
 static void
-ahc_queue_lstate_event(struct ahc_softc *ahc, struct tmode_lstate *lstate,
+ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate,
 		       u_int initiator_id, u_int event_type, u_int event_arg)
 {
 	struct ahc_tmode_event *event;
@@ -5674,7 +5769,7 @@
  * for immediate notify resources.
  */
 void
-ahc_send_lstate_events(struct ahc_softc *ahc, struct tmode_lstate *lstate)
+ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate)
 {
 	struct ccb_hdr *ccbh;
 	struct ccb_immed_notify *inot;
@@ -5825,7 +5920,7 @@
 		memcpy(ahc->critical_sections, cs_table, cs_count);
 	}
 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
-	restart_sequencer(ahc);
+	ahc_restart(ahc);
 
 	if (bootverbose)
 		printf(" %d instructions downloaded\n", downloaded);
@@ -6000,6 +6095,7 @@
 	int target;
 	int maxtarget;
 	int i;
+	uint8_t last_phase;
 	uint8_t qinpos;
 	uint8_t qintail;
 	uint8_t qoutpos;
@@ -6008,13 +6104,25 @@
 
 	saved_scbptr = ahc_inb(ahc, SCBPTR);
 
-	printf("%s: Dumping Card State at SEQADDR 0x%x\n",
-	       ahc_name(ahc),
+	last_phase = ahc_inb(ahc, LASTPHASE);
+	printf("%s: Dumping Card State %s, at SEQADDR 0x%x\n",
+	       ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg,
 	       ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
-
-	printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x, SSTAT0 0x%x\n",
-	       ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL),
-	       ahc_inb(ahc, SSTAT0));
+	printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x\n",
+	       ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL));
+	printf(" DFCNTRL = 0x%x, DFSTATUS = 0x%x\n",
+	       ahc_inb(ahc, DFCNTRL), ahc_inb(ahc, DFSTATUS));
+	printf("LASTPHASE = 0x%x, SCSISIGI = 0x%x, SXFRCTL0 = 0x%x\n",
+	       last_phase, ahc_inb(ahc, SCSISIGI), ahc_inb(ahc, SXFRCTL0));
+	printf("SSTAT0 = 0x%x, SSTAT1 = 0x%x\n",
+	       ahc_inb(ahc, SSTAT0), ahc_inb(ahc, SSTAT1));
+	if ((ahc->features & AHC_DT) != 0)
+		printf("SCSIPHASE = 0x%x\n", ahc_inb(ahc, SCSIPHASE));
+	printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n",
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+		ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8));
 	printf("SCB count = %d\n", ahc->scb_data->numscbs);
 	printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag);
 	printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB));
@@ -6112,7 +6220,8 @@
 #ifdef AHC_TARGET_MODE
 cam_status
 ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb,
-		    struct tmode_tstate **tstate, struct tmode_lstate **lstate,
+		    struct ahc_tmode_tstate **tstate,
+		    struct ahc_tmode_lstate **lstate,
 		    int notfound_failure)
 {
 
@@ -6153,8 +6262,8 @@
 void
 ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 {
-	struct	   tmode_tstate *tstate;
-	struct	   tmode_lstate *lstate;
+	struct	   ahc_tmode_tstate *tstate;
+	struct	   ahc_tmode_lstate *lstate;
 	struct	   ccb_en_lun *cel;
 	cam_status status;
 	u_int	   target;
@@ -6227,7 +6336,7 @@
 		ahc->flags |= AHC_TARGETROLE;
 		if ((ahc->features & AHC_MULTIROLE) == 0)
 			ahc->flags &= ~AHC_INITIATORROLE;
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		ahc_loadseq(ahc);
 		ahc_unlock(ahc, &s);
 	}
@@ -6296,7 +6405,7 @@
 		SLIST_INIT(&lstate->accept_tios);
 		SLIST_INIT(&lstate->immed_notifies);
 		ahc_lock(ahc, &s);
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		if (target != CAM_TARGET_WILDCARD) {
 			tstate->enabled_luns[lun] = lstate;
 			ahc->enabled_luns++;
@@ -6360,7 +6469,7 @@
 			scsiseq |= ENSELI;
 			ahc_outb(ahc, SCSISEQ, scsiseq);
 		}
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 		ahc_unlock(ahc, &s);
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_print_path(ccb->ccb_h.path);
@@ -6410,7 +6519,7 @@
 		xpt_free_path(lstate->path);
 		free(lstate, M_DEVBUF);
 
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		/* Can we clean up the target too? */
 		if (target != CAM_TARGET_WILDCARD) {
 			tstate->enabled_luns[lun] = NULL;
@@ -6463,11 +6572,11 @@
 				printf("Configuring Initiator Mode\n");
 				ahc->flags &= ~AHC_TARGETROLE;
 				ahc->flags |= AHC_INITIATORROLE;
-				pause_sequencer(ahc);
+				ahc_pause(ahc);
 				ahc_loadseq(ahc);
 			}
 		}
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 		ahc_unlock(ahc, &s);
 	}
 }
@@ -6549,11 +6658,11 @@
 				ahc_outb(ahc, HS_MAILBOX, hs_mailbox);
 			} else {
 				if (!paused)
-					pause_sequencer(ahc);	
+					ahc_pause(ahc);	
 				ahc_outb(ahc, KERNEL_TQINPOS,
 					 ahc->tqinfifonext & HOST_TQINPOS);
 				if (!paused)
-					unpause_sequencer(ahc);
+					ahc_unpause(ahc);
 			}
 		}
 	}
@@ -6562,8 +6671,8 @@
 static int
 ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
 {
-	struct	  tmode_tstate *tstate;
-	struct	  tmode_lstate *lstate;
+	struct	  ahc_tmode_tstate *tstate;
+	struct	  ahc_tmode_lstate *lstate;
 	struct	  ccb_accept_tio *atio;
 	uint8_t *byte;
 	int	  initiator;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.h linux/drivers/scsi/aic7xxx/aic7xxx.h
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.h	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx.h	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx.h#19 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.h#27 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.h,v 1.30 2000/11/10 20:13:40 gibbs Exp $
  */
@@ -209,9 +209,15 @@
 	AHC_MULTIROLE	= 0x40000,	/* Space for two roles at a time */
 	AHC_REMOVABLE	= 0x80000,	/* Hot-Swap supported */
 	AHC_AIC7770_FE	= AHC_FENONE,
-	AHC_AIC7850_FE	= AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE,
-	AHC_AIC7855_FE	= AHC_AIC7850_FE,
-	AHC_AIC7860_FE	= AHC_AIC7850_FE|AHC_ULTRA,
+	/*
+	 * The real 7850 does not support Ultra modes, but there are
+	 * several cards that use the generic 7850 PCI ID even though
+	 * they are using an Ultra capable chip (7859/7860).  We start
+	 * out with the AHC_ULTRA feature set and then check the DEVSTATUS
+	 * register to determine if the capability is really present.
+	 */
+	AHC_AIC7850_FE	= AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
+	AHC_AIC7860_FE	= AHC_AIC7850_FE,
 	AHC_AIC7870_FE	= AHC_TARGETMODE,
 	AHC_AIC7880_FE	= AHC_AIC7870_FE|AHC_ULTRA,
 	/*
@@ -286,56 +292,56 @@
  * chip/controller's configuration.
  */
 typedef enum {
-	AHC_FNONE		= 0x000,
-	AHC_PAGESCBS		= 0x001,/* Enable SCB paging */
-	AHC_CHANNEL_B_PRIMARY	= 0x002,/*
-					 * On twin channel adapters, probe
-					 * channel B first since it is the
-					 * primary bus.
+	AHC_FNONE	      = 0x000,
+	AHC_PRIMARY_CHANNEL   = 0x003,/*
+					 * The channel that should
+					 * be probed first.
 					 */
-	AHC_USEDEFAULTS		= 0x004,/*
+	AHC_USEDEFAULTS	      = 0x004,/*
 					 * For cards without an seeprom
 					 * or a BIOS to initialize the chip's
 					 * SRAM, we use the default target
 					 * settings.
 					 */
-	AHC_SEQUENCER_DEBUG	= 0x008,
-	AHC_SHARED_SRAM		= 0x010,
-	AHC_LARGE_SEEPROM	= 0x020,/* Uses C56_66 not C46 */
-	AHC_RESET_BUS_A		= 0x040,
-	AHC_RESET_BUS_B		= 0x080,
-	AHC_EXTENDED_TRANS_A	= 0x100,
-	AHC_EXTENDED_TRANS_B	= 0x200,
-	AHC_TERM_ENB_A		= 0x400,
-	AHC_TERM_ENB_B		= 0x800,
-	AHC_INITIATORROLE	= 0x1000,/*
+	AHC_SEQUENCER_DEBUG   = 0x008,
+	AHC_SHARED_SRAM	      = 0x010,
+	AHC_LARGE_SEEPROM     = 0x020,/* Uses C56_66 not C46 */
+	AHC_RESET_BUS_A	      = 0x040,
+	AHC_RESET_BUS_B	      = 0x080,
+	AHC_EXTENDED_TRANS_A  = 0x100,
+	AHC_EXTENDED_TRANS_B  = 0x200,
+	AHC_TERM_ENB_A	      = 0x400,
+	AHC_TERM_ENB_B	      = 0x800,
+	AHC_INITIATORROLE     = 0x1000,/*
 					  * Allow initiator operations on
 					  * this controller.
 					  */
-	AHC_TARGETROLE		= 0x2000,/*
+	AHC_TARGETROLE	      = 0x2000,/*
 					  * Allow target operations on this
 					  * controller.
 					  */
-	AHC_NEWEEPROM_FMT	= 0x4000,
-	AHC_RESOURCE_SHORTAGE	= 0x8000,
-	AHC_TQINFIFO_BLOCKED	= 0x10000,/* Blocked waiting for ATIOs */
-	AHC_INT50_SPEEDFLEX	= 0x20000,/*
+	AHC_NEWEEPROM_FMT     = 0x4000,
+	AHC_RESOURCE_SHORTAGE = 0x8000,
+	AHC_TQINFIFO_BLOCKED  = 0x10000,/* Blocked waiting for ATIOs */
+	AHC_INT50_SPEEDFLEX   = 0x20000,/*
 					   * Internal 50pin connector
 					   * sits behind an aic3860
 					   */
-	AHC_SCB_BTT		= 0x40000,/*
+	AHC_SCB_BTT	      = 0x40000,/*
 					   * The busy targets table is
 					   * stored in SCB space rather
 					   * than SRAM.
 					   */
-	AHC_BIOS_ENABLED	= 0x80000,
-	AHC_ALL_INTERRUPTS	= 0x100000,
-	AHC_ULTRA_DISABLED	= 0x200000/*
+	AHC_BIOS_ENABLED      = 0x80000,
+	AHC_ALL_INTERRUPTS    = 0x100000,
+	AHC_ULTRA_DISABLED    = 0x200000, /*
 					   * The precision resistor for
 					   * ultra transmission speeds is
 					   * missing, so we must limit
 					   * ourselves to fast SCSI.
 					   */
+	AHC_PAGESCBS	      = 0x400000, /* Enable SCB paging */
+	AHC_EDGE_INTERRUPT    = 0x800000  /* Device uses edge triggered ints */
 } ahc_flag;
 
 /*
@@ -515,8 +521,9 @@
 	SCB_DEVICE_RESET	= 0x0004,
 	SCB_SENSE		= 0x0008,
 	SCB_CDB32_PTR		= 0x0010,
-	SCB_RECOVERY_SCB	= 0x0040,
-	SCB_NEGOTIATE		= 0x0080,
+	SCB_RECOVERY_SCB	= 0x0020,
+	SCB_AUTO_NEGOTIATE	= 0x0040,/* Negotiate to achieve goal. */
+	SCB_NEGOTIATE		= 0x0080,/* Negotiation forced for command. */
 	SCB_ABORT		= 0x1000,
 	SCB_UNTAGGEDQ		= 0x2000,
 	SCB_ACTIVE		= 0x4000,
@@ -625,7 +632,7 @@
  * data structures.
  */
 #ifdef AHC_TARGET_MODE 
-struct tmode_lstate {
+struct ahc_tmode_lstate {
 	struct cam_path *path;
 	struct ccb_hdr_slist accept_tios;
 	struct ccb_hdr_slist immed_notifies;
@@ -634,7 +641,7 @@
 	uint8_t event_w_idx;
 };
 #else
-struct tmode_lstate;
+struct ahc_tmode_lstate;
 #endif
 
 /******************** Transfer Negotiation Datastructures *********************/
@@ -659,7 +666,7 @@
  * Per-initiator current, goal and user transfer negotiation information. */
 struct ahc_initiator_tinfo {
 	uint8_t scsirate;		/* Computed value for SCSIRATE reg */
-	struct ahc_transinfo current;
+	struct ahc_transinfo curr;
 	struct ahc_transinfo goal;
 	struct ahc_transinfo user;
 };
@@ -671,16 +678,17 @@
  * that we are the target and the targets are the initiators since the
  * negotiation is the same regardless of role.
  */
-struct tmode_tstate {
-	struct tmode_lstate*		enabled_luns[AHC_NUM_LUNS];
+struct ahc_tmode_tstate {
+	struct ahc_tmode_lstate*	enabled_luns[AHC_NUM_LUNS];
 	struct ahc_initiator_tinfo	transinfo[AHC_NUM_TARGETS];
 
 	/*
 	 * Per initiator state bitmasks.
 	 */
-	uint16_t		 ultraenb;	/* Using ultra sync rate  */
-	uint16_t	 	 discenable;	/* Disconnection allowed  */
-	uint16_t		 tagenable;	/* Tagged Queuing allowed */
+	uint16_t	 auto_negotiate;/* Auto Negotiation Required */
+	uint16_t	 ultraenb;	/* Using ultra sync rate  */
+	uint16_t	 discenable;	/* Disconnection allowed  */
+	uint16_t	 tagenable;	/* Tagged Queuing allowed */
 };
 
 /*
@@ -711,32 +719,14 @@
 
 /***************************** Lookup Tables **********************************/
 /*
- * Textual descriptions of the different chips indexed by chip type.
- */
-extern char *ahc_chip_names[];
-extern const u_int num_chip_names;
-
-/*
- * Hardware error codes.
- */
-struct hard_error_entry {
-        uint8_t errno;
-	char *errmesg;
-};
-extern struct hard_error_entry hard_error[];
-extern const u_int num_errors;
-
-/*
  * Phase -> name and message out response
  * to parity errors in each phase table. 
  */
-struct phase_table_entry {
+struct ahc_phase_table_entry {
         uint8_t phase;
         uint8_t mesg_out; /* Message response to parity errors */
 	char *phasemsg;
 };
-extern struct phase_table_entry phase_table[];
-extern const u_int num_phases;
 
 /************************** Serial EEPROM Format ******************************/
 
@@ -765,12 +755,19 @@
 #define		CFSUPREM	0x0001	/* support all removeable drives */
 #define		CFSUPREMB	0x0002	/* support removeable boot drives */
 #define		CFBIOSEN	0x0004	/* BIOS enabled */
-/*		UNUSED		0x0008	*/
+#define		CFBIOS_BUSSCAN	0x0008	/* Have the BIOS Scan the Bus */
 #define		CFSM2DRV	0x0010	/* support more than two drives */
-#define		CF284XEXTEND	0x0020	/* extended translation (284x cards) */	
 #define		CFSTPWLEVEL	0x0010	/* Termination level control */
+#define		CF284XEXTEND	0x0020	/* extended translation (284x cards) */	
+#define		CFCTRL_A	0x0020	/* BIOS displays Ctrl-A message */	
+#define		CFTERM_MENU	0x0040	/* BIOS displays termination menu */	
 #define		CFEXTEND	0x0080	/* extended translation enabled */
 #define		CFSCAMEN	0x0100	/* SCAM enable */
+#define		CFMSG_LEVEL	0x0600	/* BIOS Message Level */
+#define			CFMSG_VERBOSE	0x0000
+#define			CFMSG_SILENT	0x0200
+#define			CFMSG_DIAG	0x0400
+#define		CFBOOTCD	0x0800  /* Support Bootable CD-ROM */
 /*		UNUSED		0xff00	*/
 
 /*
@@ -785,10 +782,11 @@
 #define		CFWSTERM	0x0008	/* SCSI high byte termination */
 #define		CFSPARITY	0x0010	/* SCSI parity */
 #define		CF284XSTERM     0x0020	/* SCSI low byte term (284x cards) */	
-#define		CFMULTILUN	0x0020	/* SCSI low byte term (284x cards) */	
+#define		CFMULTILUN	0x0020
 #define		CFRESETB	0x0040	/* reset SCSI bus at boot */
 #define		CFCLUSTERENB	0x0080	/* Cluster Enable */
-#define		CFCHNLBPRIMARY	0x0100	/* aic7895 probe B channel first */
+#define		CFBOOTCHAN	0x0300	/* probe this channel first */
+#define		CFBOOTCHANSHIFT 8
 #define		CFSEAUTOTERM	0x0400	/* Ultra2 Perform secondary Auto Term*/
 #define		CFSELOWTERM	0x0800	/* Ultra2 secondary low term */
 #define		CFSEHIGHTERM	0x1000	/* Ultra2 secondary high term */
@@ -812,6 +810,7 @@
 	uint16_t res_1[10];		/* words 20-29 */
 	uint16_t signature;		/* Signature == 0x250 */
 #define		CFSIGNATURE	0x250
+#define		CFSIGNATURE2	0x300
 	uint16_t checksum;		/* word 31 */
 };
 
@@ -857,6 +856,8 @@
 	uint8_t	*btt;
 };
 
+typedef void (*ahc_bus_intr_t)(struct ahc_softc *);
+
 struct ahc_softc {
 	bus_space_tag_t           tag;
 	bus_space_handle_t        bsh;
@@ -900,24 +901,29 @@
 	ahc_dev_softc_t		  dev_softc;
 
 	/*
+	 * Bus specific device information.
+	 */
+	ahc_bus_intr_t		  bus_intr;
+
+	/*
 	 * Target mode related state kept on a per enabled lun basis.
 	 * Targets that are not enabled will have null entries.
 	 * As an initiator, we keep one target entry for our initiator
 	 * ID to store our sync/wide transfer settings.
 	 */
-	struct tmode_tstate*	  enabled_targets[AHC_NUM_TARGETS];
+	struct ahc_tmode_tstate  *enabled_targets[AHC_NUM_TARGETS];
 
 	/*
 	 * The black hole device responsible for handling requests for
 	 * disabled luns on enabled targets.
 	 */
-	struct tmode_lstate*	  black_hole;
+	struct ahc_tmode_lstate  *black_hole;
 
 	/*
 	 * Device instance currently on the bus awaiting a continue TIO
 	 * for a command that was not given the disconnect priveledge.
 	 */
-	struct tmode_lstate*	  pending_device;
+	struct ahc_tmode_lstate  *pending_device;
 
 	/*
 	 * Card characteristics
@@ -952,9 +958,6 @@
 	uint8_t			  our_id;
 	uint8_t			  our_id_b;
 
-	/* Targets that need negotiation messages */
-	uint16_t		  targ_msg_req;
-
 	/*
 	 * PCI error detection.
 	 */
@@ -1102,6 +1105,7 @@
 					struct ahc_probe_config*);
 void			 ahc_controller_info(struct ahc_softc *ahc, char *buf);
 int			 ahc_init(struct ahc_softc *ahc);
+void			 ahc_intr_enable(struct ahc_softc *ahc, int enable);
 void			 ahc_pause_and_flushwork(struct ahc_softc *ahc);
 int			 ahc_suspend(struct ahc_softc *ahc); 
 int			 ahc_resume(struct ahc_softc *ahc);
@@ -1143,8 +1147,11 @@
 void			ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
 int			ahc_reset_channel(struct ahc_softc *ahc, char channel,
 					  int initiate_reset);
-void			restart_sequencer(struct ahc_softc *ahc);
+void			ahc_restart(struct ahc_softc *ahc);
+void			ahc_calc_residual(struct scb *scb);
 /*************************** Utility Functions ********************************/
+struct ahc_phase_table_entry*
+			ahc_lookup_phase_entry(int phase);
 void			ahc_compile_devinfo(struct ahc_devinfo *devinfo,
 					    u_int our_id, u_int target,
 					    u_int lun, char channel,
@@ -1163,10 +1170,11 @@
 					   struct ahc_initiator_tinfo *tinfo,
 					   u_int *bus_width,
 					   role_t role);
-void			ahc_update_target_msg_request(struct ahc_softc *ahc,
-					struct ahc_devinfo *dinfo,
-					struct ahc_initiator_tinfo *tinfo,
-					int force, int paused);
+int			ahc_update_neg_request(struct ahc_softc*,
+					       struct ahc_devinfo*,
+					       struct ahc_tmode_tstate*,
+					       struct ahc_initiator_tinfo*,
+					       int /*force*/);
 void			ahc_set_width(struct ahc_softc *ahc,
 				      struct ahc_devinfo *devinfo,
 				      u_int width, u_int type, int paused);
@@ -1176,22 +1184,27 @@
 					 u_int period, u_int offset,
 					 u_int ppr_options,
 					 u_int type, int paused);
+typedef enum {
+	AHC_QUEUE_NONE,
+	AHC_QUEUE_BASIC,
+	AHC_QUEUE_TAGGED
+} ahc_queue_alg;
+
 void			ahc_set_tags(struct ahc_softc *ahc,
-				     struct ahc_devinfo *devinfo, int enable);
+				     struct ahc_devinfo *devinfo,
+				     ahc_queue_alg alg);
 
 /**************************** Target Mode *************************************/
 #ifdef AHC_TARGET_MODE
 void		ahc_send_lstate_events(struct ahc_softc *,
-				       struct tmode_lstate *);
+				       struct ahc_tmode_lstate *);
 void		ahc_handle_en_lun(struct ahc_softc *ahc,
 				  struct cam_sim *sim, union ccb *ccb);
 cam_status	ahc_find_tmode_devs(struct ahc_softc *ahc,
 				    struct cam_sim *sim, union ccb *ccb,
-				    struct tmode_tstate **tstate,
-				    struct tmode_lstate **lstate,
+				    struct ahc_tmode_tstate **tstate,
+				    struct ahc_tmode_lstate **lstate,
 				    int notfound_failure);
-void		ahc_setup_target_msgin(struct ahc_softc *ahc,
-				       struct ahc_devinfo *devinfo);
 #ifndef AHC_TMODE_ENABLE
 #define AHC_TMODE_ENABLE 0
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.reg linux/drivers/scsi/aic7xxx/aic7xxx.reg
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.reg	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx.reg	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx.reg#13 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.reg#17 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.reg,v 1.31 2000/11/10 20:13:40 gibbs Exp $
  */
@@ -877,7 +877,8 @@
 	address			0x094
 	access_mode RO
 	bit	PRELOAD_AVAIL	0x80
-	bit	DWORDEMP	0x20
+	bit	DFCACHETH	0x40
+	bit	FIFOQWDEMP	0x20
 	bit	MREQPEND	0x10
 	bit	HDONE		0x08
 	bit	DFTHRESH	0x04
@@ -969,6 +970,7 @@
 	bit	MSG_OUT_PHASE	0x04
 	bit	DATA_IN_PHASE	0x02
 	bit	DATA_OUT_PHASE	0x01
+	mask	DATA_PHASE_MASK	0x03
 }
 
 /*
@@ -1415,15 +1417,6 @@
 	 */
 	LAST_MSG {
 		size		1
-	}
-
-	/*
-	 * Interrupt kernel for a message to this target on
-	 * the next transaction.  This is usually used for
-	 * negotiation requests.
-	 */
-	TARGET_MSG_REQUEST {
-		size		2
 	}
 
 	/*
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.seq linux/drivers/scsi/aic7xxx/aic7xxx.seq
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx.seq	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx.seq	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx.seq#22 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.seq#27 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.106 2000/11/12 05:19:46 gibbs Exp $
  */
@@ -153,7 +153,9 @@
 	 * the kernel driver if it happens.
 	 */
 	mvi	CLRSINT1,CLRBUSFREE;
-	or	SIMODE1, ENBUSFREE;
+	if ((ahc->features & AHC_DT) == 0) {
+		or	SIMODE1, ENBUSFREE;
+	}
 
 	/*
 	 * Guard against a bus free after (re)selection
@@ -479,6 +481,9 @@
 		 */
 		mov	SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES];
 		
+		test	SCB_CONTROL, MK_MESSAGE	jz target_ITloop;
+		mvi	P_MESGIN|BSYO call change_phase;
+		jmp	host_target_message_loop;
 target_ITloop:
 		/*
 		 * Start honoring ATN signals now that
@@ -494,12 +499,12 @@
 		 * on the state of NO_DISCONNECT.
 		 */
 		test	SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 
-		if ((ahc->flags & AHC_PAGESCBS) != 0) {
-			mov	ALLZEROS	call	get_free_or_disc_scb;
-		}
 		mov	RETURN_1, ALLZEROS;
 		call	complete_target_cmd;
 		cmp	RETURN_1, CONT_MSG_LOOP jne .;
+		if ((ahc->flags & AHC_PAGESCBS) != 0) {
+			mov	ALLZEROS	call	get_free_or_disc_scb;
+		}
 		mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
 		mov	SCB_TAG	 call dma_scb;
 		jmp	target_synccmd;
@@ -703,6 +708,11 @@
 	test	CCSGCTL, CCSGEN jnz .;
 	ret;
 idle_loop:
+	/*
+	 * Do we need any more segments for this transfer?
+	 */
+	test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
+
 	/* Did we just finish fetching segs? */
 	cmp	CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
 
@@ -710,11 +720,6 @@
 	test	CCSGCTL, CCSGEN jnz return;
 
 	/*
-	 * Do we need any more segments?
-	 */
-	test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
-
-	/*
 	 * Do we have any prefetch left???
 	 */
 	cmp	CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
@@ -758,8 +763,8 @@
 		test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
 		or	SINDEX, LAST_SEG;
 		mov	SG_CACHE_PRE, SINDEX;
-		/* Load the segment by writing DFCNTRL again */
-		mov	DFCNTRL, DMAPARAMS;
+		/* Load the segment */
+		or	DFCNTRL, PRELOADEN;
 	}
 	ret;
 }
@@ -882,7 +887,11 @@
 	and	DMAPARAMS, DIRECTION;
 	mov	DFCNTRL, DMAPARAMS;
 	or	SXFRCTL1,BITBUCKET;
-	test	SSTAT1,PHASEMIS	jz .;
+	if ((ahc->features & AHC_DT) == 0) {
+		test	SSTAT1,PHASEMIS	jz .;
+	} else {
+		test	SCSIPHASE, DATA_PHASE_MASK jnz .;
+	}
 	and	SXFRCTL1, ~BITBUCKET;
 	mvi	DATA_OVERRUN call set_seqint;
 	jmp	ITloop;
@@ -903,54 +912,48 @@
 		 * completes or the target changes phase.
 		 */
 		test	SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
-		if ((ahc->flags & AHC_TARGETROLE) != 0) {
-			 /*
-			  * As a target, we control the phases,
-			  * so ignore PHASEMIS.
-			  */
-			test	SSTAT0, TARGET jnz ultra2_dma_loop;
-		}
-		if ((ahc->flags & AHC_INITIATORROLE) != 0) {
-			test	SSTAT1,PHASEMIS	jz ultra2_dma_loop;
+		if ((ahc->features & AHC_DT) == 0) {
+			if ((ahc->flags & AHC_TARGETROLE) != 0) {
+				 /*
+				  * As a target, we control the phases,
+				  * so ignore PHASEMIS.
+				  */
+				test	SSTAT0, TARGET jnz ultra2_dma_loop;
+			}
+			if ((ahc->flags & AHC_INITIATORROLE) != 0) {
+				test	SSTAT1,PHASEMIS	jz ultra2_dma_loop;
+			}
+		} else {
+			test	DFCNTRL, SCSIEN jnz ultra2_dma_loop;
 		}
 
 ultra2_dmafinish:
-		test	DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
-		if ((ahc->features & AHC_DT) == 0) {
-			and	DFCNTRL, ~SCSIEN;
-			test	DFCNTRL, SCSIEN jnz .;
-		}
-ultra2_dmafifoflush:
+		/*
+		 * The transfer has terminated either due to a phase
+		 * change, and/or the completion of the last segment.
+		 * We have two goals here.  Do as much other work
+		 * as possible while the data fifo drains on a read
+		 * and respond as quickly as possible to the standard
+		 * messages (save data pointers/disconnect and command
+		 * complete) that usually follow a data phase.
+		 */
 		if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
 			/*
-			 * On Rev A of the aic7890, the autoflush
-			 * features doesn't function correctly.
-			 * Perform an explicit manual flush.  During
-			 * a manual flush, the FIFOEMP bit becomes
-			 * true every time the PCI FIFO empties
-			 * regardless of the state of the SCSI FIFO.
-			 * It can take up to 4 clock cycles for the
-			 * SCSI FIFO to get data into the PCI FIFO
-			 * and for FIFOEMP to de-assert.  Here we
-			 * guard against this condition by making
-			 * sure the FIFOEMP bit stays on for 5 full
-			 * clock cycles.
+			 * On chips with broken auto-flush, start
+			 * the flushing process now.  We'll poke
+			 * the chip from time to time to keep the
+			 * flush process going as we complete the
+			 * data phase.
 			 */
 			or	DFCNTRL, FIFOFLUSH;
-			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-			test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
 		}
-		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
-ultra2_dmafifoempty:
-		/* Don't clobber an inprogress host data transfer */
-		test	DFSTATUS, MREQPEND	jnz ultra2_dmafifoempty;
-ultra2_dmahalt:
-		and     DFCNTRL, ~(SCSIEN|HDMAEN);
-		test	DFCNTRL, HDMAEN jnz .;
-
 		/*
+		 * We assume that, even though data may still be
+		 * transferring to the host, that the SCSI side of
+		 * the DMA engine is now in a static state.  This
+		 * allows us to update our notion of where we are
+		 * in this transfer.
+		 *
 		 * If, by chance, we stopped before being able
 		 * to fetch additional segments for this transfer,
 		 * yet the last S/G was completely exhausted,
@@ -961,14 +964,14 @@
 		 * If we happened to stop on the last segment, then
 		 * our residual information is still correct from
 		 * the idle loop and there is no need to perform
-		 * any fixups.  Just jump to data_phase_finish.
+		 * any fixups.
 		 */
 ultra2_ensure_sg:
 		test	SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
 		/* Record if we've consumed all S/G entries */
-		test	SG_CACHE_SHADOW, LAST_SEG_DONE jz data_phase_finish;
+		test    SSTAT2, SHVALID	jnz residuals_correct;
 		or	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
-		jmp	data_phase_finish;
+		jmp	residuals_correct;
 
 ultra2_shvalid:
                 test    SSTAT2, SHVALID	jnz sgptr_fixup;
@@ -998,6 +1001,62 @@
 		test	SG_CACHE_SHADOW, ODD_SEG jz . + 2;
 		or	DATA_COUNT_ODD, 0x1;
 		clr	SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
+residuals_correct:
+		/*
+		 * Go ahead and shut down the DMA engine now.
+		 * In the future, we'll want to handle end of
+		 * transfer messages prior to doing this, but this
+		 * requires similar restructuring for pre-ULTRA2
+		 * controllers.
+		 */
+		test	DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
+ultra2_fifoflush:
+		if ((ahc->features & AHC_DT) == 0) {
+			if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
+				/*
+				 * On Rev A of the aic7890, the autoflush
+				 * feature doesn't function correctly.
+				 * Perform an explicit manual flush.  During
+				 * a manual flush, the FIFOEMP bit becomes
+				 * true every time the PCI FIFO empties
+				 * regardless of the state of the SCSI FIFO.
+				 * It can take up to 4 clock cycles for the
+				 * SCSI FIFO to get data into the PCI FIFO
+				 * and for FIFOEMP to de-assert.  Here we
+				 * guard against this condition by making
+				 * sure the FIFOEMP bit stays on for 5 full
+				 * clock cycles.
+				 */
+				or	DFCNTRL, FIFOFLUSH;
+				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+			}
+			test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
+		} else {
+			/*
+			 * We enable the auto-ack feature on DT capable
+			 * controllers.  This means that the controller may
+			 * have already transferred some overrun bytes into
+			 * the data FIFO and acked them on the bus.  The only
+			 * way to detect this situation is to wait for
+			 * LAST_SEG_DONE to come true on a completed transfer
+			 * and then test to see if the data FIFO is non-empty.
+			 */
+			test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 4;
+			test	SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
+			test	DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
+			/* Overrun */
+			jmp	data_phase_loop;
+			test	DFSTATUS, FIFOEMP jz .;
+		}
+ultra2_fifoempty:
+		/* Don't clobber an inprogress host data transfer */
+		test	DFSTATUS, MREQPEND	jnz ultra2_fifoempty;
+ultra2_dmahalt:
+		and     DFCNTRL, ~(SCSIEN|HDMAEN);
+		test	DFCNTRL, SCSIEN|HDMAEN jnz .;
 	} else {
 		/* If we are the last SG block, tell the hardware. */
 		if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
@@ -1156,7 +1215,11 @@
 	}
 	if ((ahc->flags & AHC_INITIATORROLE) != 0) {
 		test	SSTAT1, REQINIT jz .;
-		test	SSTAT1,PHASEMIS	jz data_phase_loop;
+		if ((ahc->features & AHC_DT) == 0) {
+			test	SSTAT1,PHASEMIS	jz data_phase_loop;
+		} else {
+			test	SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
+		}
 	}
 
 data_phase_done:
@@ -1296,13 +1359,17 @@
 		or	DFCNTRL, FIFOFLUSH;
 	}
 p_command_loop:
-	test	SSTAT0, SDONE jnz . + 2;
-	test    SSTAT1, PHASEMIS jz p_command_loop;
-	/*
-	 * Wait for our ACK to go-away on it's own
-	 * instead of being killed by SCSIEN getting cleared.
-	 */
-	test	SCSISIGI, ACKI jnz .;
+	if ((ahc->features & AHC_DT) == 0) {
+		test	SSTAT0, SDONE jnz . + 2;
+		test    SSTAT1, PHASEMIS jz p_command_loop;
+		/*
+		 * Wait for our ACK to go-away on it's own
+		 * instead of being killed by SCSIEN getting cleared.
+		 */
+		test	SCSISIGI, ACKI jnz .;
+	} else {
+		test	DFCNTRL, SCSIEN jnz p_command_loop;
+	}
 	and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
 	test	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
 	if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1346,23 +1413,16 @@
  * reason.
  */
 p_mesgout_retry:
-	or	SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
+	/* Turn on ATN for the retry */
+	if ((ahc->features & AHC_DT) == 0) {
+		or	SCSISIGO, ATNO, LASTPHASE;
+	} else {
+		mvi	SCSISIGO, ATNO;
+	}
 p_mesgout:
 	mov	SINDEX, MSG_OUT;
 	cmp	SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
 	test	SCB_CONTROL,MK_MESSAGE	jnz host_message_loop;
-	mov	FUNCTION1, SCB_SCSIID;
-	mov	A, FUNCTION1;
-	mov	SINDEX, TARGET_MSG_REQUEST[0];
-	if ((ahc->features & AHC_TWIN) != 0) {
-		/* Second Channel uses high byte bits */
-		test	SCB_SCSIID, TWIN_CHNLB jz . + 2;
-		mov	SINDEX, TARGET_MSG_REQUEST[1];
-	} else if ((ahc->features & AHC_WIDE) != 0) {
-		test	SCB_SCSIID, 0x80	jz . + 2; /* target > 7 */
-		mov	SINDEX, TARGET_MSG_REQUEST[1];
-	}
-	test	SINDEX, A	jnz host_message_loop;
 p_mesgout_identify:
 	or	SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
 	test	SCB_CONTROL, DISCENB jnz . + 2;
@@ -1555,10 +1615,17 @@
  * only if we've actually been into a data phase to change them.  This
  * protects against bogus data in scratch ram and the residual counts
  * since they are only initialized when we go into data_in or data_out.
+ * Ack the message as soon as possible.  For chips without S/G pipelining,
+ * we can only ack the message after SHADDR has been saved.  On these
+ * chips, SHADDR increments with every bus transaction, even PIO.
  */
 mesgin_sdptrs:
-	test	SEQ_FLAGS, DPHASE	jz mesgin_done;
-
+	if ((ahc->features & AHC_ULTRA2) != 0) {
+		mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/
+		test	SEQ_FLAGS, DPHASE	jz ITloop;
+	} else {
+		test	SEQ_FLAGS, DPHASE	jz mesgin_done;
+	}
 	/*
 	 * The SCB_SGPTR becomes the next one we'll download,
 	 * and the SCB_DATAPTR becomes the current SHADDR.
@@ -1567,13 +1634,17 @@
 	 */
 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
 		bmov	SCB_DATAPTR, SHADDR, 4;
+		if ((ahc->features & AHC_ULTRA2) == 0) {
+			mov	NONE,SCSIDATL;	/*dummy read from latch to ACK*/
+		}
 		bmov	SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
 	} else {
 		mvi	DINDEX, SCB_DATAPTR;
 		mvi	SHADDR call bcopy_4;
+		mov	NONE,SCSIDATL;	/*dummy read from latch to ACK*/
 		mvi	SCB_RESIDUAL_DATACNT call bcopy_8;
 	}
-	jmp	mesgin_done;
+	jmp	ITloop;
 
 /*
  * Restore pointers message?  Data pointers are recopied from the
@@ -1751,7 +1822,11 @@
 	jmp	mesgin_done;
 
 mk_mesg:
-	or	SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
+	if ((ahc->features & AHC_DT) == 0) {
+		or	SCSISIGO, ATNO, LASTPHASE;
+	} else {
+		mvi	SCSISIGO, ATNO;
+	}
 	mov	MSG_OUT,SINDEX ret;
 
 /*
@@ -1924,7 +1999,9 @@
 	test	SSTAT1, REQINIT jz phase_lock;
 	test	SSTAT1, SCSIPERR jnz phase_lock_perr;
 phase_lock_latch_phase:
-	and	SCSISIGO, PHASE_MASK, SCSISIGI;
+	if ((ahc->features & AHC_DT) == 0) {
+		and	SCSISIGO, PHASE_MASK, SCSISIGI;
+	}
 	and	LASTPHASE, PHASE_MASK, SCSISIGI ret;
 
 if ((ahc->features & AHC_CMD_CHAN) == 0) {
@@ -2068,9 +2145,9 @@
 			 * latch is full.
 			 */
 			clr	A;
-			/* Wait for some data to arrive. */
+			/* Wait for at least 8 bytes of data to arrive. */
 dma_scb_hang_fifo:
-			test	DFSTATUS, FIFOEMP jnz dma_scb_hang_fifo;
+			test	DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
 dma_scb_hang_wait:
 			test	DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
 			test	DFSTATUS, HDONE	jnz dma_scb_hang_dma_done;
@@ -2078,8 +2155,7 @@
 			test	DFSTATUS, HDONE	jnz dma_scb_hang_dma_done;
 			/*
 			 * The PCI module no longer intends to perform
-			 * a PCI transaction and HDONE has not come true.
-			 * We are hung.  Drain the fifo.
+			 * a PCI transaction.  Drain the fifo.
 			 */
 dma_scb_hang_empty_fifo:
 			/*
@@ -2101,6 +2177,7 @@
 			 */
 			not	SINDEX;
 			add	A, 5, SINDEX;
+			cmp	A, 4	je dma_finish_nowait;
 			jmp	dma_scb_hang_fifo;
 dma_scb_hang_dma_done:
 			and	DFCNTRL, ~HDMAEN;
@@ -2146,6 +2223,7 @@
  */
 dma_finish:
 	test	DFSTATUS,HDONE	jz dma_finish;
+dma_finish_nowait:
 	/* Turn off DMA */
 	and	DFCNTRL, ~HDMAEN;
 	test	DFCNTRL, HDMAEN jnz .;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_inline.h linux/drivers/scsi/aic7xxx/aic7xxx_inline.h
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_inline.h	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_inline.h	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#15 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#21 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_inline.h,v 1.8 2000/11/12 05:19:46 gibbs Exp $
  */
@@ -37,10 +37,10 @@
 #define _AIC7XXX_INLINE_H_
 
 /************************* Sequencer Execution Control ************************/
-static __inline int  sequencer_paused(struct ahc_softc *ahc);
+static __inline int  ahc_is_paused(struct ahc_softc *ahc);
 static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
-static __inline void pause_sequencer(struct ahc_softc *ahc);
-static __inline void unpause_sequencer(struct ahc_softc *ahc);
+static __inline void ahc_pause(struct ahc_softc *ahc);
+static __inline void ahc_unpause(struct ahc_softc *ahc);
 
 /*
  * Work around any chip bugs related to halting sequencer execution.
@@ -62,7 +62,7 @@
  * Returns non-zero status if the sequencer is stopped.
  */
 static __inline int
-sequencer_paused(struct ahc_softc *ahc)
+ahc_is_paused(struct ahc_softc *ahc)
 {
 	return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
 }
@@ -75,7 +75,7 @@
  * for critical sections.
  */
 static __inline void
-pause_sequencer(struct ahc_softc *ahc)
+ahc_pause(struct ahc_softc *ahc)
 {
 	ahc_outb(ahc, HCNTRL, ahc->pause);
 
@@ -83,7 +83,7 @@
 	 * Since the sequencer can disable pausing in a critical section, we
 	 * must loop until it actually stops.
 	 */
-	while (sequencer_paused(ahc) == 0)
+	while (ahc_is_paused(ahc) == 0)
 		;
 
 	ahc_pause_bug_fix(ahc);
@@ -100,7 +100,7 @@
  * condition.
  */
 static __inline void
-unpause_sequencer(struct ahc_softc *ahc)
+ahc_unpause(struct ahc_softc *ahc)
 {
 	if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
 		ahc_outb(ahc, HCNTRL, ahc->unpause);
@@ -188,12 +188,12 @@
 
 /*********************** Miscelaneous Support Functions ***********************/
 
-static __inline int	ahc_check_residual(struct scb *scb);
+static __inline void	ahc_update_residual(struct scb *scb);
 static __inline struct ahc_initiator_tinfo *
 			ahc_fetch_transinfo(struct ahc_softc *ahc,
 					    char channel, u_int our_id,
 					    u_int remote_id,
-					    struct tmode_tstate **tstate);
+					    struct ahc_tmode_tstate **tstate);
 static __inline struct scb*
 			ahc_get_scb(struct ahc_softc *ahc);
 static __inline void	ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
@@ -211,15 +211,16 @@
  * Determine whether the sequencer reported a residual
  * for this SCB/transaction.
  */
-static __inline int
-ahc_check_residual(struct scb *scb)
+static __inline void
+ahc_update_residual(struct scb *scb)
 {
-	struct status_pkt *sp;
+	uint32_t sgptr;
 
-	sp = &scb->hscb->shared_data.status;
-	if ((scb->hscb->sgptr & SG_RESID_VALID) != 0)
-		return (1);
-	return (0);
+	sgptr = ahc_le32toh(scb->hscb->sgptr);
+	if ((sgptr & SG_RESID_VALID) != 0)
+		ahc_calc_residual(scb);
+	else
+		ahc_set_residual(scb, 0);
 }
 
 /*
@@ -228,7 +229,7 @@
  */
 static __inline struct ahc_initiator_tinfo *
 ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
-		    u_int remote_id, struct tmode_tstate **tstate)
+		    u_int remote_id, struct ahc_tmode_tstate **tstate)
 {
 	/*
 	 * Transfer data structures are stored from the perspective
@@ -345,10 +346,10 @@
 		ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
 	} else {
 		if ((ahc->features & AHC_AUTOPAUSE) == 0)
-			pause_sequencer(ahc);
+			ahc_pause(ahc);
 		ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
 		if ((ahc->features & AHC_AUTOPAUSE) == 0)
-			unpause_sequencer(ahc);
+			ahc_unpause(ahc);
 	}
 }
 
@@ -412,19 +413,28 @@
 	 * completion queues.  This avoids a costly PCI bus read in
 	 * most cases.
 	 */
-	intstat = 0;
-	if ((queuestat = ahc_check_cmdcmpltqueues(ahc)) != 0)
+	if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
+	 && (queuestat = ahc_check_cmdcmpltqueues(ahc)) != 0)
 		intstat = CMDCMPLT;
-
-	if ((intstat & INT_PEND) == 0
-	 || (ahc->flags & AHC_ALL_INTERRUPTS) != 0) {
-
+	else {
 		intstat = ahc_inb(ahc, INTSTAT);
+		/*
+		 * We can't generate queuestat once above
+		 * or we are exposed to a race when our
+		 * interrupt is shared with another device.
+		 * if instat showed a command complete interrupt,
+		 * but our first generation of queue stat
+		 * "just missed" the delivery of this transaction,
+		 * we would clear the command complete interrupt
+		 * below without ever servicing the completed
+		 * command.
+		 */
+		queuestat = ahc_check_cmdcmpltqueues(ahc);
 #if AHC_PCI_CONFIG > 0
 		if (ahc->unsolicited_ints > 500
 		 && (ahc->chip & AHC_PCI) != 0
 		 && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
-			ahc_pci_intr(ahc);
+			ahc->bus_intr(ahc);
 #endif
 	}
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c linux/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c	Fri Apr 27 13:59:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux.c	Sun May 20 12:11:39 2001
@@ -1,7 +1,7 @@
 /*
  * Adaptec AIC7xxx device driver for Linux.
  *
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c#54 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c#66 $
  *
  * Copyright (c) 1994 John Aycock
  *   The University of Calgary Department of Computer Science.
@@ -112,6 +112,7 @@
  *  8: SMP friendliness has been improved
  *
  */
+
 #include <linux/config.h>
 
 /*
@@ -158,8 +159,8 @@
  * The scsi error recovery code performs its own bus settle
  * delay handling for error recovery actions.
  */
-#ifdef CONFIG_AIC7XXX_RESET_DELAY
-#define AIC7XXX_RESET_DELAY CONFIG_AIC7XXX_RESET_DELAY
+#ifdef CONFIG_AIC7XXX_RESET_DELAY_MS
+#define AIC7XXX_RESET_DELAY CONFIG_AIC7XXX_RESET_DELAY_MS
 #else
 #define AIC7XXX_RESET_DELAY 5000
 #endif
@@ -479,45 +480,48 @@
 
 #endif
 
-static void ahc_handle_scsi_status(struct ahc_softc *,
-				   struct ahc_linux_device *, struct scb *);
-static void ahc_filter_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd);
-static void ahc_sem_timeout(u_long arg);
-static void ahc_release_sim_queue(u_long arg);
-static int aic7xxx_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
-static void aic7xxx_initialize_scsi_bus(struct ahc_softc *ahc);
-static void aic7xxx_select_queue_depth(struct Scsi_Host *host,
-				       Scsi_Device *scsi_devs);
-static void aic7xxx_device_queue_depth(struct ahc_softc *ahc,
-				       Scsi_Device *device);
-static struct ahc_linux_target*	ahc_alloc_target(struct ahc_softc *,
-						 u_int, u_int);
-static void			ahc_free_target(struct ahc_softc *ahc,
-						struct ahc_linux_target *targ);
-static struct ahc_linux_device*	ahc_alloc_device(struct ahc_softc *,
-						 struct ahc_linux_target *,
-						 u_int);
-static void			ahc_free_device(struct ahc_softc *ahc,
-						struct ahc_linux_device *dev);
-static void ahc_run_device_queue(struct ahc_softc *ahc,
-				 struct ahc_linux_device *dev);
-static void ahc_setup_tag_info(char *p, char *end);
-static int ahc_next_unit(void);
+static void ahc_linux_handle_scsi_status(struct ahc_softc *,
+					 struct ahc_linux_device *,
+					 struct scb *);
+static void ahc_linux_filter_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd);
+static void ahc_linux_sem_timeout(u_long arg);
+static void ahc_linux_freeze_sim_queue(struct ahc_softc *ahc);
+static void ahc_linux_release_sim_queue(u_long arg);
+static int  ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
+static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
+static void ahc_linux_select_queue_depth(struct Scsi_Host *host,
+					 Scsi_Device *scsi_devs);
+static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
+					 Scsi_Device *device);
+static struct ahc_linux_target*	ahc_linux_alloc_target(struct ahc_softc*,
+						       u_int, u_int);
+static void			ahc_linux_free_target(struct ahc_softc*,
+						      struct ahc_linux_target*);
+static struct ahc_linux_device*	ahc_linux_alloc_device(struct ahc_softc*,
+						       struct ahc_linux_target*,
+						       u_int);
+static void			ahc_linux_free_device(struct ahc_softc*,
+						      struct ahc_linux_device*);
+static void ahc_linux_run_device_queue(struct ahc_softc*,
+				       struct ahc_linux_device*);
+static void ahc_linux_setup_tag_info(char *p, char *end);
+static int ahc_linux_next_unit(void);
+static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf);
 
 static __inline struct ahc_linux_device*
-		     ahc_get_device(struct ahc_softc *ahc, u_int channel,
-				    u_int target, u_int lun, int /*alloc*/);
-static __inline void ahc_queue_cmd_complete(struct ahc_softc *ahc,
-					    Scsi_Cmnd *cmd);
-static __inline void ahc_run_complete_queue(struct ahc_softc *ahc,
-					    struct ahc_cmd *acmd);
-static __inline void ahc_check_device_queue(struct ahc_softc *ahc,
-					  struct ahc_linux_device *dev);
-static __inline void ahc_sniff_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd);
-static __inline void ahc_unmap_scb(struct ahc_softc *ahc, struct scb *scb);
+		     ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
+					  u_int target, u_int lun, int alloc);
+static __inline void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
+						  Scsi_Cmnd *cmd);
+static __inline void ahc_linux_run_complete_queue(struct ahc_softc *ahc,
+						  struct ahc_cmd *acmd);
+static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
+						  struct ahc_linux_device *dev);
+static __inline void ahc_linux_sniff_command(struct ahc_softc*, Scsi_Cmnd*);
+static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
 
 static __inline struct ahc_linux_device*
-ahc_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
+ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
 	       u_int lun, int alloc)
 {
 	struct ahc_linux_target *targ;
@@ -530,7 +534,7 @@
 	targ = ahc->platform_data->targets[target_offset];
 	if (targ == NULL) {
 		if (alloc != 0) {
-			targ = ahc_alloc_target(ahc, channel, target);
+			targ = ahc_linux_alloc_target(ahc, channel, target);
 			if (targ == NULL)
 				return (NULL);
 		} else
@@ -538,17 +542,17 @@
 	}
 	dev = targ->devices[lun];
 	if (dev == NULL && alloc != 0)
-		dev = ahc_alloc_device(ahc, targ, lun);
+		dev = ahc_linux_alloc_device(ahc, targ, lun);
 	return (dev);
 }
 
 static __inline void
-ahc_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
+ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
 {
 	/*
 	 * Typically, the complete queue has very few entries
 	 * queued to it before the queue is emptied by
-	 * ahc_run_complete_queue, so sorting the entries
+	 * ahc_linux_run_complete_queue, so sorting the entries
 	 * by generation number should be inexpensive.
 	 * We perform the sort so that commands that complete
 	 * with an error are retuned in the order origionally
@@ -584,7 +588,7 @@
 }
 
 static __inline void
-ahc_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd)
+ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd)
 {	
 	u_long done_flags;
 
@@ -601,7 +605,8 @@
 }
 
 static __inline void
-ahc_check_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+ahc_linux_check_device_queue(struct ahc_softc *ahc,
+			     struct ahc_linux_device *dev)
 {
 	if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0
 	 && dev->active == 0) {
@@ -613,11 +618,11 @@
 	 || dev->openings == 0 || dev->qfrozen != 0)
 		return;
 
-	ahc_run_device_queue(ahc, dev);
+	ahc_linux_run_device_queue(ahc, dev);
 }
 
 static __inline void
-ahc_run_device_queues(struct ahc_softc *ahc)
+ahc_linux_run_device_queues(struct ahc_softc *ahc)
 {
 	struct ahc_linux_device *dev;
 
@@ -626,25 +631,25 @@
 	    && (dev = LIST_FIRST(&ahc->platform_data->device_runq)) != NULL) {
 		LIST_REMOVE(dev, links);
 		dev->flags &= ~AHC_DEV_ON_RUN_LIST;
-		ahc_check_device_queue(ahc, dev);
+		ahc_linux_check_device_queue(ahc, dev);
 	}
 }
 
 static __inline void
-ahc_sniff_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
+ahc_linux_sniff_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
 {
 	/*
 	 * Determine whether we care to filter
 	 * information out of this command.  If so,
-	 * pass it on to ahc_filter_command() for more
+	 * pass it on to ahc_linux_filter_command() for more
 	 * heavy weight processing.
 	 */
 	if (cmd->cmnd[0] == INQUIRY)
-		ahc_filter_command(ahc, cmd);
+		ahc_linux_filter_command(ahc, cmd);
 }
 
 static __inline void
-ahc_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
+ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
 {
 	Scsi_Cmnd *cmd;
 
@@ -662,6 +667,24 @@
 				 scsi_to_pci_dma_dir(cmd->sc_data_direction));
 }
 
+/************************ Shutdown/halt/reboot hook ***************************/
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+static struct notifier_block ahc_linux_notifier = {
+	ahc_linux_halt, NULL, 0
+};
+
+static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf)
+{
+	struct ahc_softc *ahc;
+
+	TAILQ_FOREACH(ahc, &ahc_tailq, links) {
+		ahc_shutdown(ahc);
+	}
+	return (NOTIFY_OK);
+}
+
 /******************************** Macros **************************************/
 #define BUILD_SCSIID(ahc, cmd)						\
 	((((cmd)->target << TID_SHIFT) & TID)				\
@@ -820,6 +843,9 @@
 	/* Still equal.  Sort by BIOS address, ioport, or bus/slot/func. */
 	switch (rvalue) {
 	case AHC_PCI:
+	{
+		char primary_channel;
+
 		value = ahc_get_pci_bus(lahc->dev_softc)
 		      - ahc_get_pci_bus(rahc->dev_softc);
 		if (value != 0)
@@ -828,19 +854,18 @@
 		      - ahc_get_pci_slot(rahc->dev_softc);
 		if (value != 0)
 			break;
-		value = ahc_get_pci_function(lahc->dev_softc)
-		      - ahc_get_pci_function(rahc->dev_softc);
 		/*
 		 * On multi-function devices, the user can choose
 		 * to have function 1 probed before function 0.
-		 * Function 0 is the only one that will have
-		 * CHANNEL_B_PRIMARY set.
+		 * Give whichever channel is the primary channel
+		 * the lowest priority.
 		 */
-		if (value < 0
-		 && (lahc->flags & AHC_CHANNEL_B_PRIMARY) != 0)
-			/* Swap the two */
-			value = -value;
+		primary_channel = (lahc->flags & AHC_PRIMARY_CHANNEL) + 'A';
+		value = 1;
+		if (lahc->channel == primary_channel)
+			value = -1;
 		break;
+	}
 	case AHC_EISA:
 		if ((rahc->flags & AHC_BIOS_ENABLED) != 0) {
 			value = lahc->platform_data->bios_address
@@ -857,7 +882,7 @@
 }
 
 static void
-ahc_setup_tag_info(char *p, char *end)
+ahc_linux_setup_tag_info(char *p, char *end)
 {
 	char	*base;
 	char	*tok;
@@ -865,7 +890,7 @@
 	char	*tok_end2;
 	int      i;
 	int      instance;
-	int	 device;
+	int	 targ;
 	int	 done;
 	char	 tok_list[] = {'.', ',', '{', '}', '\0'};
 
@@ -873,7 +898,7 @@
 		return;
 
 	instance = -1;
-	device = -1;
+	targ = -1;
 	done = FALSE;
 	base = p;
 	/* Forward us just past the ':' */
@@ -886,13 +911,13 @@
 		case '{':
 			if (instance == -1)
 				instance = 0;
-			else if (device == -1)
-				device = 0;
+			else if (targ == -1)
+				targ = 0;
 			tok++;
 			break;
 		case '}':
-			if (device != -1)
-				device = -1;
+			if (targ != -1)
+				targ = -1;
 			else if (instance != -1)
 				instance = -1;
 			tok++;
@@ -901,11 +926,11 @@
 		case '.':
 			if (instance == -1)
 				done = TRUE;
-			else if (device >= 0)
-				device++;
+			else if (targ >= 0)
+				targ++;
 			else if (instance >= 0)
 				instance++;
-			if ((device >= AHC_NUM_TARGETS) ||
+			if ((targ >= AHC_NUM_TARGETS) ||
 			    (instance >= NUM_ELEMENTS(aic7xxx_tag_info)))
 				done = TRUE;
 			tok++;
@@ -926,11 +951,12 @@
 					done = FALSE;
 				}
 			}
-			if ((instance >= 0) && (device >= 0) &&
-			    (instance < NUM_ELEMENTS(aic7xxx_tag_info)) &&
-			    (device < AHC_NUM_TARGETS))
-				aic7xxx_tag_info[instance].tag_commands[device] =
+			if ((instance >= 0) && (targ >= 0)
+			 && (instance < NUM_ELEMENTS(aic7xxx_tag_info))
+			 && (targ < AHC_NUM_TARGETS)) {
+				aic7xxx_tag_info[instance].tag_commands[targ] =
 				    simple_strtoul(tok, NULL, 0) & 0xff;
+			}
 			tok = tok_end;
 			break;
 		}
@@ -980,7 +1006,7 @@
 				continue;
 
 			if (strncmp(p, "tag_info", n) == 0) {
-				ahc_setup_tag_info(p + n, end);
+				ahc_linux_setup_tag_info(p + n, end);
 			} else if (p[n] == ':') {
 				*(options[i].flag) =
 				    simple_strtoul(p + n + 1, NULL, 0);
@@ -989,8 +1015,10 @@
 			} else {
 				*(options[i].flag) = ~(*(options[i].flag));
 			}
+			break;
 		}
 	}
+	register_reboot_notifier(&ahc_linux_notifier);
 	return 1;
 }
 
@@ -1004,7 +1032,7 @@
  * Try to detect an Adaptec 7XXX controller.
  */
 int
-aic7xxx_detect(Scsi_Host_Template *template)
+ahc_linux_detect(Scsi_Host_Template *template)
 {
 	struct	ahc_softc *ahc;
 	int     found;
@@ -1016,8 +1044,8 @@
 	 */
 	if (offsetof(struct ahc_cmd_internal, end)
 	  > offsetof(struct scsi_cmnd, host_scribble)) {
-		printf("aic7xxx_detect: SCSI data structures changed.\n");
-		printf("aic7xxx_detect: Unable to attach\n");
+		printf("ahc_linux_detect: SCSI data structures changed.\n");
+		printf("ahc_linux_detect: Unable to attach\n");
 		return (0);
 	}
 #ifdef MODULE
@@ -1054,7 +1082,7 @@
 	found = 0;
 	TAILQ_FOREACH(ahc, &ahc_tailq, links) {
 
-		if (aic7xxx_register_host(ahc, template) == 0)
+		if (ahc_linux_register_host(ahc, template) == 0)
 			found++;
 	}
 	aic7xxx_detect_complete++;
@@ -1062,7 +1090,7 @@
 }
 
 int
-aic7xxx_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
+ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
 {
 	char  buf[80];
 	struct Scsi_Host *host;
@@ -1081,12 +1109,13 @@
 	host->can_queue = AHC_MAX_QUEUE;
 	host->cmd_per_lun = 2;
 	host->sg_tablesize = AHC_NSEG;
-	host->select_queue_depths = aic7xxx_select_queue_depth;
+	host->select_queue_depths = ahc_linux_select_queue_depth;
+	/* XXX No way to communicate the ID for multiple channels */
 	host->this_id = ahc->our_id;
 	host->irq = ahc->platform_data->irq;
 	host->max_id = (ahc->features & AHC_WIDE) ? 16 : 8;
 	host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
-	ahc_set_unit(ahc, ahc_next_unit());
+	ahc_set_unit(ahc, ahc_linux_next_unit());
 	sprintf(buf, "scsi%d", host->host_no);
 	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
 	if (new_name != NULL) {
@@ -1094,8 +1123,10 @@
 		ahc_set_name(ahc, new_name);
 	}
 	host->unique_id = ahc->unit;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
 	scsi_set_pci_device(host, ahc->dev_softc);
-	aic7xxx_initialize_scsi_bus(ahc);
+#endif
+	ahc_linux_initialize_scsi_bus(ahc);
 	ahc_unlock(ahc, &s);
 	return (0);
 }
@@ -1107,7 +1138,7 @@
  * scenario.
  */
 static int
-ahc_next_unit()
+ahc_linux_next_unit()
 {
 	struct ahc_softc *ahc;
 	int unit;
@@ -1129,7 +1160,7 @@
  * target.
  */
 void
-aic7xxx_initialize_scsi_bus(struct ahc_softc *ahc)
+ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
 {
 	int i;
 	int numtarg;
@@ -1159,7 +1190,7 @@
 	for (; i < numtarg; i++) {
 		struct ahc_devinfo devinfo;
 		struct ahc_initiator_tinfo *tinfo;
-		struct tmode_tstate *tstate;
+		struct ahc_tmode_tstate *tstate;
 		u_int our_id;
 		u_int target_id;
 		char channel;
@@ -1175,20 +1206,27 @@
 		tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
 					    target_id, &tstate);
 		tinfo->goal = tinfo->user;
+		/*
+		 * Don't try negotiations that require PPR messages
+		 * until we successfully retrieve Inquiry data.
+		 */
+		tinfo->goal.ppr_options = 0;
+		if (tinfo->goal.transport_version > SCSI_REV_2)
+			tinfo->goal.transport_version = SCSI_REV_2;
 		ahc_compile_devinfo(&devinfo, our_id, target_id,
 				   CAM_LUN_WILDCARD, channel, ROLE_INITIATOR);
-		ahc_update_target_msg_request(ahc, &devinfo, tinfo,
-					     /*force*/FALSE, /*paused*/FALSE);
+		ahc_update_neg_request(ahc, &devinfo, tstate,
+				       tinfo, /*force*/FALSE);
 	}
 	/* Give the bus some time to recover */
 	if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
-		ahc->platform_data->qfrozen++;
+		ahc_linux_freeze_sim_queue(ahc);
 		init_timer(&ahc->platform_data->reset_timer);
 		ahc->platform_data->reset_timer.data = (u_long)ahc;
 		ahc->platform_data->reset_timer.expires =
 		    jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
 		ahc->platform_data->reset_timer.function =
-		    ahc_release_sim_queue;
+		    ahc_linux_release_sim_queue;
 		add_timer(&ahc->platform_data->reset_timer);
 	}
 }
@@ -1238,6 +1276,11 @@
 					   0x1000);
 #endif
 		}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+		/* XXX Need an instance detach in the PCI code */
+		if (ahc->dev_softc != NULL)
+			ahc->dev_softc->driver = NULL;
+#endif
 		free(ahc->platform_data, M_DEVBUF);
 	}
 }
@@ -1252,28 +1295,41 @@
 }
 
 void
-ahc_platform_set_tags(struct ahc_softc *ahc,
-		      struct ahc_devinfo *devinfo, int enable)
+ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+		      ahc_queue_alg alg)
 {
 	struct ahc_linux_device *dev;
+	int was_queuing;
+	int now_queuing;
 
-	dev = ahc_get_device(ahc, devinfo->channel - 'A',
-			     devinfo->target,
-			     devinfo->lun, /*alloc*/FALSE);
+	dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',
+				   devinfo->target,
+				   devinfo->lun, /*alloc*/FALSE);
+	was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
+	now_queuing = alg != AHC_QUEUE_NONE;
 	if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0
+	 && (was_queuing != now_queuing)
 	 && (dev->active != 0)) {
 		dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY;
 		dev->qfrozen++;
 	}
 
-	if (enable) {
-		/*
-		 * Start out agressively and allow our
-		 * dynamic queue depth algorithm take
-		 * care of the rest.
-		 */
-		dev->maxtags = AHC_MAX_QUEUE;
-		dev->openings = dev->maxtags - dev->active;
+	dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
+	if (now_queuing) {
+
+		if (!was_queuing) {
+			/*
+			 * Start out agressively and allow our
+			 * dynamic queue depth algorithm to take
+			 * care of the rest.
+			 */
+			dev->maxtags = AHC_MAX_QUEUE;
+			dev->openings = dev->maxtags - dev->active;
+		}
+		if (alg == AHC_QUEUE_TAGGED)
+			dev->flags |= AHC_DEV_Q_TAGGED;
+		else
+			dev->flags |= AHC_DEV_Q_BASIC;
 	} else {
 		/* We can only have one opening */
 		dev->maxtags = 0;
@@ -1326,9 +1382,9 @@
 				struct ahc_busyq *busyq;
 				struct ahc_cmd *acmd;
 
-				dev = ahc_get_device(ahc, chan, targ,
-						     clun, /*alloc*/FALSE);
-
+				dev = ahc_linux_get_device(ahc, chan,
+							   targ, clun,
+							   /*alloc*/FALSE);
 				if (dev == NULL)
 					continue;
 
@@ -1341,7 +1397,7 @@
 						     acmd_links.tqe);
 					count++;
 					cmd->result = status << 16;
-					ahc_queue_cmd_complete(ahc, cmd);
+					ahc_linux_queue_cmd_complete(ahc, cmd);
 				}
 			}
 		}
@@ -1355,8 +1411,8 @@
  * off the input host adapter.
  */
 static void
-aic7xxx_select_queue_depth(struct Scsi_Host * host,
-			   Scsi_Device * scsi_devs)
+ahc_linux_select_queue_depth(struct Scsi_Host * host,
+			     Scsi_Device * scsi_devs)
 {
 	Scsi_Device *device;
 	struct	ahc_softc *ahc;
@@ -1368,7 +1424,7 @@
 	scbnum = 0;
 	for (device = scsi_devs; device != NULL; device = device->next) {
 		if (device->host == host) {
-			aic7xxx_device_queue_depth(ahc, device);
+			ahc_linux_device_queue_depth(ahc, device);
 			scbnum += device->queue_depth;
 		}
 	}
@@ -1379,11 +1435,11 @@
  * Determines the queue depth for a given device.
  */
 static void
-aic7xxx_device_queue_depth(struct ahc_softc *ahc, Scsi_Device * device)
+ahc_linux_device_queue_depth(struct ahc_softc *ahc, Scsi_Device * device)
 {
 	struct	ahc_devinfo devinfo;
 	struct	ahc_initiator_tinfo *targ_info;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	uint8_t tags;
 
 	ahc_compile_devinfo(&devinfo,
@@ -1397,7 +1453,7 @@
 
 	tags = 0;
 	if (device->tagged_supported != 0
-	 && (tstate->discenable & devinfo.target_mask) != 0) {
+	 && (ahc->user_discenable & devinfo.target_mask) != 0) {
 		if (ahc->unit >= NUM_ELEMENTS(aic7xxx_tag_info)) {
 
 			printf("aic7xxx: WARNING, insufficient "
@@ -1418,7 +1474,7 @@
 	}
 	if (tags != 0) {
 		device->queue_depth = tags;
-		ahc_set_tags(ahc, &devinfo, TRUE);
+		ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED);
 		printf("scsi%d:%d:%d:%d: Tagged Queuing enabled.  Depth %d\n",
 	       	       ahc->platform_data->host->host_no, device->channel,
 		       device->id, device->lun, tags);
@@ -1437,7 +1493,7 @@
  * Queue an SCB to the controller.
  */
 int
-aic7xxx_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
 {
 	struct	 ahc_softc *ahc;
 	struct	 ahc_linux_device *dev;
@@ -1451,29 +1507,29 @@
 	cmd->scsi_done = scsi_done;
 
 	ahc_lock(ahc, &flags);
-	dev = ahc_get_device(ahc, cmd->channel, cmd->target,
-			     cmd->lun, /*alloc*/TRUE);
+	dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target,
+				   cmd->lun, /*alloc*/TRUE);
 	if (dev == NULL) {
 		ahc_unlock(ahc, &flags);
-		printf("aic7xxx_queue: Unable to allocate device!\n");
+		printf("aic7xxx_linux_queue: Unable to allocate device!\n");
 		return (-ENOMEM);
 	}
 	cmd->result = CAM_REQ_INPROG << 16;
 	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);
-	ahc_run_device_queue(ahc, dev);
+	ahc_linux_run_device_queue(ahc, dev);
 	ahc_unlock(ahc, &flags);
 	return (0);
 }
 
 static void
-ahc_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
 {
 	struct	 ahc_cmd *acmd;
 	struct	 scsi_cmnd *cmd;
 	struct	 scb *scb;
 	struct	 hardware_scb *hscb;
 	struct	 ahc_initiator_tinfo *tinfo;
-	struct	 tmode_tstate *tstate;
+	struct	 ahc_tmode_tstate *tstate;
 	uint16_t mask;
 
 	while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
@@ -1524,19 +1580,26 @@
 					    SCB_GET_OUR_ID(scb),
 					    SCB_GET_TARGET(ahc, scb), &tstate);
 		hscb->scsirate = tinfo->scsirate;
-		hscb->scsioffset = tinfo->current.offset;
+		hscb->scsioffset = tinfo->curr.offset;
 		if ((tstate->ultraenb & mask) != 0)
 			hscb->control |= ULTRAENB;
 
-		if ((tstate->discenable & mask) != 0)
+		if ((ahc->user_discenable & mask) != 0)
 			hscb->control |= DISCENB;
 
-		if ((tstate->tagenable & mask) != 0) {
-			/* XXX What about devices that dislike ordered tags? */
-			if ((dev->num_commands % 256) == 0)
-				hscb->control |= MSG_ORDERED_Q_TAG;
-			else
-				hscb->control |= MSG_SIMPLE_Q_TAG;
+		if ((tstate->auto_negotiate & mask) != 0) {
+			scb->flags |= SCB_AUTO_NEGOTIATE;
+			scb->hscb->control |= MK_MESSAGE;
+		}
+
+		if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
+			if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
+			 && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
+				hscb->control |= MSG_ORDERED_TASK;
+				dev->commands_since_idle_or_otag = 0;
+			} else {
+				hscb->control |= MSG_SIMPLE_TASK;
+			}
 		}
 
 		hscb->cdb_len = cmd->cmd_len;
@@ -1632,7 +1695,8 @@
 		LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
 		dev->openings--;
 		dev->active++;
-		dev->num_commands++;
+		dev->commands_issued++;
+		dev->commands_since_idle_or_otag++;
 
 		/*
 		 * We only allow one untagged transaction
@@ -1661,7 +1725,7 @@
  * SCSI controller interrupt handler.
  */
 void
-aic7xxx_isr(int irq, void *dev_id, struct pt_regs * regs)
+ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct ahc_softc *ahc;
 	struct ahc_cmd *acmd;
@@ -1676,12 +1740,12 @@
 	 * dynamically register one, we'll have to postpone
 	 * that until we get integrated into the kernel.
 	 */
-	ahc_run_device_queues(ahc);
+	ahc_linux_run_device_queues(ahc);
 	acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
 	TAILQ_INIT(&ahc->platform_data->completeq);
 	ahc_unlock(ahc, &flags);
 	if (acmd != NULL)
-		ahc_run_complete_queue(ahc, acmd);
+		ahc_linux_run_complete_queue(ahc, acmd);
 }
 
 void
@@ -1692,11 +1756,11 @@
 	acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
 	TAILQ_INIT(&ahc->platform_data->completeq);
 	if (acmd != NULL)
-		ahc_run_complete_queue(ahc, acmd);
+		ahc_linux_run_complete_queue(ahc, acmd);
 }
 
 static struct ahc_linux_target*
-ahc_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
+ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
 {
 	struct ahc_linux_target *targ;
 	u_int target_offset;
@@ -1715,7 +1779,7 @@
 }
 
 static void
-ahc_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ)
+ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ)
 {
 	u_int target_offset;
 
@@ -1727,7 +1791,7 @@
 }
 
 static struct ahc_linux_device*
-ahc_alloc_device(struct ahc_softc *ahc,
+ahc_linux_alloc_device(struct ahc_softc *ahc,
 		 struct ahc_linux_target *targ, u_int lun)
 {
 	struct ahc_linux_device *dev;
@@ -1760,7 +1824,7 @@
 }
 
 static void
-ahc_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
 {
 	struct ahc_linux_target *targ;
 
@@ -1769,14 +1833,14 @@
 	free(dev, M_DEVBUF);
 	targ->refcount--;
 	if (targ->refcount == 0)
-		ahc_free_target(ahc, targ);
+		ahc_linux_free_target(ahc, targ);
 }
 
 /*
  * Return a string describing the driver.
  */
 const char *
-aic7xxx_info(struct Scsi_Host *host)
+ahc_linux_info(struct Scsi_Host *host)
 {
 	static char buffer[512];
 	char	ahc_info[256];
@@ -1802,7 +1866,7 @@
 
 void
 ahc_send_async(struct ahc_softc *ahc, char channel,
-	       u_int target, u_int lun, ac_code code)
+	       u_int target, u_int lun, ac_code code, void *arg)
 {
 	switch (code) {
 	case AC_TRANSFER_NEG:
@@ -1811,7 +1875,7 @@
 		struct	ahc_linux_target *targ;
 		struct	info_str info;
 		struct	ahc_initiator_tinfo *tinfo;
-		struct	tmode_tstate *tstate;
+		struct	ahc_tmode_tstate *tstate;
 		int	target_offset;
 
 		info.buffer = buf;
@@ -1827,10 +1891,10 @@
 		 * Don't bother reporting results while
 		 * negotiations are still pending.
 		 */
-		if (tinfo->current.period != tinfo->goal.period
-		 || tinfo->current.width != tinfo->goal.width
-		 || tinfo->current.offset != tinfo->goal.offset
-		 || tinfo->current.ppr_options != tinfo->goal.ppr_options)
+		if (tinfo->curr.period != tinfo->goal.period
+		 || tinfo->curr.width != tinfo->goal.width
+		 || tinfo->curr.offset != tinfo->goal.offset
+		 || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
 			if (bootverbose == 0)
 				break;
 
@@ -1843,24 +1907,24 @@
 			target_offset += 8;
 		targ = ahc->platform_data->targets[target_offset];
 		if (targ != NULL
-		 && tinfo->current.period == targ->last_tinfo.period
-		 && tinfo->current.width == targ->last_tinfo.width
-		 && tinfo->current.offset == targ->last_tinfo.offset
-		 && tinfo->current.ppr_options == targ->last_tinfo.ppr_options)
+		 && tinfo->curr.period == targ->last_tinfo.period
+		 && tinfo->curr.width == targ->last_tinfo.width
+		 && tinfo->curr.offset == targ->last_tinfo.offset
+		 && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options)
 			if (bootverbose == 0)
 				break;
 
-		targ->last_tinfo.period = tinfo->current.period;
-		targ->last_tinfo.width = tinfo->current.width;
-		targ->last_tinfo.offset = tinfo->current.offset;
-		targ->last_tinfo.ppr_options = tinfo->current.ppr_options;
+		targ->last_tinfo.period = tinfo->curr.period;
+		targ->last_tinfo.width = tinfo->curr.width;
+		targ->last_tinfo.offset = tinfo->curr.offset;
+		targ->last_tinfo.ppr_options = tinfo->curr.ppr_options;
 
 		printf("(%s:%c:", ahc_name(ahc), channel);
 		if (target == CAM_TARGET_WILDCARD)
 			printf("*): ");
 		else
 			printf("%d): ", target);
-		ahc_format_transinfo(&info, &tinfo->current);
+		ahc_format_transinfo(&info, &tinfo->curr);
 		if (info.pos < info.length)
 			*info.buffer = '\0';
 		else
@@ -1909,7 +1973,7 @@
 	dev = scb->platform_data->dev;
 	dev->active--;
 	dev->openings++;
-	ahc_unmap_scb(ahc, scb);
+	ahc_linux_unmap_scb(ahc, scb);
 	if (scb->flags & SCB_SENSE) {
 		memcpy(cmd->sense_buffer, ahc_get_sense_buf(ahc, scb),
 		       MIN(sizeof(struct scsi_sense_data),
@@ -1928,10 +1992,19 @@
 			ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
 		} else {
 			ahc_set_transaction_status(scb, CAM_REQ_CMP);
-			ahc_sniff_command(ahc, cmd);
+			ahc_linux_sniff_command(ahc, cmd);
 		}
 	} else if (ahc_get_transaction_status(scb) == DID_OK) {
-		ahc_handle_scsi_status(ahc, dev, scb);
+		ahc_linux_handle_scsi_status(ahc, dev, scb);
+	} else if (ahc_get_transaction_status(scb) == DID_NO_CONNECT) {
+		/*
+		 * Should a selection timeout kill the device?
+		 * That depends on whether the selection timeout
+		 * is persistent.  Since we have no guarantee that
+		 * the mid-layer will issue an inquiry for this device
+		 * again, we can't just kill it off.
+		dev->flags |= AHC_DEV_UNCONFIGURED;
+		 */
 	}
 
 	if (dev->openings == 1
@@ -1950,10 +2023,14 @@
 		dev->openings++;
 	}
 
-	if (dev->active == 0
-	 && (dev->flags & AHC_DEV_UNCONFIGURED) != 0)
-		ahc_free_device(ahc, dev);
-	else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
+	if (dev->active == 0)
+		dev->commands_since_idle_or_otag = 0;
+
+	if (TAILQ_EMPTY(&dev->busyq)) {
+		if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
+		 && dev->active == 0)
+			ahc_linux_free_device(ahc, dev);
+	} else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
 		LIST_INSERT_HEAD(&ahc->platform_data->device_runq, dev, links);
 		dev->flags |= AHC_DEV_ON_RUN_LIST;
 	}
@@ -1964,12 +2041,12 @@
 	}
 
 	ahc_free_scb(ahc, scb);
-	ahc_queue_cmd_complete(ahc, cmd);
+	ahc_linux_queue_cmd_complete(ahc, cmd);
 }
 
 static void
-ahc_handle_scsi_status(struct ahc_softc *ahc,
-		       struct ahc_linux_device *dev, struct scb *scb)
+ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
+			     struct ahc_linux_device *dev, struct scb *scb)
 {
 	/*
 	 * We don't currently trust the mid-layer to
@@ -2050,7 +2127,7 @@
 }
 
 static void
-ahc_filter_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
+ahc_linux_filter_command(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
 {
 	switch (cmd->cmnd[0]) {
 	case INQUIRY:
@@ -2058,8 +2135,9 @@
 		struct	ahc_devinfo devinfo;
 		struct	scsi_inquiry_data *sid;
 		struct	ahc_initiator_tinfo *targ_info;
-		struct	tmode_tstate *tstate;
+		struct	ahc_tmode_tstate *tstate;
 		struct	ahc_syncrate *syncrate;
+		struct	ahc_linux_device *dev;
 		u_int	scsiid;
 		u_int	maxsync;
 		int	minlen;
@@ -2078,15 +2156,20 @@
 		/*
 		 * Determine if this lun actually exists.  If so,
 		 * hold on to its corresponding device structure.
-		 */
+		 * If not, make sure we release the device and
+		 * don't bother processing the rest of this inquiry
+		 * command.
+		 */
+		dev = ahc_linux_get_device(ahc, cmd->channel,
+					   cmd->target, cmd->lun,
+					   /*alloc*/FALSE);
 		if (cmd->request_bufflen >= 1
 		 && SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
-			struct ahc_linux_device *dev;
 
-			dev = ahc_get_device(ahc, cmd->channel,
-					     cmd->target, cmd->lun,
-					     /*alloc*/FALSE);
 			dev->flags &= ~AHC_DEV_UNCONFIGURED;
+		} else {
+			dev->flags |= AHC_DEV_UNCONFIGURED;
+			break;
 		}
 
 		/*
@@ -2108,17 +2191,17 @@
 		ppr_options = targ_info->user.ppr_options;
 		minlen = offsetof(struct scsi_inquiry_data, version) + 1;
 		if (cmd->request_bufflen >= minlen) {
-			targ_info->current.protocol_version = SID_ANSI_REV(sid);
+			targ_info->curr.protocol_version = SID_ANSI_REV(sid);
 
 			/*
 			 * Only attempt SPI3 once we've verified that
 			 * the device claims to support SPI3 features.
 			 */
-			if (targ_info->current.protocol_version < SCSI_REV_2)
-				targ_info->current.transport_version =
+			if (targ_info->curr.protocol_version < SCSI_REV_2)
+				targ_info->curr.transport_version =
 				    SID_ANSI_REV(sid);
 			else
-				targ_info->current.transport_version =
+				targ_info->curr.transport_version =
 				     SCSI_REV_2;
 		}
 
@@ -2137,18 +2220,26 @@
 			break;
 		}
 		minlen = offsetof(struct scsi_inquiry_data, spi3data) + 1;
-		if (cmd->request_bufflen >= minlen
-		 && (sid->additional_length + 4) >= minlen) {
-			if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0)
+		/*
+		 * This is a kludge to deal with inquiry requests that
+		 * are not large enough for us to pull the spi3 bits.
+		 * In this case, we assume that a device that tells us
+		 * they can provide inquiry data that spans the SPI3
+		 * bits can handle a PPR request.  If the inquiry
+		 * request has sufficient buffer space to cover these
+		 * bits, we check them to see if any ppr options are
+		 * available.
+		 */
+		if ((sid->additional_length + 4) >= minlen) {
+			if (cmd->request_bufflen >= minlen
+			 && (sid->spi3data & SID_SPI_CLOCK_DT) == 0)
 				ppr_options = 0;
 
-			if ((sid->spi3data & SID_SPI_MASK) != 0
-			 && targ_info->current.protocol_version > SCSI_REV_2)
-				targ_info->current.transport_version = 3;
+			if (targ_info->curr.protocol_version > SCSI_REV_2)
+				targ_info->curr.transport_version = 3;
 		} else {
 			ppr_options = 0;
 		}
-
 		ahc_validate_width(ahc, /*tinfo limit*/NULL, &width,
 				   ROLE_UNKNOWN);
 		if ((ahc->features & AHC_ULTRA2) != 0)
@@ -2162,6 +2253,11 @@
 					     &ppr_options, maxsync);
 		ahc_validate_offset(ahc, /*tinfo limit*/NULL, syncrate,
 				    &offset, width, ROLE_UNKNOWN);
+		if (offset == 0 || period == 0) {
+			period = 0;
+			offset = 0;
+			ppr_options = 0;
+		}
 		/* Apply our filtered user settings. */
 		ahc_set_width(ahc, &devinfo, width,
 			      AHC_TRANS_GOAL, /*paused*/FALSE);
@@ -2171,14 +2267,14 @@
 		break;
 	}
 	default:
-		panic("ahc_filter_command: Unexpected Command type  %x\n",
+		panic("ahc_linux_filter_command: Unexpected Command type  %x\n",
 		      cmd->cmnd[0]);
 		break;
 	}
 }
 
 static void
-ahc_sem_timeout(u_long arg)
+ahc_linux_sem_timeout(u_long arg)
 {
 	struct semaphore *sem;
 
@@ -2187,22 +2283,42 @@
 }
 
 static void
-ahc_release_sim_queue(u_long arg)
+ahc_linux_freeze_sim_queue(struct ahc_softc *ahc)
+{
+	ahc->platform_data->qfrozen++;
+	if (ahc->platform_data->qfrozen == 1)
+		scsi_block_requests(ahc->platform_data->host);
+}
+
+static void
+ahc_linux_release_sim_queue(u_long arg)
 {
 	struct ahc_softc *ahc;
 	u_long s;
+	int    unblock_reqs;
 
 	ahc = (struct ahc_softc *)arg;
+	unblock_reqs = 0;
 	ahc_lock(ahc, &s);
 	if (ahc->platform_data->qfrozen > 0)
 		ahc->platform_data->qfrozen--;
-	if (ahc->platform_data->qfrozen == 0)
-		ahc_run_device_queues(ahc);
+	if (ahc->platform_data->qfrozen == 0) {
+		unblock_reqs = 1;
+		ahc_linux_run_device_queues(ahc);
+	}
 	ahc_unlock(ahc, &s);
+	/*
+	 * There is still a race here.  The mid-layer
+	 * should keep its own freeze count and use
+	 * a bottom half handler to run the queues
+	 * so we can unblock with our own lock held.
+	 */
+	if (unblock_reqs)
+		scsi_unblock_requests(ahc->platform_data->host);
 }
 
 static int
-aic7xxx_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
+ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
 {
 	struct ahc_softc *ahc;
 	struct ahc_cmd *acmd;
@@ -2242,8 +2358,8 @@
 	 * at all, and the system wanted us to just abort the
 	 * command return success.
 	 */
-	dev = ahc_get_device(ahc, cmd->channel, cmd->target,
-			     cmd->lun, /*alloc*/FALSE);
+	dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target,
+				   cmd->lun, /*alloc*/FALSE);
 
 	if (dev == NULL) {
 		/*
@@ -2267,7 +2383,7 @@
 		if (flag == SCB_ABORT) {
 			TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
 			cmd->result = DID_ABORT << 16;
-			ahc_queue_cmd_complete(ahc, cmd);
+			ahc_linux_queue_cmd_complete(ahc, cmd);
 			retval = SUCCESS;
 			goto done;
 		}
@@ -2315,7 +2431,7 @@
 	ahc->flags |= AHC_ALL_INTERRUPTS;
 	do {
 		ahc_intr(ahc);
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		ahc_clear_critical_section(ahc);
 	} while (ahc_inb(ahc, INTSTAT) & INT_PEND);
 	ahc->flags &= ~AHC_ALL_INTERRUPTS;
@@ -2455,7 +2571,7 @@
 	retval = SUCCESS;
 done:
 	if (paused)
-		unpause_sequencer(ahc);
+		ahc_unpause(ahc);
 	if (wait) {
     		struct timer_list timer;
 		int ret;
@@ -2464,7 +2580,7 @@
 		init_timer(&timer);
 		timer.data = (u_long)&ahc->platform_data->eh_sem;
 		timer.expires = jiffies + (5 * HZ);
-		timer.function = ahc_sem_timeout;
+		timer.function = ahc_linux_sem_timeout;
 		add_timer(&timer);
 		printf("Recovery code sleeping\n");
 		down(&ahc->platform_data->eh_sem);
@@ -2476,12 +2592,12 @@
 		}
 		ahc_lock(ahc, &s);
 	}
-	ahc_run_device_queues(ahc);
+	ahc_linux_run_device_queues(ahc);
 	acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
 	TAILQ_INIT(&ahc->platform_data->completeq);
 	ahc_unlock(ahc, &s);
 	if (acmd != NULL)
-		ahc_run_complete_queue(ahc, acmd);
+		ahc_linux_run_complete_queue(ahc, acmd);
 	spin_lock_irq(&io_request_lock);
 	return (retval);
 }
@@ -2490,11 +2606,11 @@
  * Abort the current SCSI command(s).
  */
 int
-aic7xxx_abort(Scsi_Cmnd *cmd)
+ahc_linux_abort(Scsi_Cmnd *cmd)
 {
 	int error;
 
-	error = aic7xxx_queue_recovery_cmd(cmd, SCB_ABORT);
+	error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);
 	if (error != 0)
 		printf("aic7xxx_abort returns %d\n", error);
 	return (error);
@@ -2504,11 +2620,11 @@
  * Attempt to send a target reset message to the device that timed out.
  */
 int
-aic7xxx_dev_reset(Scsi_Cmnd *cmd)
+ahc_linux_dev_reset(Scsi_Cmnd *cmd)
 {
 	int error;
 
-	error = aic7xxx_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
+	error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
 	if (error != 0)
 		printf("aic7xxx_dev_reset returns %d\n", error);
 	return (error);
@@ -2518,7 +2634,7 @@
  * Reset the SCSI bus.
  */
 int
-aic7xxx_bus_reset(Scsi_Cmnd *cmd)
+ahc_linux_bus_reset(Scsi_Cmnd *cmd)
 {
 	struct ahc_softc *ahc;
 	struct ahc_cmd *acmd;
@@ -2543,7 +2659,7 @@
 		       "%d SCBs aborted.\n", ahc_name(ahc), found);
 
 	if (acmd != NULL)
-		ahc_run_complete_queue(ahc, acmd);
+		ahc_linux_run_complete_queue(ahc, acmd);
 
 	spin_lock_irq(&io_request_lock);
 	return SUCCESS;
@@ -2553,7 +2669,7 @@
  * Return the disk geometry for the given SCSI device.
  */
 int
-aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[])
+ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
 {
 	int	heads;
 	int	sectors;
@@ -2597,14 +2713,23 @@
  * module.
  */
 int
-aic7xxx_release(struct Scsi_Host * host)
+ahc_linux_release(struct Scsi_Host * host)
 {
 	struct ahc_softc *ahc;
 
 	if (host != NULL) {
+
 		ahc = *(struct ahc_softc **)host->hostdata;
 		ahc_free(ahc);
 	}
+	if (TAILQ_EMPTY(&ahc_tailq)) {
+		unregister_reboot_notifier(&ahc_linux_notifier);
+#ifdef CONFIG_PCI
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+		pci_unregister_driver(&aic7xxx_pci_driver);
+#endif
+#endif
+	}
 	return (0);
 }
 
@@ -2626,8 +2751,8 @@
 			for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
 				struct ahc_cmd *acmd;
 
-				dev = ahc_get_device(ahc, channel, target,
-						     lun, /*alloc*/FALSE);
+				dev = ahc_linux_get_device(ahc, channel, target,
+							   lun, /*alloc*/FALSE);
 				if (dev == NULL)
 					continue;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Fri May  4 15:16:28 2001
@@ -28,24 +28,24 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h#2 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h#3 $
  */
 
 #ifndef _AIC7XXX_LINUX_HOST_H_
 #define _AIC7XXX_LINUX_HOST_H_
 
-int		 aic7xxx_proc_info(char *, char **, off_t, int, int, int);
-int		 aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-int		 aic7xxx_detect(Scsi_Host_Template *);
-int		 aic7xxx_release(struct Scsi_Host *);
-const char	*aic7xxx_info(struct Scsi_Host *);
-int		 aic7xxx_biosparam(Disk *, kdev_t, int[]);
-int		 aic7xxx_bus_reset(Scsi_Cmnd *);
-int		 aic7xxx_dev_reset(Scsi_Cmnd *);
-int		 aic7xxx_abort(Scsi_Cmnd *);
+int		 ahc_linux_proc_info(char *, char **, off_t, int, int, int);
+int		 ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
+int		 ahc_linux_detect(Scsi_Host_Template *);
+int		 ahc_linux_release(struct Scsi_Host *);
+const char	*ahc_linux_info(struct Scsi_Host *);
+int		 ahc_linux_biosparam(Disk *, kdev_t, int[]);
+int		 ahc_linux_bus_reset(Scsi_Cmnd *);
+int		 ahc_linux_dev_reset(Scsi_Cmnd *);
+int		 ahc_linux_abort(Scsi_Cmnd *);
 
 #if defined(__i386__)
-#  define AIC7XXX_BIOSPARAM aic7xxx_biosparam
+#  define AIC7XXX_BIOSPARAM ahc_linux_biosparam
 #else
 #  define AIC7XXX_BIOSPARAM NULL
 #endif
@@ -58,23 +58,23 @@
 	next: NULL,						\
 	module: NULL,						\
 	proc_dir: NULL,						\
-	proc_info: aic7xxx_proc_info,				\
+	proc_info: ahc_linux_proc_info,				\
 	name: NULL,						\
-	detect: aic7xxx_detect,					\
-	release: aic7xxx_release,				\
-	info: aic7xxx_info,					\
+	detect: ahc_linux_detect,				\
+	release: ahc_linux_release,				\
+	info: ahc_linux_info,					\
 	command: NULL,						\
-	queuecommand: aic7xxx_queue,				\
+	queuecommand: ahc_linux_queue,				\
 	eh_strategy_handler: NULL,				\
-	eh_abort_handler: aic7xxx_abort,			\
-	eh_device_reset_handler: aic7xxx_dev_reset,		\
-	eh_bus_reset_handler: aic7xxx_bus_reset,		\
+	eh_abort_handler: ahc_linux_abort,			\
+	eh_device_reset_handler: ahc_linux_dev_reset,		\
+	eh_bus_reset_handler: ahc_linux_bus_reset,		\
 	eh_host_reset_handler: NULL,				\
 	abort: NULL,						\
 	reset: NULL,						\
 	slave_attach: NULL,					\
 	bios_param: AIC7XXX_BIOSPARAM,				\
-	can_queue: 254,		/* max simultaneous cmds      */\
+	can_queue: 253,		/* max simultaneous cmds      */\
 	this_id: -1,		/* scsi id of host adapter    */\
 	sg_tablesize: 0,	/* max scatter-gather cmds    */\
 	cmd_per_lun: 2,		/* cmds per lun		      */\
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c	Tue Mar  6 22:44:16 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c#15 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux_pci.c#17 $
  */
 
 #include "aic7xxx_osm.h"
@@ -57,7 +57,7 @@
 	{ 0 }
 };
 
-static struct pci_driver aic7xxx_pci_driver = {
+struct pci_driver aic7xxx_pci_driver = {
 	name:		"aic7xxx",
 	probe:		ahc_linux_pci_dev_probe,
 	remove:		ahc_linux_pci_dev_remove,
@@ -133,7 +133,7 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	pdev->driver_data = ahc;
 	if (aic7xxx_detect_complete)
-		aic7xxx_register_host(ahc, aic7xxx_driver_template);
+		ahc_linux_register_host(ahc, aic7xxx_driver_template);
 #endif
 	return (0);
 }
@@ -191,11 +191,9 @@
 {
 	uint32_t command;
 	u_long	 base;
-#ifdef MMAPIO
 	u_long	 start;
 	u_long	 base_page;
 	u_long	 base_offset;
-#endif
 	uint8_t *maddr;
 
 	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, 4);
@@ -306,11 +304,47 @@
 	int error;
 
 	ahc->platform_data->irq = ahc->dev_softc->irq;
-	error = request_irq(ahc->platform_data->irq, aic7xxx_isr,
-			    SA_INTERRUPT|SA_SHIRQ, "aic7xxx", ahc);
-	if (error < 0)
-		error = request_irq(ahc->platform_data->irq, aic7xxx_isr,
-				    SA_SHIRQ, "aic7xxx", ahc);
+	error = request_irq(ahc->platform_data->irq, ahc_linux_isr,
+			    SA_SHIRQ, "aic7xxx", ahc);
 	
 	return (-error);
+}
+
+void
+ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	pci_set_power_state(ahc->dev_softc, new_state);
+#else
+	uint32_t cap;
+	u_int cap_offset;
+
+	/*
+	 * Traverse the capability list looking for
+	 * the power management capability.
+	 */
+	cap = 0;
+	cap_offset = ahc_pci_read_config(ahc->dev_softc,
+					 PCIR_CAP_PTR, /*bytes*/1);
+	while (cap_offset != 0) {
+
+		cap = ahc_pci_read_config(ahc->dev_softc,
+					  cap_offset, /*bytes*/4);
+		if ((cap & 0xFF) == 1
+		 && ((cap >> 16) & 0x3) > 0) {
+			uint32_t pm_control;
+
+			pm_control = ahc_pci_read_config(ahc->dev_softc,
+							 cap_offset + 4,
+							 /*bytes*/4);
+			pm_control &= ~0x3;
+			pm_control |= new_state;
+			ahc_pci_write_config(ahc->dev_softc,
+					     cap_offset + 4,
+					     pm_control, /*bytes*/2);
+			break;
+		}
+		cap_offset = (cap >> 8) & 0xFF;
+	}
+#endif 
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h linux/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h	Thu Apr 12 12:16:35 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_osm.h	Fri May  4 15:16:28 2001
@@ -18,7 +18,7 @@
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  * 
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux.h#45 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux.h#59 $
  *
  * Copyright (c) 2000, 2001 Adaptec Inc.
  * All rights reserved.
@@ -47,7 +47,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux.h#45 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_linux.h#59 $
  *
  */
 #ifndef _AIC7XXX_LINUX_H_
@@ -62,6 +62,10 @@
 #include <linux/pci.h>
 #include <linux/version.h>
 
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #include <linux/config.h>
 #endif
@@ -79,14 +83,6 @@
 #include "queue.h"
 #include "scsi_message.h"
 
-/*
- * We never have to reference the current task, and the driver core
- * makes ample use of this "name".
- */
-#ifdef current
-#undef current
-#endif
-
 /************************* Forward Declarations *******************************/
 struct ahc_softc;
 typedef struct pci_dev *ahc_dev_softc_t;
@@ -114,7 +110,7 @@
 
 /***************************** Bus Space/DMA **********************************/
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,16)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,17)
 typedef dma_addr_t bus_addr_t;
 #else
 typedef uint32_t bus_addr_t;
@@ -353,11 +349,7 @@
 #include <linux/smp.h>
 #endif
 
-#define AIC7XXX_DRIVER_VERSION  "6.1.5"
-
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
-#endif
+#define AIC7XXX_DRIVER_VERSION  "6.1.13"
 
 /**************************** Front End Queues ********************************/
 /*
@@ -401,7 +393,9 @@
 	AHC_DEV_UNCONFIGURED	 = 0x01,
 	AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
 	AHC_DEV_TIMER_ACTIVE	 = 0x04, /* Our timer is active */
-	AHC_DEV_ON_RUN_LIST	 = 0x08	 /* Queued to be run later */
+	AHC_DEV_ON_RUN_LIST	 = 0x08, /* Queued to be run later */
+	AHC_DEV_Q_BASIC		 = 0x10, /* Allow basic device queuing */
+	AHC_DEV_Q_TAGGED	 = 0x20  /* Allow full SCSI2 command queueing */
 } ahc_dev_flags;
 
 struct ahc_linux_target;
@@ -434,7 +428,7 @@
 	/*
 	 * Cumulative command counter.
 	 */
-	u_int		num_commands;
+	u_long		commands_issued;
 
 	/*
 	 * The number of tagged transactions when
@@ -465,8 +459,16 @@
 	 * on devices with a fixed number of tags.
 	 */
 	u_int		last_queuefull_same_count;
-
 #define AHC_LOCK_TAGS_COUNT 50
+
+	/*
+	 * How many transactions have been queued
+	 * without the device going idle.  We use
+	 * this statistic to 
+	 */
+	u_int		commands_since_idle_or_otag;
+#define AHC_OTAG_THRESH	250
+
 	int		lun;
 	struct		ahc_linux_target *target;
 };
@@ -570,9 +572,6 @@
 #endif
 #define mb() \
 	__asm__ __volatile__("mb": : :"memory")
-#elif defined(__sparc__)
-#define MMAPIO
-/* The default mb() define does what this driver wants. -DaveM */
 #endif
 
 static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port);
@@ -644,8 +643,8 @@
 }
 
 /**************************** Initialization **********************************/
-int	aic7xxx_register_host(struct ahc_softc *ahc,
-			      Scsi_Host_Template *template);
+int	ahc_linux_register_host(struct ahc_softc *,
+				Scsi_Host_Template *);
 
 /*************************** Pretty Printing **********************************/
 struct info_str {
@@ -784,11 +783,24 @@
 #define PCIR_SUBVEND_0	0x2c
 #define PCIR_SUBDEV_0	0x2e
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+extern struct pci_driver aic7xxx_pci_driver;
+#endif
+
+typedef enum
+{
+	AHC_POWER_STATE_D0,
+	AHC_POWER_STATE_D1,
+	AHC_POWER_STATE_D2,
+	AHC_POWER_STATE_D3
+} ahc_power_state;
+
+void ahc_power_state_change(struct ahc_softc *ahc,
+			    ahc_power_state new_state);
 /**************************** VL/EISA Routines ********************************/
 int			 aic7770_linux_probe(Scsi_Host_Template *);
 int			 aic7770_map_registers(struct ahc_softc *ahc);
-int			 aic7770_map_int(struct ahc_softc *ahc,
-					 u_int irq, int shared);
+int			 aic7770_map_int(struct ahc_softc *ahc, u_int irq);
 
 /******************************* PCI Routines *********************************/
 /*
@@ -1047,16 +1059,16 @@
 }
 
 void	ahc_platform_set_tags(struct ahc_softc *ahc,
-			      struct ahc_devinfo *devinfo, int enable);
+			      struct ahc_devinfo *devinfo, ahc_queue_alg);
 int	ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
 				char channel, int lun, u_int tag,
 				role_t role, uint32_t status);
-void	aic7xxx_isr(int irq, void *dev_id, struct pt_regs * regs);
+void	ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
 void	ahc_platform_flushwork(struct ahc_softc *ahc);
 int	ahc_softc_comp(struct ahc_softc *, struct ahc_softc *);
 void	ahc_done(struct ahc_softc*, struct scb*);
 void	ahc_send_async(struct ahc_softc *, char channel,
-		       u_int target, u_int lun, ac_code);
+		       u_int target, u_int lun, ac_code, void *);
 void	ahc_print_path(struct ahc_softc *, struct scb *);
 void	ahc_platform_dump_card_state(struct ahc_softc *ahc);
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_pci.c linux/drivers/scsi/aic7xxx/aic7xxx_pci.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_pci.c	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_pci.c	Fri May  4 15:16:28 2001
@@ -30,7 +30,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#17 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#24 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.6 2000/11/10 20:13:41 gibbs Exp $
  */
@@ -263,7 +263,7 @@
 	{
 		ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
 		ID_DEV_VENDOR_MASK,
-		"Adaptec 2930C SCSI adapter (VAR)",
+		"Adaptec 2930C Ultra SCSI adapter (VAR)",
 		ahc_aic7860_setup
 	},
 	/* aic7870 based controllers */
@@ -452,7 +452,7 @@
 	{
 		ID_AIC7892_ARO,
 		ID_ALL_MASK,
-		"Adaptec aic7892 Ultra2 SCSI adapter (ARO)",
+		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
 		ahc_aic7892_setup
 	},
 	/* aic7895 based controllers */	
@@ -546,13 +546,13 @@
 	{
 		ID_AIC7859 & ID_DEV_VENDOR_MASK,
 		ID_DEV_VENDOR_MASK,
-		"Adaptec aic7859 Ultra SCSI adapter",
+		"Adaptec aic7859 SCSI adapter",
 		ahc_aic7860_setup
 	},
 	{
 		ID_AIC7860 & ID_DEV_VENDOR_MASK,
 		ID_DEV_VENDOR_MASK,
-		"Adaptec aic7860 SCSI adapter",
+		"Adaptec aic7860 Ultra SCSI adapter",
 		ahc_aic7860_setup
 	},
 	{
@@ -644,16 +644,6 @@
 #define		CACHESIZE	0x0000003ful	/* only 5 bits */
 #define		LATTIME		0x0000ff00ul
 
-typedef enum
-{
-	AHC_POWER_STATE_D0,
-	AHC_POWER_STATE_D1,
-	AHC_POWER_STATE_D2,
-	AHC_POWER_STATE_D3
-} ahc_power_state;
-
-static void ahc_power_state_change(struct ahc_softc *ahc,
-				   ahc_power_state new_state);
 static int ahc_ext_scbram_present(struct ahc_softc *ahc);
 static void ahc_scbram_config(struct ahc_softc *ahc, int enable,
 				  int pcheck, int fast, int large);
@@ -761,9 +751,11 @@
 	if (error != 0)
 		return (error);
 
+	ahc->bus_intr = ahc_pci_intr;
+
 	/* Remeber how the card was setup in case there is no SEEPROM */
 	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
-		pause_sequencer(ahc);
+		ahc_pause(ahc);
 		if ((ahc->features & AHC_ULTRA2) != 0)
 			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
 		else
@@ -786,7 +778,8 @@
 		/* Perform ALT-Mode Setup */
 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
-		ahc_outb(ahc, OPTIONMODE, OPTIONMODE_DEFAULTS);
+		ahc_outb(ahc, OPTIONMODE,
+			 OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);
 		ahc_outb(ahc, SFUNCT, sfunct);
 
 		/* Normal mode setup */
@@ -794,9 +787,6 @@
 					  |TARGCRCENDEN);
 	}
 
-	error = ahc_pci_map_int(ahc);
-	if (error != 0)
-		return (error);
 	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
 	dscommand0 |= MPARCKEN|CACHETHEN;
 	if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -825,6 +815,19 @@
 				/*bytes*/1) & CACHESIZE;
 	ahc->pci_cachesize *= 4;
 
+	/*
+	 * We cannot perform ULTRA speeds without the presense
+	 * of the external precision resistor.
+	 */
+	if ((ahc->features & AHC_ULTRA) != 0) {
+		uint32_t devconfig;
+
+		devconfig = ahc_pci_read_config(ahc->dev_softc,
+						DEVCONFIG, /*bytes*/4);
+		if ((devconfig & REXTVALID) == 0)
+			ahc->features &= ~AHC_ULTRA;
+	}
+
 	/* See if we have a SEEPROM and perform auto-term */
 	check_extport(ahc, &sxfrctl1);
 
@@ -879,20 +882,6 @@
 	if ((sxfrctl1 & STPWEN) != 0)
 		ahc->flags |= AHC_TERM_ENB_A;
 
-	/*
-	 * We cannot perform ULTRA speeds without
-	 * the presense of the external precision
-	 * resistor.
-	 */
-	if ((ahc->features & AHC_ULTRA) != 0) {
-		uint32_t devconfig;
-
-		devconfig = ahc_pci_read_config(ahc->dev_softc,
-						DEVCONFIG, /*bytes*/4);
-		if ((devconfig & REXTVALID) == 0)
-			ahc->flags |= AHC_ULTRA_DISABLED;
-	}
-
 	/* Core initialization */
 	error = ahc_init(ahc);
 	if (error != 0)
@@ -903,42 +892,16 @@
 	 */
 	ahc_softc_insert(ahc);
 
-	return (0);
-}
-
-static void
-ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
-{
-	uint32_t cap;
-	u_int cap_offset;
-
 	/*
-	 * Traverse the capability list looking for
-	 * the power management capability.
+	 * Allow interrupts now that we are completely setup.
 	 */
-	cap = 0;
-	cap_offset = ahc_pci_read_config(ahc->dev_softc,
-					 PCIR_CAP_PTR, /*bytes*/1);
-	while (cap_offset != 0) {
-
-		cap = ahc_pci_read_config(ahc->dev_softc,
-					  cap_offset, /*bytes*/4);
-		if ((cap & 0xFF) == 1
-		 && ((cap >> 16) & 0x3) > 0) {
-			uint32_t pm_control;
-
-			pm_control = ahc_pci_read_config(ahc->dev_softc,
-							 cap_offset + 4,
-							 /*bytes*/4);
-			pm_control &= ~0x3;
-			pm_control |= new_state;
-			ahc_pci_write_config(ahc->dev_softc,
-					     cap_offset + 4,
-					     pm_control, /*bytes*/2);
-			break;
-		}
-		cap_offset = (cap >> 8) & 0xFF;
-	}
+	error = ahc_pci_map_int(ahc);
+	if (error != 0)
+		return (error);
+
+	ahc_intr_enable(ahc, TRUE);
+
+	return (0);
 }
 
 /*
@@ -1190,32 +1153,37 @@
 			}
 			sd.sd_chip = C56_66;
 		}
+		release_seeprom(&sd);
 	}
 
-#if 0
 	if (!have_seeprom) {
 		/*
 		 * Pull scratch ram settings and treat them as
 		 * if they are the contents of an seeprom if
 		 * the 'ADPT' signature is found in SCB2.
+		 * We manually compose the data as 16bit values
+		 * to avoid endian issues.
 		 */
 		ahc_outb(ahc, SCBPTR, 2);
 		if (ahc_inb(ahc, SCB_BASE) == 'A'
 		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
 		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
 		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
-			uint8_t *sc_bytes;
+			uint16_t *sc_data;
 			int	  i;
 
-			sc_bytes = (uint8_t *)&sc;
-			for (i = 0; i < 64; i++)
-				sc_bytes[i] = ahc_inb(ahc, TARG_SCSIRATE + i);
-			/* Byte 0x1c is stored in byte 4 of SCB2 */
-			sc_bytes[0x1c] = ahc_inb(ahc, SCB_BASE + 4);
+			sc_data = (uint16_t *)&sc;
+			for (i = 0; i < 32; i++) {
+				uint16_t val;
+				int	 j;
+
+				j = i * 2;
+				val = ahc_inb(ahc, SRAM_BASE + j)
+				    | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
+			}
 			have_seeprom = verify_cksum(&sc);
 		}
 	}
-#endif
 
 	if (!have_seeprom) {
 		if (bootverbose)
@@ -1301,9 +1269,8 @@
 		if (sc.adapter_control & CFRESETB)
 			scsi_conf |= RESET_SCSI;
 
-		if ((sc.adapter_control & CFCHNLBPRIMARY) != 0
-		 && (ahc->features & AHC_MULTI_FUNC) != 0)
-			ahc->flags |= AHC_CHANNEL_B_PRIMARY;
+		ahc->flags |=
+		    (sc.adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
 
 		if (sc.bios_control & CFEXTEND)
 			ahc->flags |= AHC_EXTENDED_TRANS_A;
@@ -1318,7 +1285,8 @@
 				ultraenb = 0;
 		}
 
-		if (sc.signature == CFSIGNATURE) {
+		if (sc.signature == CFSIGNATURE
+		 || sc.signature == CFSIGNATURE2) {
 			uint32_t devconfig;
 
 			/* Honor the STPWLEVEL settings */
@@ -1362,10 +1330,11 @@
 			have_autoterm = FALSE;
 	}
 
-	if (have_autoterm)
+	if (have_autoterm) {
+		acquire_seeprom(ahc, &sd);
 		configure_termination(ahc, &sd, adapter_control, sxfrctl1);
-
-	release_seeprom(&sd);
+		release_seeprom(&sd);
+	}
 }
 
 static void
@@ -1806,7 +1775,7 @@
 		ahc_outb(ahc, CLRINT, CLRPARERR);
 	}
 
-	unpause_sequencer(ahc);
+	ahc_unpause(ahc);
 }
 
 static int
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c linux/drivers/scsi/aic7xxx/aic7xxx_proc.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_proc.c	Fri May  4 15:16:28 2001
@@ -29,7 +29,7 @@
  * String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
  * sym driver.
  *
- * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#7 $
+ * $Id: //depot/src/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#11 $
  */
 #include "aic7xxx_osm.h"
 #include "aic7xxx_inline.h"
@@ -174,7 +174,7 @@
 {
 	struct	ahc_linux_target *targ;
 	struct	ahc_initiator_tinfo *tinfo;
-	struct	tmode_tstate *tstate;
+	struct	ahc_tmode_tstate *tstate;
 	int	lun;
 
 	tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
@@ -190,7 +190,7 @@
 	copy_info(info, "\tGoal: ");
 	ahc_format_transinfo(info, &tinfo->goal);
 	copy_info(info, "\tCurr: ");
-	ahc_format_transinfo(info, &tinfo->current);
+	ahc_format_transinfo(info, &tinfo->curr);
 
 	for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
 		struct ahc_linux_device *dev;
@@ -210,7 +210,7 @@
 	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
 		  dev->target->channel + 'A', dev->target->target, dev->lun);
 
-	copy_info(info, "\t\tCommands Queued %d\n", dev->num_commands);
+	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
 	copy_info(info, "\t\tCommands Active %d\n", dev->active);
 	copy_info(info, "\t\tCommand Openings %d\n", dev->openings);
 	copy_info(info, "\t\tMax Tagged Openings %d\n", dev->maxtags);
@@ -221,7 +221,7 @@
  * Return information to handle /proc support for the driver.
  */
 int
-aic7xxx_proc_info(char *buffer, char **start, off_t offset,
+ahc_linux_proc_info(char *buffer, char **start, off_t offset,
 		  int length, int hostno, int inout)
 {
 	struct	ahc_softc *ahc;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_reg.h linux/drivers/scsi/aic7xxx/aic7xxx_reg.h
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_reg.h	Tue Mar  6 19:18:16 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_reg.h	Fri May  4 15:16:28 2001
@@ -86,8 +86,8 @@
 #define		SELDO           	0x40
 #define		SELDI           	0x20
 #define		SELINGO         	0x10
-#define		IOERR           	0x08
 #define		SWRAP           	0x08
+#define		IOERR           	0x08
 #define		SDONE           	0x04
 #define		SPIORDY         	0x02
 #define		DMADONE         	0x01
@@ -191,8 +191,8 @@
 #define		BRDDAT5         	0x20
 #define		BRDDAT4         	0x10
 #define		BRDSTB          	0x10
-#define		BRDCS           	0x08
 #define		BRDDAT3         	0x08
+#define		BRDCS           	0x08
 #define		BRDDAT2         	0x04
 #define		BRDRW           	0x04
 #define		BRDRW_ULTRA2    	0x02
@@ -242,8 +242,8 @@
 #define		PRELOADEN       	0x80
 #define		WIDEODD         	0x40
 #define		SCSIEN          	0x20
-#define		SDMAENACK       	0x10
 #define		SDMAEN          	0x10
+#define		SDMAENACK       	0x10
 #define		HDMAEN          	0x08
 #define		HDMAENACK       	0x08
 #define		DIRECTION       	0x04
@@ -271,8 +271,8 @@
 #define		P_MESGOUT       	0xa0
 #define		P_COMMAND       	0x80
 #define		CDI             	0x80
-#define		IOI             	0x40
 #define		P_DATAIN        	0x40
+#define		IOI             	0x40
 #define		MSGI            	0x20
 #define		P_BUSFREE       	0x01
 #define		P_DATAOUT       	0x00
@@ -314,9 +314,7 @@
 
 #define	LAST_MSG        		0x53
 
-#define	TARGET_MSG_REQUEST		0x54
-
-#define	SCSISEQ_TEMPLATE		0x56
+#define	SCSISEQ_TEMPLATE		0x54
 #define		ENSELO          	0x40
 #define		ENSELI          	0x20
 #define		ENRSELI         	0x10
@@ -324,11 +322,11 @@
 #define		ENAUTOATNI      	0x04
 #define		ENAUTOATNP      	0x02
 
-#define	DATA_COUNT_ODD  		0x57
+#define	DATA_COUNT_ODD  		0x55
 
-#define	INITIATOR_TAG   		0x58
+#define	INITIATOR_TAG   		0x56
 
-#define	SEQ_FLAGS2      		0x59
+#define	SEQ_FLAGS2      		0x57
 #define		SCB_DMA         	0x01
 
 #define	SCSICONF        		0x5a
@@ -345,8 +343,8 @@
 #define	HOSTCONF        		0x5d
 
 #define	HA_274_BIOSCTRL 		0x5f
-#define		BIOSMODE        	0x30
 #define		BIOSDISABLED    	0x30
+#define		BIOSMODE        	0x30
 #define		CHANNEL_B_PRIMARY	0x08
 
 #define	SEQCTL          		0x60
@@ -483,7 +481,8 @@
 
 #define	DFSTATUS        		0x94
 #define		PRELOAD_AVAIL   	0x80
-#define		DWORDEMP        	0x20
+#define		DFCACHETH       	0x40
+#define		FIFOQWDEMP      	0x20
 #define		MREQPEND        	0x10
 #define		HDONE           	0x08
 #define		DFTHRESH        	0x04
@@ -521,18 +520,19 @@
 #define		COMMAND_PHASE   	0x10
 #define		MSG_IN_PHASE    	0x08
 #define		MSG_OUT_PHASE   	0x04
+#define		DATA_PHASE_MASK 	0x03
 #define		DATA_IN_PHASE   	0x02
 #define		DATA_OUT_PHASE  	0x01
 
 #define	SFUNCT          		0x9f
 #define		ALT_MODE        	0x80
 
+#define	SCB_BASE        		0xa0
+
 #define	SCB_CDB_PTR     		0xa0
+#define	SCB_RESIDUAL_DATACNT		0xa0
 #define	SCB_CDB_STORE   		0xa0
 #define	SCB_TARGET_INFO 		0xa0
-#define	SCB_RESIDUAL_DATACNT		0xa0
-
-#define	SCB_BASE        		0xa0
 
 #define	SCB_RESIDUAL_SGPTR		0xa4
 
@@ -579,13 +579,13 @@
 
 #define	SCB_NEXT        		0xbf
 
+#define	SCB_64_SPARE    		0xc0
+
 #define	SEECTL_2840     		0xc0
 #define		CS_2840         	0x04
 #define		CK_2840         	0x02
 #define		DO_2840         	0x01
 
-#define	SCB_64_SPARE    		0xc0
-
 #define	STATUS_2840     		0xc1
 #define		EEPROM_TF       	0x80
 #define		BIOS_SEL        	0x60
@@ -648,8 +648,8 @@
 #define		WR_DFTHRSH_63   	0x30
 #define		WR_DFTHRSH_50   	0x20
 #define		WR_DFTHRSH_25   	0x10
-#define		RD_DFTHRSH_MAX  	0x07
 #define		RD_DFTHRSH      	0x07
+#define		RD_DFTHRSH_MAX  	0x07
 #define		RD_DFTHRSH_90   	0x06
 #define		RD_DFTHRSH_85   	0x05
 #define		RD_DFTHRSH_75   	0x04
@@ -668,39 +668,39 @@
 #define	SG_CACHE_PRE    		0xfc
 
 
-#define	CMD_GROUP_CODE_SHIFT	0x05
+#define	SCB_INITIATOR_TAG	0x03
+#define	SCB_TARGET_DATA_DIR	0x01
+#define	SCB_TARGET_PHASES	0x00
+#define	MAX_OFFSET_ULTRA2	0x7f
+#define	MAX_OFFSET_16BIT	0x08
 #define	BUS_8_BIT	0x00
-#define	CCSGRAM_MAXSEGS	0x10
-#define	TARGET_DATA_IN	0x01
+#define	TARGET_CMD_CMPLT	0xfe
 #define	STATUS_QUEUE_FULL	0x28
 #define	STATUS_BUSY	0x08
 #define	MAX_OFFSET_8BIT	0x0f
-#define	BUS_16_BIT	0x01
+#define	BUS_32_BIT	0x02
+#define	CCSGADDR_MAX	0x80
 #define	TID_SHIFT	0x04
 #define	SCB_DOWNLOAD_SIZE_64	0x30
-#define	SCB_UPLOAD_SIZE	0x20
 #define	HOST_MAILBOX_SHIFT	0x04
-#define	SCB_INITIATOR_TAG	0x03
 #define	SCB_TARGET_STATUS	0x02
-#define	SCB_TARGET_DATA_DIR	0x01
-#define	SCB_TARGET_PHASES	0x00
-#define	MAX_OFFSET_ULTRA2	0x7f
-#define	MAX_OFFSET_16BIT	0x08
-#define	TARGET_CMD_CMPLT	0xfe
+#define	CMD_GROUP_CODE_SHIFT	0x05
+#define	CCSGRAM_MAXSEGS	0x10
 #define	SCB_LIST_NULL	0xff
 #define	SG_SIZEOF	0x08
 #define	SCB_DOWNLOAD_SIZE	0x20
 #define	SEQ_MAILBOX_SHIFT	0x00
+#define	TARGET_DATA_IN	0x01
 #define	HOST_MSG	0xff
-#define	BUS_32_BIT	0x02
-#define	CCSGADDR_MAX	0x80
+#define	BUS_16_BIT	0x01
+#define	SCB_UPLOAD_SIZE	0x20
 
 
 /* Downloaded Constant Definitions */
+#define	INVERTED_CACHESIZE_MASK	0x03
 #define	SG_PREFETCH_ADDR_MASK	0x06
 #define	SG_PREFETCH_ALIGN_MASK	0x05
 #define	QOUTFIFO_OFFSET	0x00
 #define	SG_PREFETCH_CNT	0x04
-#define	INVERTED_CACHESIZE_MASK	0x03
 #define	CACHESIZE_MASK	0x02
 #define	QINFIFO_OFFSET	0x01
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_seq.h linux/drivers/scsi/aic7xxx/aic7xxx_seq.h
--- v2.4.4/linux/drivers/scsi/aic7xxx/aic7xxx_seq.h	Tue Mar  6 19:18:16 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_seq.h	Fri May  4 15:16:28 2001
@@ -4,7 +4,7 @@
 static uint8_t seqprog[] = {
 	0xb2, 0x00, 0x00, 0x08,
 	0xf7, 0x11, 0x22, 0x08,
-	0x00, 0x65, 0xde, 0x59,
+	0x00, 0x65, 0xe4, 0x59,
 	0xf7, 0x01, 0x02, 0x08,
 	0xff, 0x6a, 0x24, 0x08,
 	0x40, 0x00, 0x40, 0x68,
@@ -17,21 +17,21 @@
 	0x01, 0x4d, 0xc8, 0x30,
 	0x00, 0x4c, 0x12, 0x70,
 	0x01, 0x39, 0xa2, 0x30,
-	0x00, 0x6a, 0x7e, 0x5e,
+	0x00, 0x6a, 0x92, 0x5e,
 	0x01, 0x51, 0x20, 0x31,
-	0x01, 0x59, 0xb2, 0x00,
+	0x01, 0x57, 0xae, 0x00,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x51, 0xda, 0x5d,
+	0x00, 0x51, 0xec, 0x5d,
 	0x01, 0x51, 0xc8, 0x30,
 	0x00, 0x39, 0xde, 0x60,
 	0x00, 0xbb, 0x30, 0x70,
-	0xc1, 0x6a, 0x96, 0x5e,
+	0xc1, 0x6a, 0xaa, 0x5e,
 	0x01, 0xbf, 0x72, 0x30,
 	0x01, 0x40, 0x7e, 0x31,
 	0x01, 0x90, 0x80, 0x30,
 	0x01, 0xf6, 0xd4, 0x30,
 	0x01, 0x4d, 0x9a, 0x18,
-	0xfe, 0x59, 0xb2, 0x08,
+	0xfe, 0x57, 0xae, 0x08,
 	0x01, 0x40, 0x20, 0x31,
 	0x00, 0x65, 0xe2, 0x58,
 	0x60, 0x0b, 0x40, 0x78,
@@ -48,10 +48,10 @@
 	0x08, 0x3c, 0x78, 0x00,
 	0x01, 0x50, 0xc8, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xc4, 0x5d,
+	0x48, 0x6a, 0xd6, 0x5d,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xc4, 0x5d,
+	0x48, 0x6a, 0xd6, 0x5d,
 	0x01, 0x6a, 0x26, 0x01,
 	0xf0, 0x19, 0x7a, 0x08,
 	0x0f, 0x18, 0xc8, 0x08,
@@ -62,7 +62,7 @@
 	0x80, 0x3d, 0x7a, 0x00,
 	0x01, 0x3d, 0xd8, 0x31,
 	0x01, 0x3d, 0x32, 0x31,
-	0x10, 0x03, 0x56, 0x79,
+	0x10, 0x03, 0x5c, 0x79,
 	0x00, 0x65, 0x0a, 0x59,
 	0x80, 0x66, 0xa8, 0x78,
 	0x01, 0x66, 0xd8, 0x31,
@@ -77,33 +77,33 @@
 	0x00, 0x65, 0xb0, 0x48,
 	0x01, 0x66, 0xd8, 0x31,
 	0x01, 0x66, 0x32, 0x31,
-	0x10, 0x03, 0x56, 0x79,
+	0x10, 0x03, 0x5c, 0x79,
 	0x00, 0x65, 0x0a, 0x59,
 	0x01, 0x66, 0xd8, 0x31,
 	0x01, 0x66, 0x32, 0x31,
-	0x01, 0x66, 0xb0, 0x30,
+	0x01, 0x66, 0xac, 0x30,
 	0x40, 0x3c, 0x78, 0x00,
 	0x10, 0x03, 0xa6, 0x78,
 	0x00, 0x65, 0x0a, 0x59,
 	0x00, 0x65, 0xb0, 0x40,
-	0x61, 0x6a, 0x96, 0x5e,
-	0x08, 0x51, 0x2e, 0x71,
+	0x61, 0x6a, 0xaa, 0x5e,
+	0x08, 0x51, 0x34, 0x71,
 	0x02, 0x0b, 0xac, 0x78,
 	0x00, 0x65, 0xa8, 0x40,
 	0x80, 0x86, 0xc8, 0x08,
 	0x01, 0x4f, 0xc8, 0x30,
 	0x00, 0x50, 0xc2, 0x60,
-	0xc4, 0x6a, 0x32, 0x5d,
+	0xc4, 0x6a, 0x44, 0x5d,
 	0x40, 0x3c, 0xbe, 0x78,
-	0x28, 0x6a, 0x48, 0x5d,
-	0x00, 0x65, 0x54, 0x41,
-	0x08, 0x6a, 0x48, 0x5d,
-	0x00, 0x65, 0x54, 0x41,
+	0x28, 0x6a, 0x5a, 0x5d,
+	0x00, 0x65, 0x5a, 0x41,
+	0x08, 0x6a, 0x5a, 0x5d,
+	0x00, 0x65, 0x5a, 0x41,
 	0xff, 0x6a, 0xd8, 0x01,
 	0xff, 0x6a, 0x32, 0x01,
 	0x90, 0x3c, 0x78, 0x00,
-	0x10, 0x03, 0x4a, 0x69,
-	0x00, 0x65, 0x2e, 0x41,
+	0x10, 0x03, 0x50, 0x69,
+	0x00, 0x65, 0x34, 0x41,
 	0x1a, 0x01, 0x02, 0x00,
 	0xf0, 0x19, 0x7a, 0x08,
 	0x0f, 0x0f, 0xc8, 0x08,
@@ -112,8 +112,8 @@
 	0x08, 0x1f, 0xda, 0x78,
 	0x80, 0x3d, 0x7a, 0x00,
 	0x20, 0x6a, 0x16, 0x00,
-	0x00, 0x65, 0xbe, 0x41,
-	0x00, 0x65, 0x76, 0x5e,
+	0x00, 0x65, 0xc4, 0x41,
+	0x00, 0x65, 0x8a, 0x5e,
 	0x00, 0x65, 0x12, 0x40,
 	0x20, 0x11, 0xe8, 0x68,
 	0x20, 0x6a, 0x18, 0x00,
@@ -125,11 +125,11 @@
 	0x01, 0xb9, 0x1e, 0x30,
 	0x7f, 0xb9, 0x0a, 0x08,
 	0x01, 0xb9, 0x0a, 0x30,
-	0x01, 0x56, 0xca, 0x30,
+	0x01, 0x54, 0xca, 0x30,
 	0x80, 0xb8, 0xfc, 0x78,
 	0x80, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0x00, 0x34,
-	0x01, 0x56, 0x00, 0x34,
+	0x01, 0x54, 0x00, 0x34,
 	0x1a, 0x01, 0x02, 0x00,
 	0x08, 0xb8, 0x06, 0x79,
 	0x20, 0x01, 0x02, 0x00,
@@ -146,40 +146,43 @@
 	0x01, 0xb9, 0x7a, 0x30,
 	0x01, 0xba, 0x7c, 0x30,
 	0x00, 0x65, 0x00, 0x59,
-	0x80, 0x0b, 0xba, 0x79,
-	0xe4, 0x6a, 0x32, 0x5d,
-	0x80, 0xba, 0x48, 0x5d,
+	0x80, 0x0b, 0xc0, 0x79,
+	0xe4, 0x6a, 0x44, 0x5d,
+	0x80, 0xba, 0x5a, 0x5d,
 	0x20, 0xb8, 0x2c, 0x79,
-	0x20, 0x6a, 0x48, 0x5d,
-	0x00, 0xa3, 0x48, 0x5d,
+	0x20, 0x6a, 0x5a, 0x5d,
+	0x00, 0xa3, 0x5a, 0x5d,
 	0x01, 0xa0, 0x78, 0x30,
-	0x10, 0x03, 0x46, 0x69,
-	0x08, 0x3c, 0x62, 0x69,
-	0x04, 0x3c, 0x88, 0x69,
-	0x02, 0x3c, 0x8e, 0x69,
-	0x01, 0x3c, 0x4c, 0x79,
-	0x00, 0x6a, 0x7e, 0x5e,
+	0x10, 0xb8, 0x34, 0x79,
+	0xe4, 0x6a, 0x44, 0x5d,
+	0x00, 0x65, 0xa8, 0x40,
+	0x10, 0x03, 0x4c, 0x69,
+	0x08, 0x3c, 0x68, 0x69,
+	0x04, 0x3c, 0x8e, 0x69,
+	0x02, 0x3c, 0x94, 0x69,
+	0x01, 0x3c, 0x52, 0x79,
 	0x01, 0x6a, 0xa2, 0x30,
-	0x00, 0x65, 0x9a, 0x59,
-	0x04, 0x51, 0x3e, 0x61,
+	0x00, 0x65, 0xa0, 0x59,
+	0x04, 0x51, 0x42, 0x61,
+	0x00, 0x6a, 0x92, 0x5e,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0xda, 0x5d,
+	0x00, 0xbb, 0xec, 0x5d,
 	0x00, 0x65, 0x2c, 0x41,
 	0xa4, 0x6a, 0x06, 0x00,
 	0x00, 0x65, 0x0a, 0x59,
 	0x00, 0x65, 0xa8, 0x40,
-	0xe4, 0x6a, 0x32, 0x5d,
-	0x20, 0x3c, 0x52, 0x79,
-	0x02, 0x6a, 0x48, 0x5d,
-	0x04, 0x6a, 0x48, 0x5d,
-	0x01, 0x03, 0x54, 0x69,
+	0xe4, 0x6a, 0x44, 0x5d,
+	0x20, 0x3c, 0x58, 0x79,
+	0x02, 0x6a, 0x5a, 0x5d,
+	0x04, 0x6a, 0x5a, 0x5d,
+	0x01, 0x03, 0x5a, 0x69,
 	0xf7, 0x11, 0x22, 0x08,
 	0xff, 0x6a, 0x24, 0x08,
 	0xff, 0x6a, 0x06, 0x08,
 	0x01, 0x6a, 0x7e, 0x00,
-	0x00, 0x65, 0x9a, 0x59,
+	0x00, 0x65, 0xa0, 0x59,
 	0x00, 0x65, 0x04, 0x40,
-	0x84, 0x6a, 0x32, 0x5d,
+	0x84, 0x6a, 0x44, 0x5d,
 	0x00, 0x65, 0x0a, 0x59,
 	0x01, 0x66, 0xc8, 0x30,
 	0x01, 0x64, 0xd8, 0x31,
@@ -187,60 +190,60 @@
 	0x5b, 0x64, 0xc8, 0x28,
 	0x30, 0x64, 0xca, 0x18,
 	0x01, 0x6c, 0xc8, 0x30,
-	0xff, 0x64, 0x84, 0x79,
+	0xff, 0x64, 0x8a, 0x79,
 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x76, 0x79,
-	0x01, 0x64, 0x7c, 0x61,
+	0x02, 0x0b, 0x7c, 0x79,
+	0x01, 0x64, 0x82, 0x61,
 	0xf7, 0x01, 0x02, 0x08,
 	0x01, 0x06, 0xd8, 0x31,
 	0x01, 0x06, 0x32, 0x31,
 	0xff, 0x64, 0xc8, 0x18,
-	0xff, 0x64, 0x76, 0x69,
+	0xff, 0x64, 0x7c, 0x69,
 	0xf7, 0x3c, 0x78, 0x08,
-	0x00, 0x65, 0x2e, 0x41,
+	0x00, 0x65, 0x34, 0x41,
 	0x40, 0xa1, 0x7e, 0x10,
-	0x04, 0xa1, 0x32, 0x5d,
-	0x00, 0x65, 0x62, 0x42,
-	0xc4, 0x6a, 0x32, 0x5d,
+	0x04, 0xa1, 0x44, 0x5d,
+	0x00, 0x65, 0x68, 0x42,
+	0xc4, 0x6a, 0x44, 0x5d,
 	0xc0, 0x6a, 0x7e, 0x00,
-	0x00, 0xa2, 0x48, 0x5d,
+	0x00, 0xa2, 0x5a, 0x5d,
 	0xe4, 0x6a, 0x06, 0x00,
-	0x00, 0x6a, 0x48, 0x5d,
-	0x00, 0x65, 0x54, 0x41,
-	0x10, 0x3c, 0x9e, 0x69,
-	0x00, 0xbb, 0x64, 0x44,
+	0x00, 0x6a, 0x5a, 0x5d,
+	0x00, 0x65, 0x5a, 0x41,
+	0x10, 0x3c, 0xa4, 0x69,
+	0x00, 0xbb, 0x6c, 0x44,
 	0x18, 0x6a, 0xda, 0x01,
 	0x01, 0x69, 0xd8, 0x31,
 	0x1c, 0x6a, 0xd0, 0x01,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0xa6, 0x79,
+	0x80, 0xee, 0xac, 0x79,
 	0xff, 0x6a, 0xdc, 0x09,
 	0x01, 0x93, 0x26, 0x01,
 	0x03, 0x6a, 0x2a, 0x01,
 	0x01, 0x69, 0x32, 0x31,
-	0x1c, 0x6a, 0xa8, 0x5d,
+	0x1c, 0x6a, 0xba, 0x5d,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x6c, 0x5e,
+	0x00, 0x65, 0x80, 0x5e,
 	0x01, 0x50, 0xa0, 0x18,
 	0x02, 0x6a, 0x22, 0x05,
 	0x80, 0x6a, 0x74, 0x00,
 	0x80, 0x3c, 0x78, 0x00,
-	0x00, 0x65, 0xa0, 0x5d,
+	0x00, 0x65, 0xb2, 0x5d,
 	0x01, 0x3f, 0xc8, 0x30,
-	0xbf, 0x64, 0x62, 0x7a,
-	0x80, 0x64, 0x82, 0x73,
-	0xa0, 0x64, 0xd8, 0x73,
-	0xc0, 0x64, 0xd0, 0x73,
-	0xe0, 0x64, 0x18, 0x74,
-	0x01, 0x6a, 0x96, 0x5e,
-	0x00, 0x65, 0xbe, 0x41,
+	0xbf, 0x64, 0x68, 0x7a,
+	0x80, 0x64, 0x96, 0x73,
+	0xa0, 0x64, 0xf0, 0x73,
+	0xc0, 0x64, 0xe6, 0x73,
+	0xe0, 0x64, 0x20, 0x74,
+	0x01, 0x6a, 0xaa, 0x5e,
+	0x00, 0x65, 0xc4, 0x41,
 	0xf7, 0x11, 0x22, 0x08,
 	0x01, 0x06, 0xd4, 0x30,
 	0xff, 0x6a, 0x24, 0x08,
 	0xf7, 0x01, 0x02, 0x08,
-	0x09, 0x0c, 0xd8, 0x79,
+	0x09, 0x0c, 0xde, 0x79,
 	0x08, 0x0c, 0x04, 0x68,
-	0xb1, 0x6a, 0x96, 0x5e,
+	0xb1, 0x6a, 0xaa, 0x5e,
 	0xff, 0x6a, 0x26, 0x09,
 	0x12, 0x01, 0x02, 0x00,
 	0x02, 0x6a, 0x08, 0x30,
@@ -253,47 +256,47 @@
 	0x00, 0xa5, 0x4a, 0x21,
 	0x00, 0xa6, 0x4c, 0x21,
 	0x00, 0xa7, 0x4e, 0x25,
-	0x08, 0xeb, 0x9a, 0x7e,
-	0x80, 0xeb, 0xf8, 0x79,
+	0x08, 0xeb, 0xae, 0x7e,
+	0x80, 0xeb, 0xfe, 0x79,
 	0xff, 0x6a, 0xd6, 0x09,
-	0x08, 0xeb, 0xfc, 0x69,
+	0x08, 0xeb, 0x02, 0x6a,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x88, 0xeb, 0x12, 0x72,
-	0x08, 0xeb, 0x9a, 0x6e,
-	0x80, 0xa3, 0x9a, 0x6e,
-	0x04, 0xea, 0x16, 0xe2,
-	0x08, 0xee, 0x9a, 0x6e,
+	0x80, 0xa3, 0xae, 0x6e,
+	0x88, 0xeb, 0x18, 0x72,
+	0x08, 0xeb, 0xae, 0x6e,
+	0x04, 0xea, 0x1c, 0xe2,
+	0x08, 0xee, 0xae, 0x6e,
 	0x04, 0x6a, 0xd0, 0x81,
 	0x05, 0xa4, 0xc0, 0x89,
 	0x03, 0xa5, 0xc2, 0x31,
 	0x09, 0x6a, 0xd6, 0x05,
-	0x00, 0x65, 0xfa, 0x59,
+	0x00, 0x65, 0x00, 0x5a,
 	0x06, 0xa4, 0xd4, 0x89,
-	0x80, 0x94, 0x9a, 0x7e,
+	0x80, 0x94, 0xae, 0x7e,
 	0x04, 0xe9, 0x10, 0x31,
 	0x01, 0xe9, 0xca, 0x30,
-	0x01, 0x65, 0x20, 0x7a,
-	0x01, 0x57, 0xae, 0x10,
+	0x01, 0x65, 0x26, 0x7a,
+	0x01, 0x55, 0xaa, 0x10,
 	0x01, 0x65, 0x18, 0x31,
 	0x02, 0xe9, 0x1a, 0x31,
 	0x01, 0xe9, 0x46, 0x31,
-	0x00, 0x65, 0xec, 0x59,
+	0x00, 0x65, 0xf2, 0x59,
 	0x01, 0xa4, 0xca, 0x30,
-	0x01, 0x57, 0x2e, 0x7a,
+	0x01, 0x55, 0x34, 0x7a,
 	0x04, 0x65, 0xca, 0x00,
-	0x80, 0xa3, 0x32, 0x7a,
+	0x80, 0xa3, 0x38, 0x7a,
 	0x02, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0xf8, 0x31,
-	0x01, 0x3b, 0x26, 0x31,
+	0x80, 0x93, 0x26, 0x01,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x01, 0x8c, 0xc8, 0x30,
 	0x00, 0x88, 0xc8, 0x18,
 	0x02, 0x64, 0xc8, 0x88,
-	0xff, 0x64, 0x9a, 0x7e,
-	0xff, 0x8d, 0x48, 0x6a,
-	0xff, 0x8e, 0x48, 0x6a,
+	0xff, 0x64, 0xae, 0x7e,
+	0xff, 0x8d, 0x4e, 0x6a,
+	0xff, 0x8e, 0x4e, 0x6a,
 	0x03, 0x8c, 0xd4, 0x98,
-	0x00, 0x65, 0x9a, 0x56,
+	0x00, 0x65, 0xae, 0x56,
 	0x01, 0x64, 0x70, 0x30,
 	0xff, 0x64, 0xc8, 0x10,
 	0x01, 0x64, 0xc8, 0x18,
@@ -304,139 +307,146 @@
 	0x03, 0xa0, 0x18, 0x31,
 	0x03, 0xa0, 0x10, 0x30,
 	0x08, 0x6a, 0xcc, 0x00,
-	0xa0, 0x6a, 0xbe, 0x5d,
-	0x01, 0xa0, 0xae, 0x08,
-	0x00, 0x65, 0x88, 0x42,
+	0xa0, 0x6a, 0xd0, 0x5d,
+	0x01, 0xa0, 0xaa, 0x08,
+	0x00, 0x65, 0x8e, 0x42,
 	0xa8, 0x6a, 0x76, 0x00,
 	0x79, 0x6a, 0x76, 0x00,
-	0x40, 0x3f, 0x6a, 0x6a,
+	0x40, 0x3f, 0x70, 0x6a,
 	0x04, 0x3b, 0x76, 0x00,
-	0x00, 0x65, 0x52, 0x5d,
+	0x00, 0x65, 0x64, 0x5d,
 	0x04, 0x6a, 0xd4, 0x81,
-	0x20, 0x3c, 0x54, 0x6a,
+	0x20, 0x3c, 0x5a, 0x6a,
 	0x20, 0x3c, 0x78, 0x00,
 	0x07, 0xac, 0x10, 0x31,
 	0x05, 0xb3, 0x46, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xac, 0x6a, 0xb6, 0x5d,
+	0xac, 0x6a, 0xc8, 0x5d,
 	0xa3, 0x6a, 0xcc, 0x00,
-	0xb3, 0x6a, 0xba, 0x5d,
-	0x00, 0x65, 0x38, 0x5a,
+	0xb3, 0x6a, 0xcc, 0x5d,
+	0x00, 0x65, 0x3e, 0x5a,
 	0xfd, 0xa4, 0x48, 0x09,
-	0x01, 0x8c, 0xae, 0x08,
+	0x01, 0x8c, 0xaa, 0x08,
 	0x03, 0x8c, 0x10, 0x30,
-	0x00, 0x65, 0xae, 0x5d,
-	0x01, 0xa4, 0x98, 0x7a,
+	0x00, 0x65, 0xc0, 0x5d,
+	0x01, 0xa4, 0xa0, 0x7a,
 	0x04, 0x3b, 0x76, 0x08,
 	0x01, 0x3b, 0x26, 0x31,
 	0x80, 0x02, 0x04, 0x00,
-	0x10, 0x0c, 0x90, 0x7a,
+	0x10, 0x0c, 0x96, 0x7a,
+	0x03, 0x9e, 0x98, 0x6a,
 	0x7f, 0x02, 0x04, 0x08,
-	0x91, 0x6a, 0x96, 0x5e,
-	0x00, 0x65, 0xbe, 0x41,
+	0x91, 0x6a, 0xaa, 0x5e,
+	0x00, 0x65, 0xc4, 0x41,
 	0x01, 0xa4, 0xca, 0x30,
-	0x80, 0xa3, 0x9e, 0x7a,
+	0x80, 0xa3, 0xa6, 0x7a,
 	0x02, 0x65, 0xca, 0x00,
-	0x01, 0x57, 0xa2, 0x7a,
+	0x01, 0x55, 0xaa, 0x7a,
 	0x04, 0x65, 0xca, 0x00,
 	0x01, 0x65, 0xf8, 0x31,
 	0x01, 0x3b, 0x26, 0x31,
-	0x00, 0x65, 0x00, 0x5a,
-	0x01, 0xfc, 0xae, 0x6a,
-	0x80, 0x0b, 0xa6, 0x6a,
-	0x10, 0x0c, 0xa6, 0x7a,
-	0x04, 0x93, 0xc0, 0x6a,
-	0xdf, 0x93, 0x26, 0x09,
-	0x20, 0x93, 0xb2, 0x6a,
+	0x00, 0x65, 0x06, 0x5a,
+	0x01, 0xfc, 0xb8, 0x6a,
+	0x80, 0x0b, 0xae, 0x6a,
+	0x10, 0x0c, 0xae, 0x7a,
+	0x20, 0x93, 0xae, 0x6a,
 	0x02, 0x93, 0x26, 0x01,
-	0x01, 0x94, 0xb4, 0x7a,
-	0x01, 0x94, 0xb4, 0x7a,
-	0x01, 0x94, 0xb4, 0x7a,
-	0x01, 0x94, 0xb4, 0x7a,
-	0x01, 0x94, 0xb4, 0x7a,
-	0x10, 0x94, 0xc0, 0x6a,
-	0xd7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0xc4, 0x6a,
-	0x02, 0xfc, 0xce, 0x7a,
-	0x01, 0xfc, 0x4e, 0x7b,
+	0x02, 0xfc, 0xc2, 0x7a,
+	0x40, 0x0d, 0xdc, 0x6a,
 	0x01, 0xa4, 0x48, 0x01,
-	0x00, 0x65, 0x4e, 0x43,
-	0x40, 0x0d, 0xd4, 0x6a,
-	0x00, 0x65, 0x00, 0x5a,
-	0x00, 0x65, 0xc6, 0x42,
-	0x80, 0xfc, 0xde, 0x7a,
-	0x80, 0xa4, 0xde, 0x6a,
+	0x00, 0x65, 0xdc, 0x42,
+	0x40, 0x0d, 0xc8, 0x6a,
+	0x00, 0x65, 0x06, 0x5a,
+	0x00, 0x65, 0xba, 0x42,
+	0x80, 0xfc, 0xd2, 0x7a,
+	0x80, 0xa4, 0xd2, 0x6a,
 	0xff, 0xa5, 0x4a, 0x19,
 	0xff, 0xa6, 0x4c, 0x21,
 	0xff, 0xa7, 0x4e, 0x21,
 	0xf8, 0xfc, 0x48, 0x09,
-	0xff, 0x6a, 0xae, 0x08,
-	0x04, 0xfc, 0xe6, 0x7a,
-	0x01, 0x57, 0xae, 0x00,
+	0xff, 0x6a, 0xaa, 0x08,
+	0x04, 0xfc, 0xda, 0x7a,
+	0x01, 0x55, 0xaa, 0x00,
 	0xff, 0x6a, 0x46, 0x09,
-	0xff, 0x38, 0xf2, 0x6a,
-	0x80, 0xa3, 0xf2, 0x7a,
-	0x80, 0x0b, 0xf0, 0x7a,
-	0x04, 0x3b, 0xf2, 0x7a,
+	0x04, 0x3b, 0xf4, 0x6a,
+	0x02, 0x93, 0x26, 0x01,
+	0x01, 0x94, 0xde, 0x7a,
+	0x01, 0x94, 0xde, 0x7a,
+	0x01, 0x94, 0xde, 0x7a,
+	0x01, 0x94, 0xde, 0x7a,
+	0x01, 0x94, 0xde, 0x7a,
+	0x01, 0xa4, 0xf2, 0x7a,
+	0x01, 0xfc, 0xec, 0x7a,
+	0x01, 0x94, 0xf4, 0x6a,
+	0x00, 0x65, 0x8e, 0x42,
+	0x01, 0x94, 0xf2, 0x7a,
+	0x10, 0x94, 0xf4, 0x6a,
+	0xd7, 0x93, 0x26, 0x09,
+	0x28, 0x93, 0xf8, 0x6a,
+	0xff, 0x38, 0x04, 0x6b,
+	0x80, 0xa3, 0x04, 0x7b,
+	0x80, 0x0b, 0x02, 0x7b,
+	0x04, 0x3b, 0x04, 0x7b,
 	0xbf, 0x3b, 0x76, 0x08,
 	0x01, 0x3b, 0x26, 0x31,
-	0x00, 0x65, 0x00, 0x5a,
-	0x01, 0x0b, 0x00, 0x6b,
-	0x10, 0x0c, 0xf4, 0x7a,
-	0x04, 0x93, 0xfe, 0x6a,
-	0x01, 0x94, 0xfc, 0x7a,
-	0x10, 0x94, 0xfe, 0x6a,
+	0x00, 0x65, 0x06, 0x5a,
+	0x01, 0x0b, 0x12, 0x6b,
+	0x10, 0x0c, 0x06, 0x7b,
+	0x04, 0x93, 0x10, 0x6b,
+	0x01, 0x94, 0x0e, 0x7b,
+	0x10, 0x94, 0x10, 0x6b,
 	0xc7, 0x93, 0x26, 0x09,
 	0x01, 0x99, 0xd4, 0x30,
-	0x38, 0x93, 0x02, 0x6b,
-	0xff, 0x08, 0x4e, 0x6b,
-	0xff, 0x09, 0x4e, 0x6b,
-	0xff, 0x0a, 0x4e, 0x6b,
-	0xff, 0x38, 0x1e, 0x7b,
+	0x38, 0x93, 0x14, 0x6b,
+	0xff, 0x08, 0x60, 0x6b,
+	0xff, 0x09, 0x60, 0x6b,
+	0xff, 0x0a, 0x60, 0x6b,
+	0xff, 0x38, 0x30, 0x7b,
 	0x04, 0x14, 0x10, 0x31,
 	0x01, 0x38, 0x18, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xbc, 0x5d,
-	0x00, 0x38, 0xa8, 0x5d,
+	0x14, 0x6a, 0xce, 0x5d,
+	0x00, 0x38, 0xba, 0x5d,
 	0xff, 0x6a, 0x70, 0x08,
-	0x00, 0x65, 0x44, 0x43,
-	0x80, 0xa3, 0x24, 0x7b,
+	0x00, 0x65, 0x56, 0x43,
+	0x80, 0xa3, 0x36, 0x7b,
 	0x01, 0xa4, 0x48, 0x01,
-	0x00, 0x65, 0x4e, 0x43,
-	0x08, 0xeb, 0x2a, 0x7b,
-	0x00, 0x65, 0x00, 0x5a,
-	0x08, 0xeb, 0x26, 0x6b,
+	0x00, 0x65, 0x60, 0x43,
+	0x08, 0xeb, 0x3c, 0x7b,
+	0x00, 0x65, 0x06, 0x5a,
+	0x08, 0xeb, 0x38, 0x6b,
 	0x07, 0xe9, 0x10, 0x31,
-	0x80, 0xe9, 0x30, 0x7b,
+	0x80, 0xe9, 0x42, 0x7b,
 	0x80, 0xa3, 0x46, 0x01,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xa4, 0x6a, 0xbc, 0x5d,
-	0x08, 0x6a, 0xa8, 0x5d,
+	0xa4, 0x6a, 0xce, 0x5d,
+	0x08, 0x6a, 0xba, 0x5d,
 	0x0d, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x6c, 0x5e,
+	0x00, 0x65, 0x80, 0x5e,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x00, 0x65, 0x4e, 0x5e,
+	0x00, 0x65, 0x62, 0x5e,
 	0x01, 0x99, 0x46, 0x31,
-	0x00, 0x65, 0x38, 0x5a,
-	0x00, 0x65, 0xec, 0x59,
+	0x00, 0x65, 0x3e, 0x5a,
+	0x00, 0x65, 0xf2, 0x59,
 	0x03, 0x8c, 0x10, 0x30,
-	0x00, 0x65, 0xae, 0x5d,
-	0x01, 0x8c, 0x4c, 0x7b,
-	0x01, 0x57, 0xae, 0x10,
-	0x80, 0x0b, 0x88, 0x6a,
-	0x80, 0x0b, 0x54, 0x6b,
-	0x01, 0x0c, 0x50, 0x7b,
-	0x10, 0x0c, 0x88, 0x7a,
-	0x00, 0x65, 0xf6, 0x59,
-	0xff, 0x38, 0x66, 0x7b,
+	0x00, 0x65, 0xc0, 0x5d,
+	0x01, 0x8c, 0x5e, 0x7b,
+	0x01, 0x55, 0xaa, 0x10,
+	0x80, 0x0b, 0x8e, 0x6a,
+	0x80, 0x0b, 0x68, 0x6b,
+	0x01, 0x0c, 0x62, 0x7b,
+	0x10, 0x0c, 0x8e, 0x7a,
+	0x03, 0x9e, 0x8e, 0x6a,
+	0x00, 0x65, 0xfc, 0x59,
+	0xff, 0x38, 0x7a, 0x7b,
 	0x01, 0x38, 0xc8, 0x30,
 	0x00, 0x08, 0x40, 0x19,
 	0xff, 0x6a, 0xc8, 0x08,
 	0x00, 0x09, 0x42, 0x21,
 	0x00, 0x0a, 0x44, 0x21,
 	0xff, 0x6a, 0x70, 0x08,
-	0x00, 0x65, 0x68, 0x43,
+	0x00, 0x65, 0x7c, 0x43,
 	0x03, 0x08, 0x40, 0x31,
 	0x03, 0x08, 0x40, 0x31,
 	0x01, 0x08, 0x40, 0x31,
@@ -445,13 +455,13 @@
 	0xfd, 0xb4, 0x68, 0x09,
 	0x12, 0x01, 0x02, 0x00,
 	0x12, 0x01, 0x02, 0x00,
-	0x04, 0x3c, 0xbe, 0x79,
+	0x04, 0x3c, 0xc4, 0x79,
 	0xfb, 0x3c, 0x78, 0x08,
-	0x04, 0x93, 0x2e, 0x79,
-	0x01, 0x0c, 0x7c, 0x6b,
-	0x00, 0x65, 0x2e, 0x41,
-	0x00, 0x65, 0xbe, 0x41,
-	0x00, 0x65, 0x52, 0x5d,
+	0x04, 0x93, 0x34, 0x79,
+	0x01, 0x0c, 0x90, 0x6b,
+	0x00, 0x65, 0x34, 0x41,
+	0x00, 0x65, 0xc4, 0x41,
+	0x00, 0x65, 0x64, 0x5d,
 	0x01, 0xbc, 0x18, 0x31,
 	0x02, 0x6a, 0x1a, 0x31,
 	0x02, 0x6a, 0xf8, 0x01,
@@ -461,16 +471,16 @@
 	0xff, 0x6a, 0x12, 0x08,
 	0xff, 0x6a, 0x14, 0x08,
 	0xf3, 0xbc, 0xd4, 0x18,
-	0xa0, 0x6a, 0xaa, 0x53,
+	0xa0, 0x6a, 0xbe, 0x53,
 	0x04, 0xa0, 0x10, 0x31,
 	0xac, 0x6a, 0x26, 0x01,
 	0x04, 0xa0, 0x10, 0x31,
 	0x03, 0x08, 0x18, 0x31,
 	0x88, 0x6a, 0xcc, 0x00,
-	0xa0, 0x6a, 0xbc, 0x5d,
-	0x00, 0xbc, 0xa8, 0x5d,
+	0xa0, 0x6a, 0xce, 0x5d,
+	0x00, 0xbc, 0xba, 0x5d,
 	0x3d, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0xc2, 0x43,
+	0x00, 0x65, 0xd6, 0x43,
 	0xff, 0x6a, 0x10, 0x09,
 	0xa4, 0x6a, 0x26, 0x01,
 	0x0c, 0xa0, 0x32, 0x31,
@@ -480,114 +490,112 @@
 	0x36, 0x6a, 0x26, 0x01,
 	0x02, 0x93, 0x26, 0x01,
 	0x35, 0x6a, 0x26, 0x01,
-	0x00, 0x65, 0x60, 0x5e,
-	0x00, 0x65, 0x60, 0x5e,
+	0x00, 0x65, 0x74, 0x5e,
+	0x00, 0x65, 0x74, 0x5e,
 	0x02, 0x93, 0x26, 0x01,
-	0x04, 0x0b, 0xc6, 0x6b,
-	0x10, 0x0c, 0xc2, 0x7b,
-	0x01, 0x03, 0xc6, 0x6b,
+	0x04, 0x0b, 0xda, 0x6b,
+	0x10, 0x0c, 0xd6, 0x7b,
+	0x01, 0x03, 0xda, 0x6b,
+	0x20, 0x93, 0xd6, 0x6b,
 	0xc7, 0x93, 0x26, 0x09,
-	0x38, 0x93, 0xca, 0x6b,
+	0x38, 0x93, 0xe0, 0x6b,
 	0x10, 0x01, 0x02, 0x00,
-	0x00, 0x65, 0xbe, 0x41,
-	0x00, 0x65, 0x52, 0x5d,
+	0x00, 0x65, 0xc4, 0x41,
+	0x00, 0x65, 0x64, 0x5d,
 	0x01, 0x06, 0x50, 0x31,
-	0x00, 0x65, 0xbe, 0x41,
+	0x00, 0x65, 0xc4, 0x41,
 	0x10, 0x3f, 0x06, 0x00,
+	0x10, 0x6a, 0x06, 0x00,
 	0x01, 0x3a, 0xca, 0x30,
-	0x80, 0x65, 0x04, 0x64,
-	0x10, 0xb8, 0x28, 0x6c,
-	0x01, 0xb9, 0xdc, 0x30,
-	0x01, 0x6e, 0xc8, 0x30,
-	0x01, 0x54, 0xca, 0x30,
-	0x80, 0xb9, 0xe8, 0x7b,
-	0x01, 0x55, 0xca, 0x30,
-	0x80, 0xb9, 0xec, 0x7b,
-	0x01, 0x55, 0xca, 0x30,
-	0x00, 0x65, 0x28, 0x6c,
+	0x80, 0x65, 0x0c, 0x64,
+	0x10, 0xb8, 0x30, 0x6c,
 	0xc0, 0xba, 0xca, 0x00,
-	0x40, 0xb8, 0xf4, 0x6b,
+	0x40, 0xb8, 0xfc, 0x6b,
 	0xbf, 0x65, 0xca, 0x08,
-	0x20, 0xb8, 0x08, 0x7c,
+	0x20, 0xb8, 0x10, 0x7c,
 	0x01, 0x65, 0x0c, 0x30,
-	0x00, 0x65, 0xa0, 0x5d,
-	0xa0, 0x3f, 0x10, 0x64,
+	0x00, 0x65, 0xb2, 0x5d,
+	0xa0, 0x3f, 0x18, 0x64,
 	0x23, 0xb8, 0x0c, 0x08,
-	0x00, 0x65, 0xa0, 0x5d,
-	0xa0, 0x3f, 0x10, 0x64,
-	0x00, 0xbb, 0x08, 0x44,
-	0xff, 0x65, 0x08, 0x64,
-	0x00, 0x65, 0x28, 0x44,
+	0x00, 0x65, 0xb2, 0x5d,
+	0xa0, 0x3f, 0x18, 0x64,
+	0x00, 0xbb, 0x10, 0x44,
+	0xff, 0x65, 0x10, 0x64,
+	0x00, 0x65, 0x30, 0x44,
 	0x40, 0x6a, 0x18, 0x00,
 	0x01, 0x65, 0x0c, 0x30,
-	0x00, 0x65, 0xa0, 0x5d,
-	0xa0, 0x3f, 0xd6, 0x73,
+	0x00, 0x65, 0xb2, 0x5d,
+	0xa0, 0x3f, 0xec, 0x73,
 	0x40, 0x6a, 0x18, 0x00,
 	0x01, 0x3a, 0xa6, 0x30,
 	0x08, 0x6a, 0x74, 0x00,
-	0x00, 0x65, 0xbe, 0x41,
-	0x64, 0x6a, 0x2c, 0x5d,
-	0x80, 0x64, 0x9e, 0x6c,
-	0x04, 0x64, 0x74, 0x74,
-	0x02, 0x64, 0x82, 0x74,
-	0x00, 0x6a, 0x44, 0x74,
-	0x03, 0x64, 0x90, 0x74,
-	0x23, 0x64, 0x30, 0x74,
-	0x08, 0x64, 0x40, 0x74,
-	0x61, 0x6a, 0x96, 0x5e,
-	0x00, 0x65, 0xa0, 0x5d,
-	0x08, 0x51, 0xc0, 0x71,
-	0x00, 0x65, 0x28, 0x44,
-	0x80, 0x04, 0x3e, 0x7c,
-	0x51, 0x6a, 0x22, 0x5d,
-	0x01, 0x51, 0x3e, 0x64,
-	0x01, 0xa4, 0x3a, 0x7c,
-	0x01, 0x57, 0x40, 0x7c,
-	0x41, 0x6a, 0x96, 0x5e,
-	0x00, 0x65, 0x40, 0x44,
-	0x07, 0x6a, 0x1a, 0x5d,
+	0x00, 0x65, 0xc4, 0x41,
+	0x64, 0x6a, 0x3e, 0x5d,
+	0x80, 0x64, 0xae, 0x6c,
+	0x04, 0x64, 0x7c, 0x74,
+	0x02, 0x64, 0x8a, 0x74,
+	0x00, 0x6a, 0x4c, 0x74,
+	0x03, 0x64, 0xa0, 0x74,
+	0x23, 0x64, 0x38, 0x74,
+	0x08, 0x64, 0x48, 0x74,
+	0x61, 0x6a, 0xaa, 0x5e,
+	0x00, 0x65, 0xb2, 0x5d,
+	0x08, 0x51, 0xc6, 0x71,
+	0x00, 0x65, 0x30, 0x44,
+	0x80, 0x04, 0x46, 0x7c,
+	0x51, 0x6a, 0x34, 0x5d,
+	0x01, 0x51, 0x46, 0x64,
+	0x01, 0xa4, 0x42, 0x7c,
+	0x01, 0x55, 0x48, 0x7c,
+	0x41, 0x6a, 0xaa, 0x5e,
+	0x00, 0x65, 0x48, 0x44,
+	0x07, 0x6a, 0x2a, 0x5d,
 	0x01, 0x06, 0xd4, 0x30,
-	0x00, 0x65, 0xbe, 0x41,
-	0x10, 0xb8, 0x48, 0x7c,
-	0xa1, 0x6a, 0x96, 0x5e,
-	0x01, 0xb4, 0x4e, 0x6c,
-	0x02, 0xb4, 0x50, 0x6c,
-	0x01, 0xa4, 0x50, 0x7c,
-	0xff, 0xa8, 0x60, 0x7c,
+	0x00, 0x65, 0xc4, 0x41,
+	0x10, 0xb8, 0x50, 0x7c,
+	0xa1, 0x6a, 0xaa, 0x5e,
+	0x01, 0xb4, 0x56, 0x6c,
+	0x02, 0xb4, 0x58, 0x6c,
+	0x01, 0xa4, 0x58, 0x7c,
+	0xff, 0xa8, 0x68, 0x7c,
 	0x04, 0xb4, 0x68, 0x01,
 	0x01, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0xda, 0x5d,
-	0xff, 0xa8, 0x60, 0x7c,
-	0x71, 0x6a, 0x96, 0x5e,
-	0x40, 0x51, 0x60, 0x64,
-	0x00, 0x65, 0x76, 0x5e,
-	0x00, 0x65, 0xd0, 0x41,
-	0x00, 0xbb, 0x64, 0x5c,
-	0x00, 0x65, 0xd0, 0x41,
-	0x00, 0x65, 0x76, 0x5e,
+	0x00, 0xbb, 0xec, 0x5d,
+	0xff, 0xa8, 0x68, 0x7c,
+	0x71, 0x6a, 0xaa, 0x5e,
+	0x40, 0x51, 0x68, 0x64,
+	0x00, 0x65, 0x8a, 0x5e,
+	0x00, 0x65, 0xd6, 0x41,
+	0x00, 0xbb, 0x6c, 0x5c,
+	0x00, 0x65, 0xd6, 0x41,
+	0x00, 0x65, 0x8a, 0x5e,
 	0x01, 0x65, 0xa2, 0x30,
 	0x01, 0xf8, 0xc8, 0x30,
 	0x01, 0x4e, 0xc8, 0x30,
-	0x00, 0x6a, 0x7e, 0xdd,
-	0x00, 0x51, 0x90, 0x5d,
+	0x00, 0x6a, 0x90, 0xdd,
+	0x00, 0x51, 0xa2, 0x5d,
 	0x01, 0x4e, 0x9c, 0x18,
 	0x02, 0x6a, 0x22, 0x05,
 	0x04, 0xb8, 0x70, 0x01,
-	0x00, 0x65, 0x92, 0x5e,
-	0x20, 0xb8, 0xd0, 0x69,
+	0x00, 0x65, 0xa6, 0x5e,
+	0x20, 0xb8, 0xd6, 0x69,
 	0x01, 0xbb, 0xa2, 0x30,
 	0x01, 0xba, 0x7c, 0x30,
-	0x00, 0xb9, 0x94, 0x5c,
-	0x00, 0x65, 0xd0, 0x41,
-	0x20, 0x3c, 0x40, 0x7c,
+	0x00, 0xb9, 0xa4, 0x5c,
+	0x00, 0x65, 0xd6, 0x41,
+	0x01, 0x06, 0xd4, 0x30,
+	0x20, 0x3c, 0xc4, 0x79,
+	0x20, 0x3c, 0x48, 0x7c,
 	0x04, 0x14, 0x58, 0x31,
+	0x01, 0x06, 0xd4, 0x30,
 	0x08, 0xa0, 0x60, 0x31,
 	0xac, 0x6a, 0xcc, 0x00,
-	0x14, 0x6a, 0xbc, 0x5d,
-	0xa0, 0x6a, 0xb4, 0x5d,
-	0x00, 0x65, 0x40, 0x44,
+	0x14, 0x6a, 0xce, 0x5d,
+	0x01, 0x06, 0xd4, 0x30,
+	0xa0, 0x6a, 0xc6, 0x5d,
+	0x00, 0x65, 0xc4, 0x41,
 	0xdf, 0x3c, 0x78, 0x08,
-	0x00, 0x65, 0x40, 0x44,
+	0x00, 0x65, 0x48, 0x44,
 	0x4c, 0x65, 0xcc, 0x28,
 	0x01, 0x3e, 0x20, 0x31,
 	0xd0, 0x66, 0xcc, 0x18,
@@ -598,103 +606,104 @@
 	0xd0, 0x65, 0xca, 0x18,
 	0x01, 0x3e, 0x20, 0x31,
 	0x30, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xac, 0x4c,
+	0x00, 0x65, 0xbc, 0x4c,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x20, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xb4, 0x54,
+	0x00, 0x65, 0xc4, 0x54,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x20, 0x65, 0xca, 0x18,
 	0xe0, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xbe, 0x4c,
+	0x00, 0x65, 0xce, 0x4c,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xd0, 0x65, 0xd4, 0x18,
-	0x00, 0x65, 0xc6, 0x54,
+	0x00, 0x65, 0xd6, 0x54,
 	0xe1, 0x6a, 0x22, 0x01,
 	0xff, 0x6a, 0xd4, 0x08,
 	0x01, 0x6c, 0xa2, 0x30,
-	0xff, 0x51, 0xd8, 0x74,
-	0x00, 0x51, 0x56, 0x5d,
+	0xff, 0x51, 0xe8, 0x74,
+	0x00, 0x51, 0x68, 0x5d,
 	0x01, 0x51, 0x20, 0x31,
-	0x00, 0x65, 0xfa, 0x44,
+	0x00, 0x65, 0x0a, 0x45,
 	0x01, 0xba, 0xc8, 0x30,
-	0x00, 0x3e, 0xfa, 0x74,
-	0x00, 0x65, 0x74, 0x5e,
+	0x00, 0x3e, 0x0a, 0x75,
+	0x00, 0x65, 0x88, 0x5e,
 	0x80, 0x3c, 0x78, 0x00,
 	0x01, 0x06, 0xd4, 0x30,
-	0x00, 0x65, 0xa0, 0x5d,
+	0x00, 0x65, 0xb2, 0x5d,
 	0x01, 0x3c, 0x78, 0x00,
-	0xe0, 0x3f, 0x16, 0x65,
+	0xe0, 0x3f, 0x26, 0x65,
 	0x02, 0x3c, 0x78, 0x00,
-	0x20, 0x12, 0x16, 0x65,
-	0x51, 0x6a, 0x22, 0x5d,
-	0x00, 0x51, 0x56, 0x5d,
-	0x51, 0x6a, 0x22, 0x5d,
+	0x20, 0x12, 0x26, 0x65,
+	0x51, 0x6a, 0x34, 0x5d,
+	0x00, 0x51, 0x68, 0x5d,
+	0x51, 0x6a, 0x34, 0x5d,
 	0x01, 0x51, 0x20, 0x31,
 	0x04, 0x3c, 0x78, 0x00,
 	0x01, 0xb9, 0xc8, 0x30,
-	0x00, 0x3d, 0x14, 0x65,
+	0x00, 0x3d, 0x24, 0x65,
 	0x08, 0x3c, 0x78, 0x00,
 	0x01, 0xba, 0xc8, 0x30,
-	0x00, 0x3e, 0x14, 0x65,
+	0x00, 0x3e, 0x24, 0x65,
 	0x10, 0x3c, 0x78, 0x00,
-	0x04, 0xb8, 0x14, 0x7d,
+	0x04, 0xb8, 0x24, 0x7d,
 	0xfb, 0xb8, 0x70, 0x09,
-	0x20, 0xb8, 0x0a, 0x6d,
+	0x20, 0xb8, 0x1a, 0x6d,
 	0x01, 0x90, 0xc8, 0x30,
 	0xff, 0x6a, 0xa2, 0x00,
-	0x00, 0x3d, 0x94, 0x5c,
+	0x00, 0x3d, 0xa4, 0x5c,
 	0x01, 0x64, 0x20, 0x31,
 	0x80, 0x6a, 0x78, 0x00,
 	0x00, 0x65, 0x02, 0x59,
-	0x10, 0xb8, 0x40, 0x7c,
-	0xff, 0x6a, 0x1a, 0x5d,
-	0x00, 0x65, 0x40, 0x44,
-	0x00, 0x65, 0x74, 0x5e,
-	0x31, 0x6a, 0x96, 0x5e,
-	0x00, 0x65, 0x40, 0x44,
+	0x10, 0xb8, 0x48, 0x7c,
+	0xff, 0x6a, 0x2a, 0x5d,
+	0x00, 0x65, 0x48, 0x44,
+	0x00, 0x65, 0x88, 0x5e,
+	0x31, 0x6a, 0xaa, 0x5e,
+	0x00, 0x65, 0x48, 0x44,
 	0x10, 0x3f, 0x06, 0x00,
+	0x10, 0x6a, 0x06, 0x00,
 	0x01, 0x65, 0x74, 0x34,
-	0x81, 0x6a, 0x96, 0x5e,
-	0x00, 0x65, 0x24, 0x45,
+	0x81, 0x6a, 0xaa, 0x5e,
+	0x00, 0x65, 0x36, 0x45,
 	0x01, 0x06, 0xd4, 0x30,
-	0x01, 0x0c, 0x24, 0x7d,
-	0x04, 0x0c, 0x1e, 0x6d,
+	0x01, 0x0c, 0x36, 0x7d,
+	0x04, 0x0c, 0x30, 0x6d,
 	0xe0, 0x03, 0x7e, 0x08,
-	0xe0, 0x3f, 0xbe, 0x61,
+	0xe0, 0x3f, 0xc4, 0x61,
 	0x01, 0x65, 0xcc, 0x30,
 	0x01, 0x12, 0xda, 0x34,
 	0x01, 0x06, 0xd4, 0x34,
-	0x01, 0x03, 0x32, 0x6d,
+	0x01, 0x03, 0x44, 0x6d,
 	0x40, 0x03, 0xcc, 0x08,
 	0x01, 0x65, 0x06, 0x30,
 	0x40, 0x65, 0xc8, 0x08,
-	0x00, 0x66, 0x40, 0x75,
-	0x40, 0x65, 0x40, 0x7d,
-	0x00, 0x65, 0x40, 0x5d,
+	0x00, 0x66, 0x52, 0x75,
+	0x40, 0x65, 0x52, 0x7d,
+	0x00, 0x65, 0x52, 0x5d,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x08,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x08, 0x01, 0x02, 0x00,
-	0x02, 0x0b, 0x4a, 0x7d,
+	0x02, 0x0b, 0x5c, 0x7d,
 	0x01, 0x65, 0x0c, 0x30,
-	0x02, 0x0b, 0x4e, 0x7d,
+	0x02, 0x0b, 0x60, 0x7d,
 	0xf7, 0x01, 0x02, 0x0c,
-	0x80, 0x3c, 0x9a, 0x6e,
-	0x21, 0x6a, 0x96, 0x46,
+	0x80, 0x3c, 0xae, 0x6e,
+	0x21, 0x6a, 0xaa, 0x46,
 	0x01, 0x65, 0xc8, 0x30,
-	0xff, 0x41, 0x76, 0x75,
+	0xff, 0x41, 0x88, 0x75,
 	0x01, 0x41, 0x20, 0x31,
 	0xff, 0x6a, 0xa4, 0x00,
-	0x00, 0x65, 0x66, 0x45,
-	0xff, 0xbf, 0x76, 0x75,
+	0x00, 0x65, 0x78, 0x45,
+	0xff, 0xbf, 0x88, 0x75,
 	0x01, 0x90, 0xa4, 0x30,
 	0x01, 0xbf, 0x20, 0x31,
-	0x00, 0xbb, 0x60, 0x65,
-	0xff, 0x52, 0x74, 0x75,
+	0x00, 0xbb, 0x72, 0x65,
+	0xff, 0x52, 0x86, 0x75,
 	0x01, 0xbf, 0xcc, 0x30,
 	0x01, 0x90, 0xca, 0x30,
 	0x01, 0x52, 0x20, 0x31,
@@ -702,28 +711,28 @@
 	0x01, 0x65, 0x20, 0x35,
 	0x01, 0xbf, 0x82, 0x34,
 	0x01, 0x64, 0xa2, 0x30,
-	0x00, 0x6a, 0x7e, 0x5e,
+	0x00, 0x6a, 0x92, 0x5e,
 	0x0d, 0x6a, 0x76, 0x00,
-	0x00, 0x51, 0xda, 0x45,
+	0x00, 0x51, 0xec, 0x45,
 	0x01, 0x65, 0xa4, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xce, 0x5d,
+	0x48, 0x6a, 0xe0, 0x5d,
 	0x01, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x05,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x48, 0x6a, 0xce, 0x5d,
-	0x01, 0x6a, 0xa8, 0x5d,
+	0x48, 0x6a, 0xe0, 0x5d,
+	0x01, 0x6a, 0xba, 0x5d,
 	0x01, 0x6a, 0x26, 0x05,
 	0x01, 0x65, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0x94, 0x7d,
+	0x80, 0xee, 0xa6, 0x7d,
 	0xff, 0x6a, 0xdc, 0x0d,
 	0x01, 0x65, 0x32, 0x31,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x6c, 0x46,
-	0x81, 0x6a, 0x96, 0x5e,
-	0x01, 0x0c, 0xa0, 0x7d,
-	0x04, 0x0c, 0x9e, 0x6d,
+	0x00, 0x65, 0x80, 0x46,
+	0x81, 0x6a, 0xaa, 0x5e,
+	0x01, 0x0c, 0xb2, 0x7d,
+	0x04, 0x0c, 0xb0, 0x6d,
 	0xe0, 0x03, 0x06, 0x08,
 	0xe0, 0x03, 0x7e, 0x0c,
 	0x01, 0x65, 0x18, 0x31,
@@ -742,7 +751,7 @@
 	0x01, 0x6c, 0xda, 0x34,
 	0x3d, 0x64, 0xa4, 0x28,
 	0x55, 0x64, 0xc8, 0x28,
-	0x00, 0x65, 0xce, 0x45,
+	0x00, 0x65, 0xe0, 0x45,
 	0x2e, 0x64, 0xa4, 0x28,
 	0x66, 0x64, 0xc8, 0x28,
 	0x00, 0x6c, 0xda, 0x18,
@@ -753,61 +762,62 @@
 	0x00, 0x6c, 0xda, 0x24,
 	0x01, 0x65, 0xc8, 0x30,
 	0xe0, 0x6a, 0xcc, 0x00,
-	0x44, 0x6a, 0xca, 0x5d,
+	0x44, 0x6a, 0xdc, 0x5d,
 	0x01, 0x90, 0xe2, 0x31,
-	0x04, 0x3b, 0xee, 0x7d,
+	0x04, 0x3b, 0x00, 0x7e,
 	0x30, 0x6a, 0xd0, 0x01,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x1d, 0x6a, 0xdc, 0x01,
-	0xdc, 0xee, 0xea, 0x65,
-	0x00, 0x65, 0x06, 0x46,
+	0xdc, 0xee, 0xfc, 0x65,
+	0x00, 0x65, 0x18, 0x46,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x01, 0x6a, 0xdc, 0x01,
 	0x20, 0xa0, 0xd8, 0x31,
 	0x09, 0xee, 0xdc, 0x01,
-	0x80, 0xee, 0xf6, 0x7d,
+	0x80, 0xee, 0x08, 0x7e,
 	0x11, 0x6a, 0xdc, 0x01,
-	0x50, 0xee, 0xfa, 0x65,
+	0x50, 0xee, 0x0c, 0x66,
 	0x20, 0x6a, 0xd0, 0x01,
 	0x09, 0x6a, 0xdc, 0x01,
-	0x88, 0xee, 0x00, 0x66,
+	0x88, 0xee, 0x12, 0x66,
 	0x19, 0x6a, 0xdc, 0x01,
-	0xd8, 0xee, 0x04, 0x66,
+	0xd8, 0xee, 0x16, 0x66,
 	0xff, 0x6a, 0xdc, 0x09,
-	0x18, 0xee, 0x08, 0x6e,
+	0x18, 0xee, 0x1a, 0x6e,
 	0xff, 0x6a, 0xd4, 0x0c,
 	0x88, 0x6a, 0xcc, 0x00,
-	0x44, 0x6a, 0xca, 0x5d,
-	0x20, 0x6a, 0xa8, 0x5d,
+	0x44, 0x6a, 0xdc, 0x5d,
+	0x20, 0x6a, 0xba, 0x5d,
 	0x01, 0x3b, 0x26, 0x31,
-	0x04, 0x3b, 0x22, 0x6e,
+	0x04, 0x3b, 0x34, 0x6e,
 	0xa0, 0x6a, 0xca, 0x00,
 	0x20, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0x5c, 0x5e,
-	0x00, 0x65, 0x1a, 0x66,
+	0x00, 0x65, 0x70, 0x5e,
+	0x00, 0x65, 0x2c, 0x66,
 	0x0a, 0x93, 0x26, 0x01,
-	0x00, 0x65, 0x6c, 0x46,
+	0x00, 0x65, 0x80, 0x46,
 	0xa0, 0x6a, 0xcc, 0x00,
 	0xff, 0x6a, 0xc8, 0x08,
-	0x01, 0x94, 0x26, 0x6e,
-	0x10, 0x94, 0x28, 0x6e,
-	0x08, 0x94, 0x3e, 0x6e,
-	0x08, 0x94, 0x3e, 0x6e,
-	0x08, 0x94, 0x3e, 0x6e,
+	0x20, 0x94, 0x38, 0x6e,
+	0x10, 0x94, 0x3a, 0x6e,
+	0x08, 0x94, 0x52, 0x6e,
+	0x08, 0x94, 0x52, 0x6e,
+	0x08, 0x94, 0x52, 0x6e,
 	0x07, 0x8c, 0xca, 0x18,
 	0x3d, 0x65, 0xca, 0x28,
 	0x00, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0x42, 0x5e,
+	0x00, 0x65, 0x56, 0x5e,
 	0xff, 0x65, 0xca, 0x10,
 	0x05, 0x65, 0xc8, 0x18,
-	0x00, 0x65, 0x26, 0x46,
+	0x04, 0x64, 0x82, 0x76,
+	0x00, 0x65, 0x38, 0x46,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x40, 0x6e,
+	0x08, 0x93, 0x54, 0x6e,
 	0x00, 0x62, 0xc4, 0x18,
-	0x00, 0x65, 0x6c, 0x5e,
-	0x00, 0x65, 0x4c, 0x5e,
-	0x00, 0x65, 0x4c, 0x5e,
-	0x00, 0x65, 0x4c, 0x5e,
+	0x00, 0x65, 0x80, 0x5e,
+	0x00, 0x65, 0x60, 0x5e,
+	0x00, 0x65, 0x60, 0x5e,
+	0x00, 0x65, 0x60, 0x5e,
 	0x01, 0x99, 0xda, 0x30,
 	0x01, 0x99, 0xda, 0x30,
 	0x01, 0x99, 0xda, 0x30,
@@ -824,23 +834,23 @@
 	0x01, 0x6c, 0x32, 0x31,
 	0x01, 0x6c, 0x32, 0x31,
 	0x01, 0x6c, 0x32, 0x35,
-	0x08, 0x94, 0x6c, 0x7e,
+	0x08, 0x94, 0x80, 0x7e,
 	0xf7, 0x93, 0x26, 0x09,
-	0x08, 0x93, 0x70, 0x6e,
+	0x08, 0x93, 0x84, 0x6e,
 	0xff, 0x6a, 0xd4, 0x0c,
-	0x04, 0xb8, 0x92, 0x6e,
+	0x04, 0xb8, 0xa6, 0x6e,
 	0x01, 0x42, 0x7e, 0x31,
 	0xff, 0x6a, 0x76, 0x01,
 	0x01, 0x90, 0x84, 0x34,
 	0xff, 0x6a, 0x76, 0x05,
-	0xff, 0x42, 0x8e, 0x66,
-	0xff, 0x41, 0x86, 0x66,
-	0xd1, 0x6a, 0x96, 0x5e,
+	0xff, 0x42, 0xa2, 0x66,
+	0xff, 0x41, 0x9a, 0x66,
+	0xd1, 0x6a, 0xaa, 0x5e,
 	0xff, 0x6a, 0xca, 0x04,
 	0x01, 0x41, 0x20, 0x31,
 	0x01, 0xbf, 0x82, 0x30,
 	0x01, 0x6a, 0x76, 0x00,
-	0x00, 0xbb, 0xda, 0x45,
+	0x00, 0xbb, 0xec, 0x45,
 	0x01, 0x42, 0x20, 0x31,
 	0x01, 0xbf, 0x84, 0x34,
 	0x01, 0x41, 0x7e, 0x31,
@@ -919,7 +929,7 @@
 static int
 ahc_patch14_func(struct ahc_softc *ahc)
 {
-	return ((ahc->features & AHC_DT) == 0);
+	return ((ahc->features & AHC_ULTRA2) == 0);
 }
 
 static int ahc_patch13_func(struct ahc_softc *ahc);
@@ -927,7 +937,7 @@
 static int
 ahc_patch13_func(struct ahc_softc *ahc)
 {
-	return ((ahc->features & AHC_ULTRA2) == 0);
+	return ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0);
 }
 
 static int ahc_patch12_func(struct ahc_softc *ahc);
@@ -935,7 +945,7 @@
 static int
 ahc_patch12_func(struct ahc_softc *ahc)
 {
-	return ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0);
+	return ((ahc->features & AHC_ULTRA) != 0);
 }
 
 static int ahc_patch11_func(struct ahc_softc *ahc);
@@ -943,7 +953,7 @@
 static int
 ahc_patch11_func(struct ahc_softc *ahc)
 {
-	return ((ahc->features & AHC_ULTRA) != 0);
+	return ((ahc->features & AHC_HS_MAILBOX) != 0);
 }
 
 static int ahc_patch10_func(struct ahc_softc *ahc);
@@ -951,7 +961,7 @@
 static int
 ahc_patch10_func(struct ahc_softc *ahc)
 {
-	return ((ahc->features & AHC_HS_MAILBOX) != 0);
+	return ((ahc->features & AHC_MULTI_TID) != 0);
 }
 
 static int ahc_patch9_func(struct ahc_softc *ahc);
@@ -959,7 +969,7 @@
 static int
 ahc_patch9_func(struct ahc_softc *ahc)
 {
-	return ((ahc->features & AHC_MULTI_TID) != 0);
+	return ((ahc->features & AHC_CMD_CHAN) != 0);
 }
 
 static int ahc_patch8_func(struct ahc_softc *ahc);
@@ -967,7 +977,7 @@
 static int
 ahc_patch8_func(struct ahc_softc *ahc)
 {
-	return ((ahc->features & AHC_CMD_CHAN) != 0);
+	return ((ahc->flags & AHC_INITIATORROLE) != 0);
 }
 
 static int ahc_patch7_func(struct ahc_softc *ahc);
@@ -975,7 +985,7 @@
 static int
 ahc_patch7_func(struct ahc_softc *ahc)
 {
-	return ((ahc->flags & AHC_INITIATORROLE) != 0);
+	return ((ahc->flags & AHC_TARGETROLE) != 0);
 }
 
 static int ahc_patch6_func(struct ahc_softc *ahc);
@@ -983,7 +993,7 @@
 static int
 ahc_patch6_func(struct ahc_softc *ahc)
 {
-	return ((ahc->flags & AHC_TARGETROLE) != 0);
+	return ((ahc->features & AHC_DT) == 0);
 }
 
 static int ahc_patch5_func(struct ahc_softc *ahc);
@@ -1051,28 +1061,29 @@
 	{ ahc_patch5_func, 22, 2, 1 },
 	{ ahc_patch3_func, 27, 1, 2 },
 	{ ahc_patch0_func, 28, 1, 1 },
-	{ ahc_patch6_func, 37, 65, 21 },
-	{ ahc_patch7_func, 37, 1, 1 },
-	{ ahc_patch8_func, 45, 3, 2 },
+	{ ahc_patch6_func, 34, 1, 1 },
+	{ ahc_patch7_func, 37, 65, 21 },
+	{ ahc_patch8_func, 37, 1, 1 },
+	{ ahc_patch9_func, 45, 3, 2 },
 	{ ahc_patch0_func, 48, 3, 1 },
-	{ ahc_patch9_func, 52, 1, 2 },
+	{ ahc_patch10_func, 52, 1, 2 },
 	{ ahc_patch0_func, 53, 2, 3 },
 	{ ahc_patch1_func, 53, 1, 2 },
 	{ ahc_patch0_func, 54, 1, 1 },
 	{ ahc_patch2_func, 56, 2, 1 },
-	{ ahc_patch8_func, 58, 1, 2 },
+	{ ahc_patch9_func, 58, 1, 2 },
 	{ ahc_patch0_func, 59, 1, 1 },
-	{ ahc_patch8_func, 63, 1, 2 },
+	{ ahc_patch9_func, 63, 1, 2 },
 	{ ahc_patch0_func, 64, 1, 1 },
-	{ ahc_patch8_func, 73, 1, 2 },
+	{ ahc_patch9_func, 73, 1, 2 },
 	{ ahc_patch0_func, 74, 1, 1 },
-	{ ahc_patch8_func, 77, 1, 2 },
+	{ ahc_patch9_func, 77, 1, 2 },
 	{ ahc_patch0_func, 78, 1, 1 },
-	{ ahc_patch10_func, 88, 1, 2 },
+	{ ahc_patch11_func, 88, 1, 2 },
 	{ ahc_patch0_func, 89, 1, 1 },
-	{ ahc_patch8_func, 97, 1, 2 },
+	{ ahc_patch9_func, 97, 1, 2 },
 	{ ahc_patch0_func, 98, 1, 1 },
-	{ ahc_patch7_func, 102, 9, 4 },
+	{ ahc_patch8_func, 102, 9, 4 },
 	{ ahc_patch1_func, 104, 1, 2 },
 	{ ahc_patch0_func, 105, 1, 1 },
 	{ ahc_patch2_func, 107, 2, 1 },
@@ -1081,147 +1092,162 @@
 	{ ahc_patch0_func, 121, 2, 3 },
 	{ ahc_patch2_func, 121, 1, 2 },
 	{ ahc_patch0_func, 122, 1, 1 },
-	{ ahc_patch6_func, 123, 4, 2 },
+	{ ahc_patch7_func, 123, 4, 2 },
 	{ ahc_patch0_func, 127, 1, 1 },
-	{ ahc_patch11_func, 129, 2, 1 },
+	{ ahc_patch12_func, 129, 2, 1 },
 	{ ahc_patch1_func, 131, 1, 2 },
 	{ ahc_patch0_func, 132, 1, 1 },
-	{ ahc_patch6_func, 133, 4, 1 },
-	{ ahc_patch6_func, 144, 77, 9 },
-	{ ahc_patch4_func, 156, 1, 1 },
-	{ ahc_patch1_func, 172, 1, 1 },
-	{ ahc_patch8_func, 180, 1, 2 },
-	{ ahc_patch0_func, 181, 1, 1 },
-	{ ahc_patch8_func, 190, 1, 2 },
-	{ ahc_patch0_func, 191, 1, 1 },
-	{ ahc_patch8_func, 207, 6, 2 },
-	{ ahc_patch0_func, 213, 6, 1 },
-	{ ahc_patch7_func, 221, 18, 2 },
-	{ ahc_patch1_func, 234, 1, 1 },
-	{ ahc_patch1_func, 241, 1, 2 },
-	{ ahc_patch0_func, 242, 2, 2 },
-	{ ahc_patch11_func, 243, 1, 1 },
-	{ ahc_patch8_func, 251, 33, 2 },
-	{ ahc_patch1_func, 267, 16, 1 },
-	{ ahc_patch12_func, 284, 14, 1 },
-	{ ahc_patch1_func, 298, 2, 2 },
-	{ ahc_patch0_func, 300, 3, 3 },
-	{ ahc_patch8_func, 300, 1, 2 },
-	{ ahc_patch0_func, 301, 2, 1 },
-	{ ahc_patch1_func, 305, 1, 2 },
-	{ ahc_patch0_func, 306, 1, 1 },
-	{ ahc_patch8_func, 310, 1, 1 },
-	{ ahc_patch8_func, 313, 2, 2 },
-	{ ahc_patch0_func, 315, 4, 1 },
-	{ ahc_patch12_func, 319, 1, 1 },
-	{ ahc_patch13_func, 322, 2, 3 },
-	{ ahc_patch8_func, 322, 1, 2 },
-	{ ahc_patch0_func, 323, 1, 1 },
-	{ ahc_patch1_func, 332, 40, 6 },
-	{ ahc_patch6_func, 341, 1, 1 },
-	{ ahc_patch7_func, 342, 1, 1 },
-	{ ahc_patch14_func, 344, 2, 1 },
-	{ ahc_patch15_func, 346, 5, 1 },
-	{ ahc_patch0_func, 372, 51, 15 },
-	{ ahc_patch12_func, 372, 1, 1 },
-	{ ahc_patch6_func, 374, 2, 2 },
-	{ ahc_patch16_func, 375, 1, 1 },
-	{ ahc_patch8_func, 378, 1, 1 },
-	{ ahc_patch17_func, 385, 1, 1 },
-	{ ahc_patch12_func, 390, 9, 3 },
-	{ ahc_patch8_func, 391, 3, 2 },
-	{ ahc_patch0_func, 394, 3, 1 },
-	{ ahc_patch8_func, 402, 6, 2 },
-	{ ahc_patch0_func, 408, 8, 1 },
-	{ ahc_patch12_func, 416, 1, 1 },
-	{ ahc_patch8_func, 418, 1, 2 },
-	{ ahc_patch0_func, 419, 1, 1 },
-	{ ahc_patch6_func, 422, 1, 1 },
-	{ ahc_patch6_func, 423, 1, 1 },
-	{ ahc_patch7_func, 424, 2, 1 },
-	{ ahc_patch8_func, 426, 1, 1 },
-	{ ahc_patch12_func, 427, 9, 4 },
-	{ ahc_patch8_func, 427, 1, 1 },
-	{ ahc_patch8_func, 434, 2, 1 },
-	{ ahc_patch0_func, 436, 4, 3 },
-	{ ahc_patch8_func, 436, 1, 2 },
-	{ ahc_patch0_func, 437, 3, 1 },
-	{ ahc_patch1_func, 441, 2, 1 },
-	{ ahc_patch6_func, 443, 5, 2 },
-	{ ahc_patch0_func, 448, 1, 1 },
-	{ ahc_patch7_func, 449, 113, 22 },
-	{ ahc_patch1_func, 450, 3, 2 },
-	{ ahc_patch0_func, 453, 5, 3 },
-	{ ahc_patch8_func, 453, 2, 2 },
-	{ ahc_patch0_func, 455, 3, 1 },
-	{ ahc_patch1_func, 460, 2, 2 },
-	{ ahc_patch0_func, 462, 6, 3 },
-	{ ahc_patch8_func, 462, 2, 2 },
-	{ ahc_patch0_func, 464, 3, 1 },
+	{ ahc_patch7_func, 133, 4, 1 },
+	{ ahc_patch7_func, 144, 80, 9 },
+	{ ahc_patch4_func, 162, 1, 1 },
+	{ ahc_patch1_func, 175, 1, 1 },
+	{ ahc_patch9_func, 183, 1, 2 },
+	{ ahc_patch0_func, 184, 1, 1 },
+	{ ahc_patch9_func, 193, 1, 2 },
+	{ ahc_patch0_func, 194, 1, 1 },
+	{ ahc_patch9_func, 210, 6, 2 },
+	{ ahc_patch0_func, 216, 6, 1 },
+	{ ahc_patch8_func, 224, 18, 2 },
+	{ ahc_patch1_func, 237, 1, 1 },
+	{ ahc_patch1_func, 244, 1, 2 },
+	{ ahc_patch0_func, 245, 2, 2 },
+	{ ahc_patch12_func, 246, 1, 1 },
+	{ ahc_patch9_func, 254, 33, 2 },
+	{ ahc_patch1_func, 270, 16, 1 },
+	{ ahc_patch13_func, 287, 14, 1 },
+	{ ahc_patch1_func, 301, 2, 2 },
+	{ ahc_patch0_func, 303, 3, 3 },
+	{ ahc_patch9_func, 303, 1, 2 },
+	{ ahc_patch0_func, 304, 2, 1 },
+	{ ahc_patch1_func, 308, 1, 2 },
+	{ ahc_patch0_func, 309, 1, 1 },
+	{ ahc_patch9_func, 313, 1, 1 },
+	{ ahc_patch9_func, 316, 2, 2 },
+	{ ahc_patch0_func, 318, 4, 1 },
+	{ ahc_patch13_func, 322, 1, 1 },
+	{ ahc_patch14_func, 325, 2, 3 },
+	{ ahc_patch9_func, 325, 1, 2 },
+	{ ahc_patch0_func, 326, 1, 1 },
+	{ ahc_patch6_func, 331, 1, 2 },
+	{ ahc_patch0_func, 332, 1, 1 },
+	{ ahc_patch1_func, 336, 45, 10 },
+	{ ahc_patch6_func, 345, 2, 4 },
+	{ ahc_patch7_func, 345, 1, 1 },
+	{ ahc_patch8_func, 346, 1, 1 },
+	{ ahc_patch0_func, 347, 1, 1 },
+	{ ahc_patch15_func, 348, 1, 1 },
+	{ ahc_patch6_func, 367, 6, 3 },
+	{ ahc_patch15_func, 367, 5, 1 },
+	{ ahc_patch0_func, 373, 5, 1 },
+	{ ahc_patch0_func, 381, 51, 15 },
+	{ ahc_patch13_func, 381, 1, 1 },
+	{ ahc_patch7_func, 383, 2, 2 },
+	{ ahc_patch16_func, 384, 1, 1 },
+	{ ahc_patch9_func, 387, 1, 1 },
+	{ ahc_patch17_func, 394, 1, 1 },
+	{ ahc_patch13_func, 399, 9, 3 },
+	{ ahc_patch9_func, 400, 3, 2 },
+	{ ahc_patch0_func, 403, 3, 1 },
+	{ ahc_patch9_func, 411, 6, 2 },
+	{ ahc_patch0_func, 417, 8, 1 },
+	{ ahc_patch13_func, 425, 1, 1 },
+	{ ahc_patch9_func, 427, 1, 2 },
+	{ ahc_patch0_func, 428, 1, 1 },
+	{ ahc_patch7_func, 431, 1, 1 },
+	{ ahc_patch7_func, 432, 1, 1 },
+	{ ahc_patch8_func, 433, 3, 3 },
+	{ ahc_patch6_func, 434, 1, 2 },
+	{ ahc_patch0_func, 435, 1, 1 },
+	{ ahc_patch9_func, 436, 1, 1 },
+	{ ahc_patch13_func, 437, 9, 4 },
+	{ ahc_patch9_func, 437, 1, 1 },
+	{ ahc_patch9_func, 444, 2, 1 },
+	{ ahc_patch0_func, 446, 4, 3 },
+	{ ahc_patch9_func, 446, 1, 2 },
+	{ ahc_patch0_func, 447, 3, 1 },
+	{ ahc_patch1_func, 451, 2, 1 },
+	{ ahc_patch7_func, 453, 5, 2 },
+	{ ahc_patch0_func, 458, 1, 1 },
+	{ ahc_patch8_func, 459, 107, 23 },
+	{ ahc_patch1_func, 460, 3, 2 },
+	{ ahc_patch0_func, 463, 5, 3 },
+	{ ahc_patch9_func, 463, 2, 2 },
+	{ ahc_patch0_func, 465, 3, 1 },
 	{ ahc_patch1_func, 470, 2, 2 },
-	{ ahc_patch0_func, 472, 9, 7 },
-	{ ahc_patch8_func, 472, 5, 6 },
-	{ ahc_patch18_func, 472, 1, 2 },
-	{ ahc_patch0_func, 473, 1, 1 },
-	{ ahc_patch18_func, 475, 1, 2 },
-	{ ahc_patch0_func, 476, 1, 1 },
-	{ ahc_patch0_func, 477, 4, 1 },
-	{ ahc_patch1_func, 486, 1, 1 },
-	{ ahc_patch2_func, 498, 2, 2 },
-	{ ahc_patch0_func, 500, 2, 2 },
-	{ ahc_patch19_func, 500, 2, 1 },
-	{ ahc_patch19_func, 536, 7, 1 },
-	{ ahc_patch3_func, 564, 1, 2 },
-	{ ahc_patch0_func, 565, 1, 1 },
-	{ ahc_patch20_func, 568, 1, 1 },
-	{ ahc_patch7_func, 570, 95, 26 },
-	{ ahc_patch4_func, 571, 1, 1 },
-	{ ahc_patch8_func, 578, 2, 2 },
-	{ ahc_patch0_func, 580, 3, 1 },
-	{ ahc_patch18_func, 587, 2, 2 },
-	{ ahc_patch0_func, 589, 1, 1 },
-	{ ahc_patch18_func, 593, 10, 3 },
-	{ ahc_patch5_func, 595, 8, 1 },
-	{ ahc_patch0_func, 603, 9, 2 },
-	{ ahc_patch5_func, 604, 8, 1 },
-	{ ahc_patch4_func, 614, 1, 2 },
-	{ ahc_patch0_func, 615, 1, 1 },
-	{ ahc_patch18_func, 616, 1, 2 },
-	{ ahc_patch0_func, 617, 3, 2 },
-	{ ahc_patch4_func, 619, 1, 1 },
-	{ ahc_patch5_func, 620, 1, 1 },
-	{ ahc_patch5_func, 623, 1, 1 },
-	{ ahc_patch5_func, 625, 1, 1 },
-	{ ahc_patch4_func, 627, 2, 2 },
-	{ ahc_patch0_func, 629, 2, 1 },
+	{ ahc_patch0_func, 472, 6, 3 },
+	{ ahc_patch9_func, 472, 2, 2 },
+	{ ahc_patch0_func, 474, 3, 1 },
+	{ ahc_patch1_func, 480, 2, 2 },
+	{ ahc_patch0_func, 482, 9, 7 },
+	{ ahc_patch9_func, 482, 5, 6 },
+	{ ahc_patch18_func, 482, 1, 2 },
+	{ ahc_patch0_func, 483, 1, 1 },
+	{ ahc_patch18_func, 485, 1, 2 },
+	{ ahc_patch0_func, 486, 1, 1 },
+	{ ahc_patch0_func, 487, 4, 1 },
+	{ ahc_patch6_func, 491, 3, 2 },
+	{ ahc_patch0_func, 494, 1, 1 },
+	{ ahc_patch1_func, 497, 1, 1 },
+	{ ahc_patch6_func, 502, 1, 2 },
+	{ ahc_patch0_func, 503, 1, 1 },
+	{ ahc_patch19_func, 540, 7, 1 },
+	{ ahc_patch3_func, 568, 1, 2 },
+	{ ahc_patch0_func, 569, 1, 1 },
+	{ ahc_patch20_func, 572, 1, 1 },
+	{ ahc_patch8_func, 574, 100, 31 },
+	{ ahc_patch4_func, 575, 1, 1 },
+	{ ahc_patch1_func, 581, 2, 2 },
+	{ ahc_patch0_func, 583, 1, 1 },
+	{ ahc_patch9_func, 584, 3, 3 },
+	{ ahc_patch14_func, 585, 1, 1 },
+	{ ahc_patch0_func, 587, 4, 1 },
+	{ ahc_patch18_func, 595, 2, 2 },
+	{ ahc_patch0_func, 597, 1, 1 },
+	{ ahc_patch18_func, 601, 10, 3 },
+	{ ahc_patch5_func, 603, 8, 1 },
+	{ ahc_patch0_func, 611, 9, 2 },
+	{ ahc_patch5_func, 612, 8, 1 },
+	{ ahc_patch4_func, 622, 1, 2 },
+	{ ahc_patch0_func, 623, 1, 1 },
+	{ ahc_patch18_func, 624, 1, 2 },
+	{ ahc_patch0_func, 625, 3, 2 },
+	{ ahc_patch4_func, 627, 1, 1 },
+	{ ahc_patch5_func, 628, 1, 1 },
 	{ ahc_patch5_func, 631, 1, 1 },
-	{ ahc_patch5_func, 634, 1, 1 },
-	{ ahc_patch5_func, 637, 1, 1 },
-	{ ahc_patch18_func, 641, 1, 1 },
-	{ ahc_patch18_func, 644, 1, 1 },
-	{ ahc_patch4_func, 650, 1, 1 },
-	{ ahc_patch6_func, 665, 16, 1 },
-	{ ahc_patch4_func, 683, 20, 1 },
-	{ ahc_patch8_func, 704, 4, 2 },
-	{ ahc_patch0_func, 708, 4, 1 },
-	{ ahc_patch8_func, 712, 4, 2 },
-	{ ahc_patch0_func, 716, 3, 1 },
-	{ ahc_patch21_func, 724, 14, 1 },
-	{ ahc_patch6_func, 738, 3, 1 },
-	{ ahc_patch8_func, 750, 24, 8 },
-	{ ahc_patch18_func, 754, 1, 2 },
-	{ ahc_patch0_func, 755, 1, 1 },
-	{ ahc_patch13_func, 760, 4, 2 },
-	{ ahc_patch0_func, 764, 7, 3 },
-	{ ahc_patch22_func, 764, 5, 2 },
-	{ ahc_patch0_func, 769, 2, 1 },
-	{ ahc_patch0_func, 774, 40, 3 },
-	{ ahc_patch17_func, 786, 16, 2 },
-	{ ahc_patch0_func, 802, 1, 1 },
-	{ ahc_patch4_func, 826, 1, 1 },
-	{ ahc_patch4_func, 827, 3, 2 },
-	{ ahc_patch0_func, 830, 1, 1 },
-	{ ahc_patch4_func, 831, 12, 1 }
+	{ ahc_patch5_func, 633, 1, 1 },
+	{ ahc_patch4_func, 635, 2, 2 },
+	{ ahc_patch0_func, 637, 2, 1 },
+	{ ahc_patch5_func, 639, 1, 1 },
+	{ ahc_patch5_func, 642, 1, 1 },
+	{ ahc_patch5_func, 645, 1, 1 },
+	{ ahc_patch18_func, 649, 1, 1 },
+	{ ahc_patch18_func, 652, 1, 1 },
+	{ ahc_patch4_func, 658, 1, 1 },
+	{ ahc_patch6_func, 661, 1, 2 },
+	{ ahc_patch0_func, 662, 1, 1 },
+	{ ahc_patch7_func, 674, 16, 1 },
+	{ ahc_patch4_func, 692, 20, 1 },
+	{ ahc_patch9_func, 713, 4, 2 },
+	{ ahc_patch0_func, 717, 4, 1 },
+	{ ahc_patch9_func, 721, 4, 2 },
+	{ ahc_patch0_func, 725, 3, 1 },
+	{ ahc_patch6_func, 731, 1, 1 },
+	{ ahc_patch21_func, 733, 14, 1 },
+	{ ahc_patch7_func, 747, 3, 1 },
+	{ ahc_patch9_func, 759, 24, 8 },
+	{ ahc_patch18_func, 763, 1, 2 },
+	{ ahc_patch0_func, 764, 1, 1 },
+	{ ahc_patch14_func, 769, 4, 2 },
+	{ ahc_patch0_func, 773, 7, 3 },
+	{ ahc_patch22_func, 773, 5, 2 },
+	{ ahc_patch0_func, 778, 2, 1 },
+	{ ahc_patch0_func, 783, 41, 3 },
+	{ ahc_patch17_func, 795, 17, 2 },
+	{ ahc_patch0_func, 812, 1, 1 },
+	{ ahc_patch4_func, 836, 1, 1 },
+	{ ahc_patch4_func, 837, 3, 2 },
+	{ ahc_patch0_func, 840, 1, 1 },
+	{ ahc_patch4_func, 841, 12, 1 }
 };
 struct cs {
 	u_int16_t	begin;
@@ -1229,11 +1255,11 @@
 } critical_sections[] = {
 	{ 11, 18 },
 	{ 21, 30 },
-	{ 683, 699 },
-	{ 827, 830 },
-	{ 831, 837 },
-	{ 839, 841 },
-	{ 841, 843 }
+	{ 692, 708 },
+	{ 837, 840 },
+	{ 841, 847 },
+	{ 849, 851 },
+	{ 851, 853 }
 };
 const int num_critical_sections = sizeof(critical_sections)
 				 / sizeof(*critical_sections);
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aicasm/Makefile linux/drivers/scsi/aic7xxx/aicasm/Makefile
--- v2.4.4/linux/drivers/scsi/aic7xxx/aicasm/Makefile	Tue Mar  6 22:44:16 2001
+++ linux/drivers/scsi/aic7xxx/aicasm/Makefile	Fri May  4 15:16:28 2001
@@ -2,17 +2,23 @@
 
 CSRCS=	aicasm.c aicasm_symbol.c
 GENSRCS= aicasm_gram.c aicasm_scan.c
-
-GENHDRS=	y.tab.h
+DEPHDRS= aicdb.h
+GENHDRS= y.tab.h aicdb.h
 
 SRCS=	${GENSRCS} ${CSRCS}
 CLEANFILES= ${GENSRCS} ${GENHDRS} y.output
 # Override default kernel CFLAGS.  This is a userland app.
-AICASM_CFLAGS:= -I/usr/include -ldb1
+AICASM_CFLAGS:= -I/usr/include -I. -ldb
 YFLAGS= -d
 
 NOMAN=	noman
 
+ifneq ($(HOSTCC),)
+AICASM_CC= $(HOSTCC)
+else
+AICASM_CC= $(CC)
+endif
+
 ifdef DEBUG
 CFLAGS+= -DDEBUG -g
 YFLAGS+= -t -v
@@ -21,8 +27,21 @@
 
 .SUFFIXES= .l .y .c
 
-$(PROG): $(SRCS)
-	$(HOSTCC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG)
+$(PROG): $(SRCS) $(DEPHDRS)
+	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG)
+
+aicdb.h:
+	@if [ -e "/usr/include/db3/db_185.h" ]; then		\
+		echo "#include <db3/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db2/db_185.h" ]; then		\
+		echo "#include <db2/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db/db_185.h" ]; then		\
+		echo "#include <db/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db_185.h" ]; then		\
+		echo "#include <db_185.h>" > aicdb.h;		\
+	 else							\
+		echo "*** Install db development libraries";	\
+	 fi
 
 clean:
 	rm -f $(CLEANFILES) $(PROG)
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c linux/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
--- v2.4.4/linux/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c	Fri May  4 15:16:28 2001
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: //depot/src/aic7xxx/aicasm/aicasm_symbol.c#4 $
+ * $Id: //depot/src/aic7xxx/aicasm/aicasm_symbol.c#5 $
  *
  * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_symbol.c,v 1.11 2000/09/22 22:19:54 gibbs Exp $
  */
@@ -36,7 +36,7 @@
 #include <sys/types.h>
 
 #ifdef __linux__
-#include <db1/db.h>
+#include "aicdb.h"
 #else
 #include <db.h>
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.4.4/linux/drivers/scsi/eata.c	Fri Feb 16 16:02:36 2001
+++ linux/drivers/scsi/eata.c	Sat May 19 17:43:06 2001
@@ -1,6 +1,10 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *       1 May 2001 Rev. 6.05 for linux 2.4.4
+ *        + Clean up all pci related routines.
+ *        + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d)
+ *
  *      30 Jan 2001 Rev. 6.04 for linux 2.4.1
  *        + Call pci_resource_start after pci_enable_device.
  *
@@ -828,77 +832,38 @@
    return FALSE;
 }
 
-static inline void tune_pci_port(unsigned long port_base) {
-
-#if defined(CONFIG_PCI)
-
-   unsigned int addr, k;
-   struct pci_dev *dev = NULL;
-
-   if (!pci_present()) return;
-
-   for (k = 0; k < MAX_PCI; k++) {
-
-      if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break;
-
-      if (pci_enable_device (dev)) continue;
-
-      addr = pci_resource_start (dev, 0);
-
-#if defined(DEBUG_PCI_DETECT)
-      printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n",
-             driver_name, dev->bus->number, dev->devfn, addr);
-#endif
-
-      if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) {
-         pci_set_master(dev);
-         return;
-         }
-
-      }
-
-#endif /* end CONFIG_PCI */
-
-   return;
-}
-
-static inline int
-            get_pci_irq(unsigned long port_base, unsigned char *apic_irq) {
+static inline struct pci_dev *get_pci_dev(unsigned long port_base) {
 
 #if defined(CONFIG_PCI)
 
    unsigned int addr;
    struct pci_dev *dev = NULL;
 
-   if (!pci_present()) return FALSE;
+   if (!pci_present()) return NULL;
 
    while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) {
-
-      if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;
+      addr = pci_resource_start (dev, 0);
 
 #if defined(DEBUG_PCI_DETECT)
-      printk("%s: get_pci_irq, bus %d, devfn 0x%x, addr 0x%x, apic_irq %u.\n",
-             driver_name, dev->bus->number, dev->devfn, addr, dev->irq);
+      printk("%s: get_pci_dev, bus %d, devfn 0x%x, addr 0x%x.\n",
+             driver_name, dev->bus->number, dev->devfn, addr);
 #endif
 
-      if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) {
-         *apic_irq = dev->irq;
-         return TRUE;
-         }
-
+      if (addr + PCI_BASE_ADDRESS_0 == port_base) return dev;
       }
 
 #endif /* end CONFIG_PCI */
 
-   return FALSE;
+   return NULL;
 }
 
 static inline int port_detect \
       (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {
    unsigned char irq, dma_channel, subversion, i;
-   unsigned char protocol_rev, apic_irq;
+   unsigned char protocol_rev;
    struct eata_info info;
    char *bus_type, dma_name[16], tag_type;
+   struct pci_dev *pdev;
 
    /* Allowed DMA channels for ISA (0 indicates reserved) */
    unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
@@ -1002,9 +967,11 @@
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
              name, irq);
 
-   if (get_pci_irq(port_base, &apic_irq) && (irq != apic_irq)) {
-      printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, apic_irq);
-      irq = apic_irq;
+   pdev = get_pci_dev(port_base);
+
+   if (pdev && (irq != pdev->irq)) {
+      printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, pdev->irq);
+      irq = pdev->irq;
       }
 
    /* Board detected, allocate its IRQ */
@@ -1064,10 +1031,6 @@
    sh[j]->can_queue = (ushort) ntohs(info.queue_size);
    sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;
    sh[j]->select_queue_depths = select_queue_depths;
-
-   /* Register the I/O space that we use */
-   request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name);
-
    memset(HD(j), 0, sizeof(struct hostdata));
    HD(j)->subversion = subversion;
    HD(j)->protocol_rev = protocol_rev;
@@ -1185,7 +1148,8 @@
              info.pci, info.eisa, info.raidnum);
 #endif
 
-   tune_pci_port(sh[j]->io_port);
+   if (pdev) pci_set_master(pdev);
+
    return TRUE;
 }
 
@@ -1254,19 +1218,26 @@
 
       if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break;
 
-      if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;
+      if (pci_enable_device (dev)) {
+
+#if defined(DEBUG_PCI_DETECT)
+         printk("%s: detect, bus %d, devfn 0x%x, pci_enable_device failed.\n",
+                driver_name, dev->bus->number, dev->devfn);
+#endif
+
+         continue;
+         }
+
+      addr = pci_resource_start (dev, 0);
 
 #if defined(DEBUG_PCI_DETECT)
       printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n",
              driver_name, k, dev->bus->number, dev->devfn, addr);
 #endif
 
-      if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
-             continue;
-
       /* Order addresses according to rev_scan value */
       io_port[MAX_INT_PARAM + (rev_scan ? (MAX_PCI - k) : (1 + k))] =
-             (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
+             addr + PCI_BASE_ADDRESS_0;
       }
 
 #endif /* end CONFIG_PCI */
@@ -1327,7 +1298,7 @@
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
       0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
-      0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
+      0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b, 0x5d
       };
 
    static const unsigned char data_none_cmds[] = {
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v2.4.4/linux/drivers/scsi/eata.h	Fri Feb 16 16:02:36 2001
+++ linux/drivers/scsi/eata.h	Sat May 19 17:43:06 2001
@@ -13,7 +13,7 @@
 int eata2x_reset(Scsi_Cmnd *);
 int eata2x_biosparam(Disk *, kdev_t, int *);
 
-#define EATA_VERSION "6.04.00"
+#define EATA_VERSION "6.05.00"
 
 #define EATA {                                                               \
                 name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.4.4/linux/drivers/scsi/fdomain.c	Fri Apr 27 13:59:18 2001
+++ linux/drivers/scsi/fdomain.c	Fri May  4 15:11:42 2001
@@ -587,9 +587,7 @@
 
 static void do_pause( unsigned amount )	/* Pause for amount*10 milliseconds */
 {
-   do {
-	udelay(10*1000);
-   } while (--amount);
+   mdelay(10*amount);
 }
 
 inline static void fdomain_make_bus_idle( void )
@@ -971,7 +969,7 @@
    	return 0;
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
-   scsi_set_pci_device(shpnt->pci_dev, pdev);
+   scsi_set_pci_device(shpnt, pdev);
    shpnt->n_io_port = 0x10;
    print_banner( shpnt );
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- v2.4.4/linux/drivers/scsi/gdth.c	Fri Apr 27 13:59:18 2001
+++ linux/drivers/scsi/gdth.c	Sat May 19 17:43:06 2001
@@ -2,7 +2,7 @@
  * GDT ISA/EISA/PCI Disk Array Controller driver for Linux              *
  *                                                                      *
  * gdth.c                                                               *
- * Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner *
+ * Copyright (C) 1995-01 ICP vortex Computersysteme GmbH, Achim Leubner *
  *                                                                      *
  * <achim@vortex.de>                                                    *
  *                                                                      *
@@ -20,9 +20,92 @@
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Tested with Linux 1.2.13, ..., 2.2.4                                 *
+ * Tested with Linux 1.2.13, ..., 2.2.18, ..., 2.4.2                    *
  *                                                                      *
  * $Log: gdth.c,v $
+ * Revision 1.49  2001/03/15 15:07:17  achim
+ * New __setup interface for boot command line options added
+ *
+ * Revision 1.48  2001/02/06 12:36:28  achim
+ * Bugfix Cluster protocol
+ *
+ * Revision 1.47  2001/01/10 14:42:06  achim
+ * New switch shared_access added
+ *
+ * Revision 1.46  2001/01/09 08:11:35  achim
+ * gdth_command() removed
+ * meaning of Scsi_Pointer members changed
+ *
+ * Revision 1.45  2000/11/16 12:02:24  achim
+ * Changes for kernel 2.4
+ *
+ * Revision 1.44  2000/10/11 08:44:10  achim
+ * Clustering changes: New flag media_changed added
+ *
+ * Revision 1.43  2000/09/20 12:59:01  achim
+ * DPMEM remap functions for all PCI controller types implemented
+ * Small changes for ia64 platform
+ *
+ * Revision 1.42  2000/07/20 09:04:50  achim
+ * Small changes for kernel 2.4
+ *
+ * Revision 1.41  2000/07/04 14:11:11  achim
+ * gdth_analyse_hdrive() added to rescan drives after online expansion
+ *
+ * Revision 1.40  2000/06/27 11:24:16  achim
+ * Changes Clustering, Screenservice
+ *
+ * Revision 1.39  2000/06/15 13:09:04  achim
+ * Changes for gdth_do_cmd()
+ *
+ * Revision 1.38  2000/06/15 12:08:43  achim
+ * Bugfix gdth_sync_event(), service SCREENSERVICE
+ * Data direction for command 0xc2 changed to DOU
+ *
+ * Revision 1.37  2000/05/25 13:50:10  achim
+ * New driver parameter virt_ctr added
+ *
+ * Revision 1.36  2000/05/04 08:50:46  achim
+ * Event buffer now in gdth_ha_str
+ *
+ * Revision 1.35  2000/03/03 10:44:08  achim
+ * New event_string only valid for the RP controller family
+ *
+ * Revision 1.34  2000/03/02 14:55:29  achim
+ * New mechanism for async. event handling implemented
+ *
+ * Revision 1.33  2000/02/21 15:37:37  achim
+ * Bugfix Alpha platform + DPMEM above 4GB
+ *
+ * Revision 1.32  2000/02/14 16:17:37  achim
+ * Bugfix sense_buffer[] + raw devices
+ *
+ * Revision 1.31  2000/02/10 10:29:00  achim
+ * Delete sense_buffer[0], if command OK
+ *
+ * Revision 1.30  1999/11/02 13:42:39  achim
+ * ARRAY_DRV_LIST2 implemented
+ * Now 255 log. and 100 host drives supported
+ *
+ * Revision 1.29  1999/10/05 13:28:47  achim
+ * GDT_CLUST_RESET added
+ *
+ * Revision 1.28  1999/08/12 13:44:54  achim
+ * MOUNTALL removed
+ * Cluster drives -> removeable drives
+ *
+ * Revision 1.27  1999/06/22 07:22:38  achim
+ * Small changes
+ *
+ * Revision 1.26  1999/06/10 16:09:12  achim
+ * Cluster Host Drive support: Bugfixes
+ *
+ * Revision 1.25  1999/06/01 16:03:56  achim
+ * gdth_init_pci(): Manipulate config. space to start RP controller
+ *
+ * Revision 1.24  1999/05/26 11:53:06  achim
+ * Cluster Host Drive support added
+ *
  * Revision 1.23  1999/03/26 09:12:31  achim
  * Default value for hdr_channel set to 0
  *
@@ -120,7 +203,7 @@
  * Initial revision
  *
  ************************************************************************/
-#ident "$Id: gdth.c,v 1.23 1999/03/26 09:12:31 achim Exp $" 
+#ident "$Id: gdth.c,v 1.49 2001/03/15 15:07:17 achim Exp $" 
 
 /* All GDT Disk Array Controllers are fully supported by this driver.
  * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -147,10 +230,17 @@
  * max_ids:x                    x - target ID count per channel (1..MAXID)
  * rescan:Y                     rescan all channels/IDs 
  * rescan:N                     use all devices found until now
+ * virt_ctr:Y                   map every channel to a virtual controller 
+ * virt_ctr:N                   use multi channel support 
  * hdr_channel:x                x - number of virtual bus for host drives
+ * shared_access:Y              disable driver reserve/release protocol to 
+ *                              access a shared resource from several nodes, 
+ *                              appropiate controller firmware required
+ * shared_access:N              enable driver reserve/release protocol
  *
- * The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
- *                        max_ids:127,rescan:N,hdr_channel:0".
+ * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
+ *                          max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0,
+ *                          shared_access:N".
  * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
  * 
  * When loading the gdth driver as a module, the same options are available. 
@@ -160,10 +250,22 @@
  * '1' in place of 'Y' and '0' in place of 'N'.
  * 
  * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
- *                         max_ids=127 rescan=0 hdr_channel=0"
+ *           max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0"
  * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
  */
 
+/* The meaning of the Scsi_Pointer members in this driver is as follows:
+ * ptr:                         Chaining
+ * this_residual:               Command priority
+ * buffer:                      Unused
+ * buffers_residual:            Timeout value
+ * Status:                      Command status (gdth_do_cmd())
+ * Message:                     Additional info (gdth_do_cmd())
+ * have_data_in:                Flag for gdth_wait_completion()
+ * sent_command:                Opcode special command
+ * phase:                       Service/parameter/return code special command
+ */
+
 #ifdef MODULE
 #include <linux/module.h>
 #endif
@@ -181,13 +283,32 @@
 #include <linux/proc_fs.h>
 #include <linux/time.h>
 #include <linux/timer.h>
+#ifdef GDTH_RTC
+#include <linux/mc146818rtc.h>
+#endif
+#if LINUX_VERSION_CODE >= 0x020100
 #include <linux/reboot.h>
+#else
+#include <linux/bios32.h>
+#endif
+#if LINUX_VERSION_CODE >= 0x020126
+#include <linux/init.h>
+#endif
 
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#if LINUX_VERSION_CODE >= 0x020322
 #include <linux/spinlock.h>
+#elif LINUX_VERSION_CODE >= 0x02015F
+#include <asm/spinlock.h>
+#endif
+
+#if LINUX_VERSION_CODE >= 0x010300
 #include <linux/blk.h>
+#else
+#include "../block/blk.h"
+#endif
 #include "scsi.h"
 #include "hosts.h"
 #include "sd.h"
@@ -196,9 +317,13 @@
 
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs);
+#if LINUX_VERSION_CODE >= 0x010346
 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
+#else
+static void gdth_interrupt(int irq,struct pt_regs *regs);
+#endif
 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
-static int gdth_async_event(int hanum,int service);
+static int gdth_async_event(int hanum);
 static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
 
 static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
@@ -233,19 +358,25 @@
 static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
                              ulong32 p2,ulong32 p3);
 static int gdth_search_drives(int hanum);
+static int gdth_analyse_hdrive(int hanum, ushort hdrive);
 
 static void *gdth_mmap(ulong paddr, ulong size);
 static void gdth_munmap(void *addr);
 
 static const char *gdth_ctr_name(int hanum);
 
+#if LINUX_VERSION_CODE >= 0x010300
 static void gdth_flush(int hanum);
+#if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
+#else
+static int halt_called = FALSE;
+void gdth_halt(void);
+#endif
+#endif
 
 #ifdef DEBUG_GDTH
 static unchar   DebugState = DEBUG_GDTH;
-extern long sys_syslog(int,char*,int);
-#define LOGEN sys_syslog(7,NULL,0)
 
 #ifdef __SERIAL__
 #define MAX_SERBUF 160
@@ -314,9 +445,9 @@
 #define TRACE3(a)   {if (DebugState!=0) {ser_printk a;}}
 
 #else /* !__SERIAL__ */
-#define TRACE(a)    {if (DebugState==1) {LOGEN;printk a;}}
-#define TRACE2(a)   {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}}
-#define TRACE3(a)   {if (DebugState!=0) {LOGEN;printk a;}}
+#define TRACE(a)    {if (DebugState==1) {printk a;}}
+#define TRACE2(a)   {if (DebugState==1 || DebugState==2) {printk a;}}
+#define TRACE3(a)   {if (DebugState!=0) {printk a;}}
 #endif
 
 #else /* !DEBUG */
@@ -341,6 +472,64 @@
 
 #define BUS_L2P(a,b)    ((b)>(a)->virt_bus ? (b-1):(b))
 
+#if LINUX_VERSION_CODE < 0x010300
+static void *gdth_mmap(ulong paddr, ulong size) 
+{
+    if (paddr >= high_memory)
+        return NULL; 
+    else
+        return (void *)paddr;
+}
+static void gdth_munmap(void *addr) 
+{
+}
+inline ulong32 virt_to_phys(volatile void *addr)
+{
+    return (ulong32)addr;
+}
+inline void *phys_to_virt(ulong32 addr)
+{
+    return (void *)addr;
+}
+#define virt_to_bus             virt_to_phys
+#define bus_to_virt             phys_to_virt
+#define gdth_readb(addr)        (*(volatile unchar *)(addr))
+#define gdth_readw(addr)        (*(volatile ushort *)(addr))
+#define gdth_readl(addr)        (*(volatile ulong32 *)(addr))
+#define gdth_writeb(b,addr)     (*(volatile unchar *)(addr) = (b))
+#define gdth_writew(b,addr)     (*(volatile ushort *)(addr) = (b))
+#define gdth_writel(b,addr)     (*(volatile ulong32 *)(addr) = (b))
+#define memset_io(a,b,c)        memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)    memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)      memcpy((void *)(a),(b),(c))
+
+#define PCI_SLOT(devfn)         ((devfn >> 3) & 0x1f)
+
+#elif LINUX_VERSION_CODE < 0x020100
+static int remapped = FALSE;
+static void *gdth_mmap(ulong paddr, ulong size) 
+{
+    if ( paddr >= high_memory) {
+        remapped = TRUE;
+        return vremap(paddr, size);
+    } else {
+        return (void *)paddr; 
+    }
+}
+static void gdth_munmap(void *addr) 
+{
+    if (remapped)
+        vfree(addr);
+    remapped = FALSE;
+}
+#define gdth_readb(addr)        readb((ulong)(addr))
+#define gdth_readw(addr)        readw((ulong)(addr))
+#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
+#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
+#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
+#define gdth_writel(b,addr)     writel((ulong32)(b),(ulong)(addr))
+
+#else
 static void *gdth_mmap(ulong paddr, ulong size) 
 { 
     return ioremap(paddr, size); 
@@ -354,7 +543,9 @@
 #define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
 #define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
 #define gdth_writew(b,addr)     writew((b),(ulong)(addr))
-#define gdth_writel(b,addr)     writel((b),(ulong)(addr))
+#define gdth_writel(b,addr)     writel((ulong32)(b),(ulong)(addr))
+#endif
+
 
 static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
 static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
@@ -388,15 +579,24 @@
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
     DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-    DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
+    DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
 };
 
 /* __initfunc, __initdata macros */
-#include <linux/init.h>
+#if LINUX_VERSION_CODE >= 0x020322
+#define GDTH_INITFUNC(type, func)       type __init func 
+#elif LINUX_VERSION_CODE >= 0x020126
+#define GDTH_INITFUNC(type, func)       __initfunc(type func)
+#else
+#define GDTH_INITFUNC(type, func)       type func
+#define __initdata
+#define __init
+#endif
 
+#if LINUX_VERSION_CODE >= 0x02015F
 #define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
 #define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
 #define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
@@ -405,6 +605,16 @@
 #define GDTH_UNLOCK_SCSI_DONE(flags)    spin_unlock_irqrestore(&io_request_lock,flags)
 #define GDTH_LOCK_SCSI_DOCMD()          spin_lock_irq(&io_request_lock)
 #define GDTH_UNLOCK_SCSI_DOCMD()        spin_unlock_irq(&io_request_lock)
+#else
+#define GDTH_INIT_LOCK_HA(ha)           do {} while (0)
+#define GDTH_LOCK_HA(ha,flags)          do {save_flags(flags); cli();} while (0)
+#define GDTH_UNLOCK_HA(ha,flags)        do {restore_flags(flags);} while (0)
+
+#define GDTH_LOCK_SCSI_DONE(flags)      do {} while (0)
+#define GDTH_UNLOCK_SCSI_DONE(flags)    do {} while (0)
+#define GDTH_LOCK_SCSI_DOCMD()          do {} while (0)
+#define GDTH_UNLOCK_SCSI_DOCMD()        do {} while (0)
+#endif
 
 /* LILO and modprobe/insmod parameters */
 /* IRQ list for GDT3000/3020 EISA controllers */
@@ -428,8 +638,13 @@
 static int max_ids = MAXID;
 /* rescan all IDs */
 static int rescan = 0;
+/* map channels to virtual controllers */
+static int virt_ctr = 0;
+/* shared access */
+static int shared_access = 0;
 
 #ifdef MODULE
+#if LINUX_VERSION_CODE >= 0x02011A
 /* parameters for modprobe/insmod */
 MODULE_PARM(irq, "i");
 MODULE_PARM(disable, "i");
@@ -439,25 +654,45 @@
 MODULE_PARM(hdr_channel, "i");
 MODULE_PARM(max_ids, "i");
 MODULE_PARM(rescan, "i");
+MODULE_PARM(virt_ctr, "i");
+MODULE_PARM(shared_access, "i");
 MODULE_AUTHOR("Achim Leubner");
 #endif
+#endif
 
 /* /proc support */
+#if LINUX_VERSION_CODE >= 0x010300
 #include <linux/stat.h> 
+#if LINUX_VERSION_CODE < 0x020322
+struct proc_dir_entry proc_scsi_gdth = {
+    PROC_SCSI_GDTH, 4, "gdth",
+    S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+#endif
 #include "gdth_proc.h"
 #include "gdth_proc.c"
+#endif
 
+#if LINUX_VERSION_CODE >= 0x020100
 /* notifier block to get a notify on system shutdown/halt/reboot */
 static struct notifier_block gdth_notifier = {
     gdth_halt, NULL, 0
 };
+#endif
+
 
 static void gdth_delay(int milliseconds)
 {
     if (milliseconds == 0) {
         udelay(1);
     } else {
+#if LINUX_VERSION_CODE >= 0x020168
         mdelay(milliseconds);
+#else
+        int i;
+        for (i = 0; i < milliseconds; ++i) 
+            udelay(1000);
+#endif
     }
 }
 
@@ -465,24 +700,24 @@
 {
     *cyls = size /HEADS/SECS;
     if (*cyls <= MAXCYLS) {
-	*heads = HEADS;
-	*secs = SECS;
-    } else {                            		/* too high for 64*32 */
-	*cyls = size /MEDHEADS/MEDSECS;
-	if (*cyls <= MAXCYLS) {
-	    *heads = MEDHEADS;
-	    *secs = MEDSECS;
-	} else {                        		/* too high for 127*63 */
-	    *cyls = size /BIGHEADS/BIGSECS;
-	    *heads = BIGHEADS;
-	    *secs = BIGSECS;
-	}
+        *heads = HEADS;
+        *secs = SECS;
+    } else {                                        /* too high for 64*32 */
+        *cyls = size /MEDHEADS/MEDSECS;
+        if (*cyls <= MAXCYLS) {
+            *heads = MEDHEADS;
+            *secs = MEDSECS;
+        } else {                                    /* too high for 127*63 */
+            *cyls = size /BIGHEADS/BIGSECS;
+            *heads = BIGHEADS;
+            *secs = BIGSECS;
+        }
     }
 }
 
 /* controller search and initialization functions */
 
-static int __init gdth_search_eisa(ushort eisa_adr)
+GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
 {
     ulong32 id;
     
@@ -500,7 +735,7 @@
 }
 
 
-static int __init gdth_search_isa(ulong32 bios_adr)
+GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
 {
     void *addr;
     ulong32 id;
@@ -516,11 +751,16 @@
 }
 
 
-static int __init gdth_search_pci(gdth_pci_str *pcistr)
+GDTH_INITFUNC(static int, gdth_search_pci(gdth_pci_str *pcistr))
 {
-    ulong32 base0, base1, base2;
+    ulong base0, base1, base2;
     ushort device_id, cnt;
+#if LINUX_VERSION_CODE >= 0x2015C
     struct pci_dev *pdev;
+#else
+    int error;
+    ushort idx;
+#endif
     
     TRACE(("gdth_search_pci()\n"));
 
@@ -530,11 +770,46 @@
         if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
             device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
             continue;
+#if LINUX_VERSION_CODE >= 0x20363
+        pdev = NULL;
+        while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) 
+               != NULL) {
+            if (pci_enable_device(pdev))
+                continue;
+            if (cnt >= MAXHA)
+                return cnt;
+            /* GDT PCI controller found, resources are already in pdev */
+            pcistr[cnt].pdev = pdev;
+            pcistr[cnt].device_id = device_id;
+            pcistr[cnt].bus = pdev->bus->number;
+            pcistr[cnt].device_fn = pdev->devfn;
+            pcistr[cnt].irq = pdev->irq;
+            base0 = pci_resource_flags(pdev, 0);
+            base1 = pci_resource_flags(pdev, 1);
+            base2 = pci_resource_flags(pdev, 2);
+            if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
+                device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
+                if (!(base0 & IORESOURCE_MEM)) 
+                    continue;
+                pcistr[cnt].dpmem = pci_resource_start(pdev, 0);
+            } else {                                  /* GDT6110, GDT6120, .. */
+                if (!(base0 & IORESOURCE_MEM) ||
+                    !(base2 & IORESOURCE_MEM) ||
+                    !(base1 & IORESOURCE_IO)) 
+                    continue;
+                pcistr[cnt].dpmem = pci_resource_start(pdev, 2);
+                pcistr[cnt].io_mm = pci_resource_start(pdev, 0);
+                pcistr[cnt].io    = pci_resource_start(pdev, 1);
+            }
+            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
+                    pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
+                    pcistr[cnt].irq, pcistr[cnt].dpmem));
+            cnt++;
+        }       
+#elif LINUX_VERSION_CODE >= 0x2015C
         pdev = NULL;
         while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) 
                != NULL) {
-	    if (pci_enable_device(pdev))
-	    	continue;
             if (cnt >= MAXHA)
                 return cnt;
             /* GDT PCI controller found, resources are already in pdev */
@@ -543,16 +818,16 @@
             pcistr[cnt].bus = pdev->bus->number;
             pcistr[cnt].device_fn = pdev->devfn;
             pcistr[cnt].irq = pdev->irq;
-            base0 = pdev->resource[0].flags;
-            base1 = pdev->resource[1].flags;
-            base2 = pdev->resource[2].flags;
+            base0 = pdev->base_address[0];
+            base1 = pdev->base_address[1];
+            base2 = pdev->base_address[2];
             if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
                 device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
                 if ((base0 & PCI_BASE_ADDRESS_SPACE) != 
                     PCI_BASE_ADDRESS_SPACE_MEMORY)
                     continue;
-                pcistr[cnt].dpmem = pdev->resource[0].start;
-            } else {                                    /* GDT6110, GDT6120, .. */
+                pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+            } else {                                  /* GDT6110, GDT6120, .. */
                 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
                     PCI_BASE_ADDRESS_SPACE_MEMORY ||
                     (base2 & PCI_BASE_ADDRESS_SPACE) !=
@@ -560,21 +835,77 @@
                     (base1 & PCI_BASE_ADDRESS_SPACE) !=
                     PCI_BASE_ADDRESS_SPACE_IO)
                     continue;
-                pcistr[cnt].dpmem = pdev->resource[2].start;
-                pcistr[cnt].io_mm = pdev->resource[0].start;
-                pcistr[cnt].io    = pdev->resource[1].start;
+                pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
             }
-            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
+            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
                     pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
                     pcistr[cnt].irq, pcistr[cnt].dpmem));
             cnt++;
         }       
+#else   
+        idx = 0;
+        while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++,
+                                    &pcistr[cnt].bus,&pcistr[cnt].device_fn)) {
+            if (cnt >= MAXHA)
+                return cnt;
+            /* GDT PCI ctr. found, now read resources from config space */
+#if LINUX_VERSION_CODE >= 0x010300
+#define GDTH_BASEP      (int *)
+#else
+#define GDTH_BASEP
+#endif
+            if ((error = pcibios_read_config_dword(pcistr[cnt].bus,
+                                                   pcistr[cnt].device_fn,
+                                                   PCI_BASE_ADDRESS_0,
+                                                   GDTH_BASEP&base0)) ||
+                (error = pcibios_read_config_dword(pcistr[cnt].bus,
+                                                   pcistr[cnt].device_fn,
+                                                   PCI_BASE_ADDRESS_1,
+                                                   GDTH_BASEP&base1)) ||
+                (error = pcibios_read_config_dword(pcistr[cnt].bus,
+                                                   pcistr[cnt].device_fn,
+                                                   PCI_BASE_ADDRESS_2,
+                                                   GDTH_BASEP&base2)) ||
+                (error = pcibios_read_config_byte(pcistr[cnt].bus,
+                                                  pcistr[cnt].device_fn,
+                                                  PCI_INTERRUPT_LINE,
+                                                  &pcistr[cnt].irq))) {
+                printk("GDT-PCI: error %d reading configuration space", error);
+                continue;
+            }
+            pcistr[cnt].device_id = device_id;
+            if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
+                device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
+                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY)
+                    continue;
+                pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+            } else {                                    /* GDT6110, GDT6120, .. */
+                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
+                    (base2 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
+                    (base1 & PCI_BASE_ADDRESS_SPACE) !=
+                    PCI_BASE_ADDRESS_SPACE_IO)
+                    continue;
+                pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
+            }
+            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
+                    pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
+                    pcistr[cnt].irq, pcistr[cnt].dpmem));
+            cnt++;
+        }
+#endif
     }   
     return cnt;
 }
 
 
-static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
+GDTH_INITFUNC(static void, gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
 {    
     gdth_pci_str temp;
     int i, changed;
@@ -612,7 +943,7 @@
 }
 
 
-static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
+GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
 {
     ulong32 retries,id;
     unchar prot_ver,eisacf,i,irq_found;
@@ -701,7 +1032,7 @@
 }
 
        
-static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
+GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
 {
     register gdt2_dpram_str *dp2_ptr;
     int i;
@@ -798,14 +1129,18 @@
 }
 
 
-static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
 {
     register gdt6_dpram_str *dp6_ptr;
     register gdt6c_dpram_str *dp6c_ptr;
     register gdt6m_dpram_str *dp6m_ptr;
     ulong32 retries;
     unchar prot_ver;
+    ushort command;
     int i, found = FALSE;
+#if LINUX_VERSION_CODE < 0x2015C
+    int rom_addr;
+#endif
 
     TRACE(("gdth_init_pci()\n"));
 
@@ -820,8 +1155,51 @@
             printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
             return 0;
         }
+        /* check and reset interface area */
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        /* reset interface area */
+        gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
+        if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_old() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_0, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_0, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6_ptr = (gdt6_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
+                if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
+        }
         memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
         if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
@@ -890,8 +1268,51 @@
             gdth_munmap(ha->brd);
             return 0;
         }
+        /* check and reset interface area */
         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
-        /* reset interface area */
+        gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
+        if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_plx() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_2, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_2, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
+                if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
+        }
         memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
         if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
@@ -961,12 +1382,53 @@
             return 0;
         }
 
+        /* manipulate config. space to enable DPMEM, start RP controller */
+#if LINUX_VERSION_CODE >= 0x20363
+        pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
+        command |= 6;
+        pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
+        if (pci_resource_start(pcistr->pdev, 8) == 1UL)
+            pci_resource_start(pcistr->pdev, 8) = 0UL;
+        i = 0xFEFF0001UL;
+        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
+        gdth_delay(1);
+        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
+                               pci_resource_start(pcistr->pdev, 8));
+#elif LINUX_VERSION_CODE >= 0x2015C
+        pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
+        command |= 6;
+        pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
+        if (pcistr->pdev->rom_address == 1UL)
+            pcistr->pdev->rom_address = 0UL;
+        i = 0xFEFF0001UL;
+        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
+        gdth_delay(1);
+        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
+                               pcistr->pdev->rom_address);
+#else
+        pcibios_read_config_word(pcistr->bus, pcistr->device_fn,
+                                 PCI_COMMAND, &command);
+        command |= 6;
+        pcibios_write_config_word(pcistr->bus, pcistr->device_fn, 
+                                  PCI_COMMAND, command);
+        pcibios_read_config_dword(pcistr->bus, pcistr->device_fn,
+                                  PCI_ROM_ADDRESS, &rom_addr);
+        if (rom_addr == 1UL)
+            rom_addr = 0UL;
+        i = 0xFEFF0001UL;
+        pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                   PCI_ROM_ADDRESS, i);
+        gdth_delay(1);
+        pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                   PCI_ROM_ADDRESS, rom_addr);
+#endif
+        
         /* check and reset interface area */
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
         if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
-            printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n", 
-                   (int)pcistr->dpmem);
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
             found = FALSE;
             for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
                 gdth_munmap(ha->brd);
@@ -980,8 +1442,13 @@
                     continue;
                 }
                 gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
                 pci_write_config_dword(pcistr->pdev, 
                                        PCI_BASE_ADDRESS_0, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_0, i);
+#endif
                 ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1060,7 +1527,7 @@
 
 /* controller protocol functions */
 
-static void __init gdth_enable_int(int hanum)
+GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
 {
     gdth_ha_str *ha;
     ulong flags;
@@ -1312,7 +1779,11 @@
 
     gdth_from_wait = TRUE;
     do {
+#if LINUX_VERSION_CODE >= 0x010346
         gdth_interrupt((int)ha->irq,ha,NULL);
+#else
+        gdth_interrupt((int)ha->irq,NULL);
+#endif
         if (wait_hanum==hanum && wait_index==index) {
             answer_found = TRUE;
             break;
@@ -1367,6 +1838,12 @@
             cmd_ptr->u.raw.bus        = (unchar)p2;
             cmd_ptr->u.raw.target     = (unchar)p3;
             cmd_ptr->u.raw.lun        = (unchar)(p3 >> 8);
+        } else if (service == SCREENSERVICE) {
+            if (opcode == GDT_REALTIME) {
+                *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1;
+                *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = p2;
+                *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = p3;
+            }
         }
         ha->cmd_len          = sizeof(gdth_cmd_str);
         ha->cmd_offs_dpmem   = 0;
@@ -1389,19 +1866,22 @@
 
 /* search for devices */
 
-static int __init gdth_search_drives(int hanum)
+GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
 {
     register gdth_ha_str *ha;
     ushort cdev_cnt, i;
-    int drv_cyls, drv_hds, drv_secs;
-    ulong32 bus_no;
-    ulong32 drv_cnt, drv_no, j;
+    ulong32 bus_no, drv_cnt, drv_no, j;
     gdth_getch_str *chn;
     gdth_drlist_str *drl;
     gdth_iochan_str *ioc;
     gdth_raw_iochan_str *iocr;
-    gdth_arraylist_str *alst;
-        
+    gdth_arcdl_str *alst;
+    gdth_alist_str *alst2;
+#ifdef GDTH_RTC
+    unchar rtc[12];
+    ulong flags;
+#endif     
+   
     TRACE(("gdth_search_drives() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
@@ -1412,7 +1892,30 @@
         return 0;
     }
     TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
-    
+
+#ifdef GDTH_RTC
+    /* read realtime clock info, send to controller */
+    /* 1. wait for the falling edge of update flag */
+    spin_lock_irqsave(&rtc_lock, flags);
+    for (j = 0; j < 1000000; ++j)
+        if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+            break;
+    for (j = 0; j < 1000000; ++j)
+        if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+            break;
+    /* 2. read info */
+    do {
+        for (j = 0; j < 12; ++j) 
+            rtc[j] = CMOS_READ(j);
+    } while (rtc[0] != CMOS_READ(0));
+    spin_lock_irqrestore(&rtc_lock, flags);
+    TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0],
+            *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]));
+    /* 3. send to controller firmware */
+    gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0],
+                      *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]);
+#endif   
+ 
     /* initialize cache service */
     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
         printk("GDT: Initialization error cache service (code %d)\n",
@@ -1421,19 +1924,7 @@
     }
     TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
     cdev_cnt = (ushort)ha->info;
-
-    /* mount all cache devices */
-    gdth_internal_cmd(hanum,CACHESERVICE,GDT_MOUNT,0xffff,1,0);
-    TRACE2(("gdth_search_drives(): mountall CACHESERVICE OK\n"));
-
-    /* initialize cache service after mountall */
-    if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
-        printk("GDT: Initialization error cache service (code %d)\n",
-               ha->status);
-        return 0;
-    }
-    TRACE2(("gdth_search_drives() CACHES. init. after mountall\n"));
-    cdev_cnt = (ushort)ha->info;
+    ha->fw_vers = ha->service;
 
     /* detect number of buses - try new IOCTL */
     iocr = (gdth_raw_iochan_str *)ha->pscratch;
@@ -1493,7 +1984,8 @@
     ha->more_proc = FALSE;
     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
                           INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
-        memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch, sizeof(gdth_binfo_str));
+        memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch,
+               sizeof(gdth_binfo_str));
         if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES,
                               INVALID_CHANNEL,sizeof(gdth_bfeat_str))) {
             TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n"));
@@ -1562,22 +2054,37 @@
                                   INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) {
                 for (j = 0; j < drv_cnt; ++j) {
                     drv_no = ((ulong32 *)ha->pscratch)[j];
-                    if (drv_no < MAX_HDRIVES) {
+                    if (drv_no < MAX_LDRIVES) {
                         ha->hdr[drv_no].is_logdrv = TRUE;
                         TRACE2(("Drive %d is log. drive\n",drv_no));
                     }
                 }
             }
+            alst = (gdth_arcdl_str *)ha->pscratch;
+            alst->entries_avail = MAX_LDRIVES;
+            alst->first_entry = 0;
+            alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]);
             if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
-                                  ARRAY_DRV_LIST | LA_CTRL_PATTERN,
-                                  0, 35 * sizeof(gdth_arraylist_str))) {
+                                  ARRAY_DRV_LIST2 | LA_CTRL_PATTERN, 
+                                  INVALID_CHANNEL, sizeof(gdth_arcdl_str) +
+                                  (alst->entries_avail-1) * sizeof(gdth_alist_str))) { 
+                for (j = 0; j < alst->entries_init; ++j) {
+                    ha->hdr[j].is_arraydrv = alst->list[j].is_arrayd;
+                    ha->hdr[j].is_master = alst->list[j].is_master;
+                    ha->hdr[j].is_parity = alst->list[j].is_parity;
+                    ha->hdr[j].is_hotfix = alst->list[j].is_hotfix;
+                    ha->hdr[j].master_no = alst->list[j].cd_handle;
+                }
+            } else if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+                                         ARRAY_DRV_LIST | LA_CTRL_PATTERN,
+                                         0, 35 * sizeof(gdth_alist_str))) {
                 for (j = 0; j < 35; ++j) {
-                    alst = &((gdth_arraylist_str *)ha->pscratch)[j];
-                    ha->hdr[j].is_arraydrv = alst->is_arrayd;
-                    ha->hdr[j].is_master = alst->is_master;
-                    ha->hdr[j].is_parity = alst->is_parity;
-                    ha->hdr[j].is_hotfix = alst->is_hotfix;
-                    ha->hdr[j].master_no = alst->cd_handle;
+                    alst2 = &((gdth_alist_str *)ha->pscratch)[j];
+                    ha->hdr[j].is_arraydrv = alst2->is_arrayd;
+                    ha->hdr[j].is_master = alst2->is_master;
+                    ha->hdr[j].is_parity = alst2->is_parity;
+                    ha->hdr[j].is_hotfix = alst2->is_hotfix;
+                    ha->hdr[j].master_no = alst2->cd_handle;
                 }
             }
         }
@@ -1592,7 +2099,6 @@
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
 
     /* set/get features raw service (scatter/gather) */
-    ha->raw_feat = 0;
     if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
                           0,0)) {
         TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
@@ -1636,44 +2142,67 @@
         }
     }
 
-    /* scanning for cache devices */
-    for (i=0; i<cdev_cnt && i<MAX_HDRIVES; ++i) {
-        TRACE(("gdth_search_drives() cachedev. %d\n",i));
-        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,i,0,0)) {
-            /* static relation between host drive number and Bus/ID */
-            TRACE(("gdth_search_dr() drive %d mapped to bus/id %d/%d\n",
-                   i,ha->bus_cnt,i));
-
-            ha->hdr[i].present = TRUE;
-            ha->hdr[i].size = ha->info;
-
-            /* evaluate mapping (sectors per head, heads per cylinder) */
-            ha->hdr[i].size &= ~SECS32;
-            if (ha->info2 == 0) {
-		gdth_eval_mapping(ha->hdr[i].size,&drv_cyls,&drv_hds,&drv_secs);
-            } else {
-                drv_hds = ha->info2 & 0xff;
-                drv_secs = (ha->info2 >> 8) & 0xff;
-                drv_cyls = ha->hdr[i].size /drv_hds/drv_secs;
-            }
-            ha->hdr[i].heads = (unchar)drv_hds;
-            ha->hdr[i].secs  = (unchar)drv_secs;
-            /* round size */
-            ha->hdr[i].size  = drv_cyls * drv_hds * drv_secs;
-            TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
-                   i,ha->hdr[i].size,drv_hds,drv_secs));
+    /* scanning for host drives */
+    for (i = 0; i < cdev_cnt; ++i) 
+        gdth_analyse_hdrive(hanum,i);
+    
+    TRACE(("gdth_search_drives() OK\n"));
+    return 1;
+}
+
+static int gdth_analyse_hdrive(int hanum,ushort hdrive)
+{
+    register gdth_ha_str *ha;
+    int drv_cyls, drv_hds, drv_secs;
+
+    TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive));
+    if (hdrive >= MAX_HDRIVES)
+        return 0;
+    ha = HADATA(gdth_ctr_tab[hanum]);
+
+    if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,hdrive,0,0)) 
+        return 0;
+    ha->hdr[hdrive].present = TRUE;
+    ha->hdr[hdrive].size = ha->info;
+
+    /* evaluate mapping (sectors per head, heads per cylinder) */
+    ha->hdr[hdrive].size &= ~SECS32;
+    if (ha->info2 == 0) {
+        gdth_eval_mapping(ha->hdr[hdrive].size,&drv_cyls,&drv_hds,&drv_secs);
+    } else {
+        drv_hds = ha->info2 & 0xff;
+        drv_secs = (ha->info2 >> 8) & 0xff;
+        drv_cyls = ha->hdr[hdrive].size /drv_hds/drv_secs;
+    }
+    ha->hdr[hdrive].heads = (unchar)drv_hds;
+    ha->hdr[hdrive].secs  = (unchar)drv_secs;
+    /* round size */
+    ha->hdr[hdrive].size  = drv_cyls * drv_hds * drv_secs;
+    TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
+            hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
             
-            /* get informations about device */
-            if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i,
-                                  0,0)) {
-                TRACE(("gdth_search_dr() cache drive %d devtype %d\n",
-                       i,ha->info));
-                ha->hdr[i].devtype = (ushort)ha->info;
-            }
-        }
+    /* get informations about device */
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) {
+        TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
+                hdrive,ha->info));
+        ha->hdr[hdrive].devtype = (ushort)ha->info;
+    }
+
+    /* cluster info */
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_CLUST_INFO,hdrive,0,0)) {
+        TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
+                hdrive,ha->info));
+        if (!shared_access)
+            ha->hdr[hdrive].cluster_type = (unchar)ha->info;
+    }
+
+    /* R/W attributes */
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) {
+        TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
+                hdrive,ha->info));
+        ha->hdr[hdrive].rw_attribs = (unchar)ha->info;
     }
 
-    TRACE(("gdth_search_drives() OK\n"));
     return 1;
 }
 
@@ -1693,8 +2222,9 @@
     GDTH_LOCK_HA(ha, flags);
 
     scp->SCp.this_residual = (int)priority;
-    b = scp->channel;
+    b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
     t = scp->target;
+#if LINUX_VERSION_CODE >= 0x010300
     if (priority >= DEFAULT_PRI) {
         if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
             (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
@@ -1702,6 +2232,7 @@
             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
     }
+#endif
 
     if (ha->req_first==NULL) {
         ha->req_first = scp;                    /* queue was empty */
@@ -1752,7 +2283,7 @@
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-        b = nscp->channel;
+        b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
         t = nscp->target;
         if (nscp->SCp.this_residual >= DEFAULT_PRI) {
             if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
@@ -1773,10 +2304,12 @@
             firsttime = FALSE;
         }
 
-        if (nscp->done != gdth_scsi_done) 
+#if LINUX_VERSION_CODE >= 0x010300
+        if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) 
+#endif
         {
         if (nscp->SCp.phase == -1) {
-            nscp->SCp.phase = SCSIRAWSERVICE;           /* default: raw svc. */ 
+            nscp->SCp.phase = CACHESERVICE;           /* default: cache svc. */ 
             if (nscp->cmnd[0] == TEST_UNIT_READY) {
                 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", 
                         b, t, nscp->lun));
@@ -1789,8 +2322,9 @@
                 } else if ((ha->scan_mode & 0x0f) == 1) {
                     if (b == 0 && ((t == 0 && nscp->lun == 1) ||
                          (t == 1 && nscp->lun == 0))) {
-                        nscp->SCp.Status = GDT_SCAN_START;
-                        nscp->SCp.phase |= ((ha->scan_mode & 0x10 ? 1:0) << 8);
+                        nscp->SCp.sent_command = GDT_SCAN_START;
+                        nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) 
+                            | SCSIRAWSERVICE;
                         ha->scan_mode = 0x12;
                         TRACE2(("Scan mode: 0x%x (SCAN_START)\n", 
                                 ha->scan_mode));
@@ -1800,29 +2334,55 @@
                     }                   
                 } else if (ha->scan_mode == 0x12) {
                     if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
-                        nscp->SCp.Status = GDT_SCAN_END;
+                        nscp->SCp.phase = SCSIRAWSERVICE;
+                        nscp->SCp.sent_command = GDT_SCAN_END;
                         ha->scan_mode &= 0x10;
                         TRACE2(("Scan mode: 0x%x (SCAN_END)\n", 
                                 ha->scan_mode));
                     }
                 }
             }
+            if (b == ha->virt_bus && nscp->cmnd[0] != INQUIRY &&
+                nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
+                (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
+                /* always GDT_CLUST_INFO! */
+                nscp->SCp.sent_command = GDT_CLUST_INFO;
+            }
         }
         }
 
-        if (nscp->SCp.Status != -1) {
-            if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
+        if (nscp->SCp.sent_command != -1) {
+            if ((nscp->SCp.phase & 0xff) == CACHESERVICE) {
+                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                    this_cmd = FALSE;
+                next_cmd = FALSE;
+            } else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
                 if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
                     this_cmd = FALSE;
                 next_cmd = FALSE;
+            } else {
+                memset((char*)nscp->sense_buffer,0,16);
+                nscp->sense_buffer[0] = 0x70;
+                nscp->sense_buffer[2] = NOT_READY;
+                nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                if (!nscp->SCp.have_data_in)
+                    nscp->SCp.have_data_in++;
+                else {
+                    GDTH_UNLOCK_HA(ha,flags);
+                    /* io_request_lock already active ! */
+                    nscp->scsi_done(nscp);
+                    GDTH_LOCK_HA(ha,flags);
+                }
             }
         } else
 
-        if (nscp->done == gdth_scsi_done) {
+#if LINUX_VERSION_CODE >= 0x010300
+        if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
             if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
                 this_cmd = FALSE;
             next_cmd = FALSE;
         } else
+#endif
         if (b != ha->virt_bus) {
             if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
                 !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) 
@@ -1833,10 +2393,14 @@
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
                     nscp->cmnd[0], b, t, nscp->lun));
             nscp->result = DID_BAD_TARGET << 16;
-            GDTH_UNLOCK_HA(ha,flags);
-            /* io_request_lock already active ! */      
-            nscp->scsi_done(nscp);
-            GDTH_LOCK_HA(ha,flags);
+            if (!nscp->SCp.have_data_in)
+                nscp->SCp.have_data_in++;
+            else {
+                GDTH_UNLOCK_HA(ha,flags);
+                /* io_request_lock already active ! */      
+                nscp->scsi_done(nscp);
+                GDTH_LOCK_HA(ha,flags);
+            }
         } else {
             switch (nscp->cmnd[0]) {
               case TEST_UNIT_READY:
@@ -1849,7 +2413,24 @@
                 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                        nscp->cmnd[4],nscp->cmnd[5]));
-                if (gdth_internal_cache_cmd(hanum,nscp)) {
+                if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
+                    /* return UNIT_ATTENTION */
+                    TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
+                             nscp->cmnd[0], t));
+                    ha->hdr[t].media_changed = FALSE;
+                    memset((char*)nscp->sense_buffer,0,16);
+                    nscp->sense_buffer[0] = 0x70;
+                    nscp->sense_buffer[2] = UNIT_ATTENTION;
+                    nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
+                        nscp->scsi_done(nscp);
+                        GDTH_LOCK_HA(ha,flags);
+                    }
+                } else if (gdth_internal_cache_cmd(hanum,nscp)) {
                     GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */      
                     nscp->scsi_done(nscp);
@@ -1864,6 +2445,7 @@
                 if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
                     TRACE(("Prevent r. nonremov. drive->do nothing\n"));
                     nscp->result = DID_OK << 16;
+                    nscp->sense_buffer[0] = 0;
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
@@ -1881,11 +2463,36 @@
                 }
                 break;
                 
+              case RESERVE:
+              case RELEASE:
+                TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
+                        "RESERVE" : "RELEASE"));
+                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                    this_cmd = FALSE;
+                break;
+                
               case READ_6:
               case WRITE_6:
               case READ_10:
               case WRITE_10:
-                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                if (ha->hdr[t].media_changed) {
+                    /* return UNIT_ATTENTION */
+                    TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
+                             nscp->cmnd[0], t));
+                    ha->hdr[t].media_changed = FALSE;
+                    memset((char*)nscp->sense_buffer,0,16);
+                    nscp->sense_buffer[0] = 0x70;
+                    nscp->sense_buffer[2] = UNIT_ATTENTION;
+                    nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
+                        nscp->scsi_done(nscp);
+                        GDTH_LOCK_HA(ha,flags);
+                    }
+                } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
                     this_cmd = FALSE;
                 break;
 
@@ -1985,7 +2592,10 @@
         inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK;
         /* you can here set all disks to removable, if you want to do
            a flush using the ALLOW_MEDIUM_REMOVAL command */
-        inq.modif_rmb = ha->hdr[t].devtype&1 ? 0x80:0x00;
+        inq.modif_rmb = 0x00;
+        if ((ha->hdr[t].devtype & 1) ||
+            (ha->hdr[t].cluster_type & CLUSTER_DRIVE))
+            inq.modif_rmb = 0x80;
         inq.version   = 2;
         inq.resp_aenc = 2;
         inq.add_length= 32;
@@ -2028,7 +2638,9 @@
         TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
         break;
     }
+
     scp->result = DID_OK << 16;
+    scp->sense_buffer[0] = 0;
 
     if (!scp->SCp.have_data_in)
         scp->SCp.have_data_in++;
@@ -2043,8 +2655,9 @@
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
-    ushort i;
-    int cmd_index;
+    ushort i, cnt;
+    ulong32 no;
+    int cmd_index, read_write;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
@@ -2066,37 +2679,46 @@
         gdth_set_sema0(hanum);
 
     /* fill command */
-    if (scp->cmnd[0]==ALLOW_MEDIUM_REMOVAL) {
+    read_write = FALSE;
+    if (scp->SCp.sent_command != -1) 
+        cmdp->OpCode = scp->SCp.sent_command;   /* special cache cmd. */
+    else if (scp->cmnd[0] == RESERVE) 
+        cmdp->OpCode = GDT_RESERVE_DRV;
+    else if (scp->cmnd[0] == RELEASE)
+        cmdp->OpCode = GDT_RELEASE_DRV;
+    else if (scp->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
         if (scp->cmnd[4] & 1)                   /* prevent ? */
-            cmdp->OpCode      = GDT_MOUNT;
+            cmdp->OpCode = GDT_MOUNT;
         else if (scp->cmnd[3] & 1)              /* removable drive ? */
-            cmdp->OpCode      = GDT_UNMOUNT;
+            cmdp->OpCode = GDT_UNMOUNT;
+        else
+            cmdp->OpCode = GDT_FLUSH;
+    } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10) {
+        read_write = TRUE;
+        if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && 
+                                   (ha->cache_feat & GDT_WR_THROUGH)))
+            cmdp->OpCode = GDT_WRITE_THR;
         else
-            cmdp->OpCode      = GDT_FLUSH;
+            cmdp->OpCode = GDT_WRITE;
     } else {
-        if (scp->cmnd[0]==WRITE_6 || scp->cmnd[0]==WRITE_10) {
-            if (gdth_write_through)
-                cmdp->OpCode  = GDT_WRITE_THR;
-            else
-                cmdp->OpCode  = GDT_WRITE;
-        } else {
-            cmdp->OpCode      = GDT_READ;
-        }
+        read_write = TRUE;
+        cmdp->OpCode = GDT_READ;
     }
+    
+    cmdp->BoardNode        = LOCALBOARD;
+    cmdp->u.cache.DeviceNo = hdrive;
+    cmdp->u.cache.BlockNo  = 1;
+    cmdp->u.cache.sg_canz  = 0;
 
-    cmdp->BoardNode           = LOCALBOARD;
-    cmdp->u.cache.DeviceNo    = hdrive;
-
-    if (scp->cmnd[0]==ALLOW_MEDIUM_REMOVAL) {
-        cmdp->u.cache.BlockNo = 1;
-        cmdp->u.cache.sg_canz = 0;
-    } else {
+    if (read_write) {
         if (scp->cmd_len != 6) {
-            cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]);
-            cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]);
+            memcpy(&no, &scp->cmnd[2], sizeof(ulong32));
+            cmdp->u.cache.BlockNo = ntohl(no);
+            memcpy(&cnt, &scp->cmnd[7], sizeof(ushort));
+            cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt);
         } else {
-            cmdp->u.cache.BlockNo = 
-                ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL;
+            memcpy(&no, &scp->cmnd[0], sizeof(ulong32));
+            cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL;
             cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
         }
 
@@ -2189,8 +2811,8 @@
         gdth_set_sema0(hanum);
 
     /* fill command */  
-    if (scp->SCp.Status != -1) {
-        cmdp->OpCode           = scp->SCp.Status;       /* special raw cmd. */
+    if (scp->SCp.sent_command != -1) {
+        cmdp->OpCode           = scp->SCp.sent_command; /* special raw cmd. */
         cmdp->BoardNode        = LOCALBOARD;
         cmdp->u.raw.direction  = (scp->SCp.phase >> 8);
         TRACE2(("special raw cmd 0x%x param 0x%x\n", 
@@ -2209,12 +2831,12 @@
         cmdp->u.raw.lun        = l;
         cmdp->u.raw.bus        = b;
         cmdp->u.raw.priority   = 0;
-        cmdp->u.raw.link_p     = NULL;
+        cmdp->u.raw.link_p     = 0;
         cmdp->u.raw.sdlen      = scp->request_bufflen;
         cmdp->u.raw.sense_len  = 16;
         cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
         cmdp->u.raw.direction  = 
-            gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
+            gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
         memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
 
         if (scp->use_sg) {
@@ -2346,8 +2968,12 @@
 
     if (ebuffer[elastidx].event_source == source &&
         ebuffer[elastidx].event_idx == idx &&
-        !memcmp((char *)&ebuffer[elastidx].event_data.eu,
-            (char *)&evt->eu, evt->size)) {
+        ((evt->size != 0 && ebuffer[elastidx].event_data.size != 0 &&
+            !memcmp((char *)&ebuffer[elastidx].event_data.eu,
+            (char *)&evt->eu, evt->size)) ||
+        (evt->size == 0 && ebuffer[elastidx].event_data.size == 0 &&
+            !strcmp((char *)&ebuffer[elastidx].event_data.event_string,
+            (char *)&evt->event_string)))) { 
         e = &ebuffer[elastidx];
         do_gettimeofday(&tv);
         e->last_stamp = tv.tv_sec;
@@ -2370,6 +2996,7 @@
         e->first_stamp = e->last_stamp = tv.tv_sec;
         e->same_count = 1;
         e->event_data = *evt;
+        e->application = 0;
     }
     return e;
 }
@@ -2449,18 +3076,20 @@
 
 /* SCSI interface functions */
 
+#if LINUX_VERSION_CODE >= 0x010346
 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
+#else
+static void gdth_interrupt(int irq,struct pt_regs *regs)
+#endif
 {
     register gdth_ha_str *ha;
     gdt6m_dpram_str *dp6m_ptr;
     gdt6_dpram_str *dp6_ptr;
     gdt2_dpram_str *dp2_ptr;
     Scsi_Cmnd *scp;
-    int hanum, rval;
+    int hanum, rval, i;
     unchar IStatus;
-    ushort CmdStatus, Service = 0;
-    ulong32 InfoBytes, InfoBytes2 = 0;
-    gdth_evt_data dvr;
+    ushort Service;
     ulong flags = 0;
 
     TRACE(("gdth_interrupt() IRQ %d\n",irq));
@@ -2478,9 +3107,7 @@
 
     /* search controller */
     if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
-        /*
-        TRACE2(("gdth_interrupt(): Spurious interrupt received\n"));
-        */
+        /* spurious interrupt */
         if (!gdth_polling)
             GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
         return;
@@ -2494,34 +3121,28 @@
     if (ha->type == GDT_EISA) {
         if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = inw(ha->bmic + MAILBOXREG+8);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {            /* async. event ? */
-                Service = inw(ha->bmic + MAILBOXREG+10);
-                InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
-            }
+            ha->status = inw(ha->bmic + MAILBOXREG+8);
+            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
         } else                                      /* no error */
-            CmdStatus = S_OK;
-        InfoBytes = inl(ha->bmic + MAILBOXREG+12);
-        if (gdth_polling)                           /* init. -> more info */
-            InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
+            ha->status = S_OK;
+        ha->info = inl(ha->bmic + MAILBOXREG+12);
+        ha->service = inw(ha->bmic + MAILBOXREG+10);
+        ha->info2 = inl(ha->bmic + MAILBOXREG+4);
+
         outb(0xff, ha->bmic + EDOORREG);            /* acknowledge interrupt */
         outb(0x00, ha->bmic + SEMA1REG);            /* reset status semaphore */
     } else if (ha->type == GDT_ISA) {
         dp2_ptr = (gdt2_dpram_str *)ha->brd;
         if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = gdth_readw(&dp2_ptr->u.ic.Status);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {            /* async. event ? */
-                Service = gdth_readw(&dp2_ptr->u.ic.Service);
-                InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
-            }
+            ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
+            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
         } else                                      /* no error */
-            CmdStatus = S_OK;
-        InfoBytes = gdth_readl(&dp2_ptr->u.ic.Info[0]);
-        if (gdth_polling)                           /* init. -> more info */
-            InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
+            ha->status = S_OK;
+        ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]);
+        ha->service = gdth_readw(&dp2_ptr->u.ic.Service);
+        ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
+
         gdth_writeb(0xff, &dp2_ptr->io.irqdel);     /* acknowledge interrupt */
         gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);   /* reset command index */
         gdth_writeb(0, &dp2_ptr->io.Sema1);         /* reset status semaphore */
@@ -2529,52 +3150,56 @@
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
         if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = gdth_readw(&dp6_ptr->u.ic.Status);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {        /* async. event ? */
-                Service = gdth_readw(&dp6_ptr->u.ic.Service);
-                InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
-            }
+            ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
+            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
         } else                                      /* no error */
-            CmdStatus = S_OK;
-        InfoBytes = gdth_readl(&dp6_ptr->u.ic.Info[0]);
-        if (gdth_polling)                           /* init. -> more info */
-            InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
+            ha->status = S_OK;
+        ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]);
+        ha->service = gdth_readw(&dp6_ptr->u.ic.Service);
+        ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
+
         gdth_writeb(0xff, &dp6_ptr->io.irqdel);     /* acknowledge interrupt */
         gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);   /* reset command index */
         gdth_writeb(0, &dp6_ptr->io.Sema1);         /* reset status semaphore */
     } else if (ha->type == GDT_PCINEW) {
         if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = inw(PTR2USHORT(&ha->plx->status));
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {            /* async. event ? */
-                Service = inw(PTR2USHORT(&ha->plx->service));
-                InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
-            }
+            ha->status = inw(PTR2USHORT(&ha->plx->status));
+            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
         } else
-            CmdStatus = S_OK;
+            ha->status = S_OK;
+        ha->info = inl(PTR2USHORT(&ha->plx->info[0]));
+        ha->service = inw(PTR2USHORT(&ha->plx->service));
+        ha->info2 = inl(PTR2USHORT(&ha->plx->info[1]));
 
-        InfoBytes = inl(PTR2USHORT(&ha->plx->info[0]));
-        if (gdth_polling)                           /* init. -> more info */
-            InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
         outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
     } else if (ha->type == GDT_PCIMPR) {
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
         if (IStatus & 0x80) {                       /* error flag */
             IStatus &= ~0x80;
-            CmdStatus = gdth_readw(&dp6m_ptr->i960r.status);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
-            if (IStatus == ASYNCINDEX) {            /* async. event ? */
-                Service = gdth_readw(&dp6m_ptr->i960r.service);
-                InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
-            }
+            ha->status = gdth_readw(&dp6m_ptr->i960r.status);
+            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
         } else                                      /* no error */
-            CmdStatus = S_OK;
-        InfoBytes = gdth_readl(&dp6m_ptr->i960r.info[0]);
-        if (gdth_polling)                           /* init. -> more info */
-            InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+            ha->status = S_OK;
+        ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]);
+        ha->service = gdth_readw(&dp6m_ptr->i960r.service);
+        ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+
+        /* event string */
+        if (IStatus == ASYNCINDEX) {
+            if (ha->service != SCREENSERVICE &&
+                (ha->fw_vers & 0xff) >= 0x1a) {
+                ha->dvr.severity =   
+                    gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
+                for (i = 0; i < 256; ++i) {
+                    ha->dvr.event_string[i] = gdth_readb
+                        (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
+                    if (ha->dvr.event_string[i] == 0)
+                        break;
+                }
+            }
+        }
         gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
         gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
     } else {
@@ -2585,10 +3210,7 @@
     }
 
     TRACE(("gdth_interrupt() index %d stat %d info %d\n",
-           IStatus,CmdStatus,InfoBytes));
-    ha->status = CmdStatus;
-    ha->info   = InfoBytes;
-    ha->info2  = InfoBytes2;
+           IStatus,ha->status,ha->info));
 
     if (gdth_from_wait) {
         wait_hanum = hanum;
@@ -2597,7 +3219,7 @@
 
     if (IStatus == ASYNCINDEX) {
         TRACE2(("gdth_interrupt() async. event\n"));
-        gdth_async_event(hanum,Service);
+        gdth_async_event(hanum);
         if (!gdth_polling)
             GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
         gdth_next(hanum);
@@ -2606,9 +3228,9 @@
 
     if (IStatus == SPEZINDEX) {
         TRACE2(("Service unknown or not initialized !\n"));
-        dvr.size = sizeof(dvr.eu.driver);
-        dvr.eu.driver.ionode = hanum;
-        gdth_store_event(ha, ES_DRIVER, 4, &dvr);
+        ha->dvr.size = sizeof(ha->dvr.eu.driver);
+        ha->dvr.eu.driver.ionode = hanum;
+        gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
         if (!gdth_polling)
             GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
         return;
@@ -2618,10 +3240,10 @@
     ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
     if (scp == UNUSED_CMND) {
         TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
-        dvr.size = sizeof(dvr.eu.driver);
-        dvr.eu.driver.ionode = hanum;
-        dvr.eu.driver.index = IStatus;
-        gdth_store_event(ha, ES_DRIVER, 1, &dvr);
+        ha->dvr.size = sizeof(ha->dvr.eu.driver);
+        ha->dvr.eu.driver.ionode = hanum;
+        ha->dvr.eu.driver.index = IStatus;
+        gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
         if (!gdth_polling)
             GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
         return;
@@ -2652,9 +3274,7 @@
     register gdth_ha_str *ha;
     gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
-    char c='\r';
-    ushort i;
-    gdth_evt_data dvr;
+    unchar b;
 
     ha   = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
@@ -2682,11 +3302,11 @@
             cmdp->OpCode        = GDT_READ;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
-            cmdp->u.screen.msg_handle= msg->msg_handle;
-            cmdp->u.screen.msg_addr  = virt_to_bus(msg);
+            cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
+            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
             ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
-            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong32);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
@@ -2695,22 +3315,19 @@
         }
 
         if (msg->msg_answer && msg->msg_alen) {
-            for (i=0; i<msg->msg_alen && i<MSGLEN; ++i) {
-                /* getchar() ?? */           
-                /* .. */
-                if (c == '\r')
-                    break;
-                msg->msg_text[i] = c; 
-            }
-            msg->msg_alen -= i;
-            if (c!='\r' && msg->msg_alen!=0) {
-                msg->msg_answer = 1;
-                msg->msg_ext    = 1;
+            /* default answers (getchar() not possible) */
+            if (msg->msg_alen == 1) {
+                msg->msg_alen = 0;
+                msg->msg_len = 1;
+                msg->msg_text[0] = 0;
             } else {
-                msg->msg_ext    = 0;
-                msg->msg_answer = 0;
+                msg->msg_alen -= 2;
+                msg->msg_len = 2;
+                msg->msg_text[0] = 1;
+                msg->msg_text[1] = 0;
             }
-            msg->msg_len = i;
+            msg->msg_ext    = 0;
+            msg->msg_answer = 0;
             while (gdth_test_busy(hanum))
                 gdth_delay(0);
             cmdp->Service       = SCREENSERVICE;
@@ -2720,11 +3337,11 @@
             cmdp->OpCode        = GDT_WRITE;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
-            cmdp->u.screen.msg_handle= msg->msg_handle;
-            cmdp->u.screen.msg_addr  = virt_to_bus(msg);
+            cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
+            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
             ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
-            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong32);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
@@ -2734,54 +3351,110 @@
         printk("\n");
 
     } else {
-        if (scp->SCp.Status == -1 && scp->channel != ha->virt_bus) {
-            ha->raw[BUS_L2P(ha,scp->channel)].io_cnt[scp->target]--;
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
+            ha->raw[BUS_L2P(ha,b)].io_cnt[scp->target]--;
         }
         /* cache or raw service */
         if (ha->status == S_OK) {
-            scp->SCp.Message = S_OK;
-            if (scp->SCp.Status != -1) {
+            scp->SCp.Status = S_OK;
+            scp->SCp.Message = ha->info;
+            if (scp->SCp.sent_command != -1) {
                 TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
-                        scp->SCp.Status));
-                scp->SCp.Status = -1;
+                        scp->SCp.sent_command));
+                /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
+                if (scp->SCp.sent_command == GDT_CLUST_INFO) {
+                    ha->hdr[scp->target].cluster_type = (unchar)ha->info;
+                    if (!(ha->hdr[scp->target].cluster_type & 
+                        CLUSTER_MOUNTED)) {
+                        /* NOT MOUNTED -> MOUNT */
+                        scp->SCp.sent_command = GDT_MOUNT;
+                        if (ha->hdr[scp->target].cluster_type & 
+                            CLUSTER_RESERVED) {
+                            /* cluster drive RESERVED (on the other node) */
+                            scp->SCp.phase = -2;      /* reservation conflict */
+                        }
+                    } else {
+                        scp->SCp.sent_command = -1;
+                    }
+                } else {
+                    if (scp->SCp.sent_command == GDT_MOUNT) {
+                        ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED;
+                        ha->hdr[scp->target].media_changed = TRUE;
+                    } else if (scp->SCp.sent_command == GDT_UNMOUNT) {
+                        ha->hdr[scp->target].cluster_type &= ~CLUSTER_MOUNTED;
+                        ha->hdr[scp->target].media_changed = TRUE;
+                    } 
+                    scp->SCp.sent_command = -1;
+                }
+                /* retry */
                 scp->SCp.this_residual = HIGH_PRI;
                 return 2;
+            } else {
+                /* RESERVE/RELEASE ? */
+                if (scp->cmnd[0] == RESERVE) {
+                    ha->hdr[scp->target].cluster_type |= CLUSTER_RESERVED;
+                } else if (scp->cmnd[0] == RELEASE) {
+                    ha->hdr[scp->target].cluster_type &= ~CLUSTER_RESERVED;
+                }           
+                scp->result = DID_OK << 16;
+                scp->sense_buffer[0] = 0;
             }
-            scp->result = DID_OK << 16;
         } else if (ha->status == S_BSY) {
             TRACE2(("Controller busy -> retry !\n"));
-            scp->SCp.Message = S_BSY;
+            scp->SCp.Status = S_BSY;
+            scp->SCp.Message = ha->info;
+            if (scp->SCp.sent_command == GDT_MOUNT)
+                scp->SCp.sent_command = GDT_CLUST_INFO;
+            /* retry */
             return 2;
         } else {
-            scp->SCp.Message = (int)((ha->info<<16)|ha->status);
-            if (scp->SCp.Status != -1) {
+            scp->SCp.Status = ha->status;
+            scp->SCp.Message = ha->info;
+
+            if (scp->SCp.sent_command != -1) {
                 TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
-                        scp->SCp.Status, ha->status));
-                scp->SCp.Status = -1;
-                scp->SCp.this_residual = HIGH_PRI;
-                return 2;
-            }
-            if (service == CACHESERVICE) {
+                        scp->SCp.sent_command, ha->status));
+                if (scp->SCp.sent_command == GDT_SCAN_START ||
+                    scp->SCp.sent_command == GDT_SCAN_END) {
+                    scp->SCp.sent_command = -1;
+                    /* retry */
+                    scp->SCp.this_residual = HIGH_PRI;
+                    return 2;
+                }
                 memset((char*)scp->sense_buffer,0,16);
                 scp->sense_buffer[0] = 0x70;
                 scp->sense_buffer[2] = NOT_READY;
                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-
+            } else if (service == CACHESERVICE) {
+                if (ha->status == S_CACHE_UNKNOWN &&
+                    (ha->hdr[scp->target].cluster_type & 
+                     CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
+                    /* bus reset -> force GDT_CLUST_INFO */
+                    ha->hdr[scp->target].cluster_type &= ~CLUSTER_RESERVED;
+                }
+                memset((char*)scp->sense_buffer,0,16);
+                scp->sense_buffer[0] = 0x70;
+                scp->sense_buffer[2] = NOT_READY;
+                scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+#if LINUX_VERSION_CODE >= 0x010300
                 if (scp->done != gdth_scsi_done)
+#endif  
                 {
-                    dvr.size = sizeof(dvr.eu.sync);
-                    dvr.eu.sync.ionode  = hanum;
-                    dvr.eu.sync.service = service;
-                    dvr.eu.sync.status  = ha->status;
-                    dvr.eu.sync.info    = ha->info;
-                    dvr.eu.sync.hostdrive = scp->target;
+                    ha->dvr.size = sizeof(ha->dvr.eu.sync);
+                    ha->dvr.eu.sync.ionode  = hanum;
+                    ha->dvr.eu.sync.service = service;
+                    ha->dvr.eu.sync.status  = ha->status;
+                    ha->dvr.eu.sync.info    = ha->info;
+                    ha->dvr.eu.sync.hostdrive = scp->target;
                     if (ha->status >= 0x8000)
-                        gdth_store_event(ha, ES_SYNC, 0, &dvr);
+                        gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
                     else
-                        gdth_store_event(ha, ES_SYNC, service, &dvr);
+                        gdth_store_event(ha, ES_SYNC, service, &ha->dvr);
                 }
             } else {
-                if (ha->status!=S_RAW_SCSI || ha->info>=0x100) {
+                /* sense buffer filled from controller firmware (DMA) */
+                if (ha->status != S_RAW_SCSI || ha->info >= 0x100) {
                     scp->result = DID_BAD_TARGET << 16;
                 } else {
                     scp->result = (DID_OK << 16) | ha->info;
@@ -2944,12 +3617,17 @@
         "GDT HA %u, Uncorrectable DRAM error detected with ECC",
 /*72*/  "\011\000\002\012\001\013\001\014\001"
         "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
+/*73*/  "\005\000\002\006\002"
+        "GDT HA %u, Host drive %u resetted locally",
+/*74*/  "\005\000\002\006\002"
+        "GDT HA %u, Host drive %u resetted remotely",
+/*75*/  "\003\000\002"
+        "GDT HA %u, async. status 75 unknown",
 };
 
 
-static int gdth_async_event(int hanum,int service)
+static int gdth_async_event(int hanum)
 {
-    gdth_evt_data dvr;
     gdth_ha_str *ha;
     gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
@@ -2959,9 +3637,9 @@
     cmdp= ha->pccb;
     msg = (gdth_msg_str *)ha->pscratch;
     TRACE2(("gdth_async_event() ha %d serv %d\n",
-            hanum,service));
+            hanum,ha->service));
 
-    if (service == SCREENSERVICE) {
+    if (ha->service == SCREENSERVICE) {
         if (ha->status == MSG_REQUEST) {
             while (gdth_test_busy(hanum))
                 gdth_delay(0);
@@ -2972,11 +3650,11 @@
             cmdp->OpCode        = GDT_READ;
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
-            cmdp->u.screen.msg_handle= MSG_INV_HANDLE;
-            cmdp->u.screen.msg_addr  = virt_to_bus(msg);
+            cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE;
+            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
             ha->scratch_busy = TRUE;
             ha->cmd_offs_dpmem = 0;
-            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr) 
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
                 + sizeof(ulong32);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
@@ -2991,14 +3669,29 @@
         }
 
     } else {
-        dvr.size = sizeof(dvr.eu.async);
-        dvr.eu.async.ionode   = hanum;
-        dvr.eu.async.service = service;
-        dvr.eu.async.status  = ha->status;
-        dvr.eu.async.info    = ha->info;
-        *(ulong32 *)dvr.eu.async.scsi_coord  = ha->info2;
-        gdth_store_event(ha, ES_ASYNC, service, &dvr);
-        gdth_log_event( &dvr, NULL );
+        if (ha->type == GDT_PCIMPR && 
+            (ha->fw_vers & 0xff) >= 0x1a) {
+            ha->dvr.size = 0;
+            ha->dvr.eu.async.ionode = hanum;
+            ha->dvr.eu.async.status  = ha->status;
+            /* severity and event_string already set! */
+        } else {        
+            ha->dvr.size = sizeof(ha->dvr.eu.async);
+            ha->dvr.eu.async.ionode   = hanum;
+            ha->dvr.eu.async.service = ha->service;
+            ha->dvr.eu.async.status  = ha->status;
+            ha->dvr.eu.async.info    = ha->info;
+            *(ulong32 *)ha->dvr.eu.async.scsi_coord  = ha->info2;
+        }
+        gdth_store_event( ha, ES_ASYNC, ha->service, &ha->dvr );
+        gdth_log_event( &ha->dvr, NULL );
+    
+        /* new host drive from expand? */
+        if (ha->service == CACHESERVICE && ha->status == 56) {
+            TRACE2(("gdth_async_event(): new host drive %d created\n",
+                    (ushort)ha->info));
+            gdth_analyse_hdrive(hanum, (ushort)ha->info);
+        }   
     }
     return 1;
 }
@@ -3010,7 +3703,14 @@
     int i,j;
 
     TRACE2(("gdth_log_event()\n"));
-    if (dvr->eu.async.service == CACHESERVICE && 
+    if (dvr->size == 0) {
+        if (buffer == NULL) {
+            printk("Adapter %d: %s\n",dvr->eu.async.ionode,dvr->event_string); 
+        } else {
+            sprintf(buffer,"Adapter %d: %s\n",
+                dvr->eu.async.ionode,dvr->event_string); 
+        }
+    } else if (dvr->eu.async.service == CACHESERVICE && 
         INDEX_OK(dvr->eu.async.status, async_cache_tab)) {
         TRACE2(("GDT: Async. event cache service, event no.: %d\n",
                 dvr->eu.async.status));
@@ -3081,8 +3781,96 @@
 }
 #endif
 
+GDTH_INITFUNC(void, internal_setup(char *str,int *ints))
+{
+    int i, argc;
+    char *cur_str, *argv;
 
-int __init gdth_detect(Scsi_Host_Template *shtp)
+    TRACE2(("internal_setup() str %s ints[0] %d\n", 
+            str ? str:"NULL", ints ? ints[0]:0));
+
+    /* read irq[] from ints[] */
+    if (ints) {
+        argc = ints[0];
+        if (argc > 0) {
+            if (argc > MAXHA)
+                argc = MAXHA;
+            for (i = 0; i < argc; ++i)
+                irq[i] = ints[i+1];
+        }
+    }
+
+    /* analyse string */
+    argv = str;
+    while (argv && (cur_str = strchr(argv, ':'))) {
+        int val = 0, c = *++cur_str;
+        
+        if (c == 'n' || c == 'N')
+            val = 0;
+        else if (c == 'y' || c == 'Y')
+            val = 1;
+        else
+            val = (int)simple_strtoul(cur_str, NULL, 0);
+
+        if (!strncmp(argv, "disable:", 8))
+            disable = val;
+        else if (!strncmp(argv, "reserve_mode:", 13))
+            reserve_mode = val;
+        else if (!strncmp(argv, "reverse_scan:", 13))
+            reverse_scan = val;
+        else if (!strncmp(argv, "hdr_channel:", 12))
+            hdr_channel = val;
+        else if (!strncmp(argv, "max_ids:", 8))
+            max_ids = val;
+        else if (!strncmp(argv, "rescan:", 7))
+            rescan = val;
+        else if (!strncmp(argv, "virt_ctr:", 9))
+            virt_ctr = val;
+        else if (!strncmp(argv, "shared_access:", 14))
+            shared_access = val;
+        else if (!strncmp(argv, "reserve_list:", 13)) {
+            reserve_list[0] = val;
+            for (i = 1; i < MAX_RES_ARGS; i++) {
+                cur_str = strchr(cur_str, ',');
+                if (!cur_str)
+                    break;
+                if (!isdigit((int)*++cur_str)) {
+                    --cur_str;          
+                    break;
+                }
+                reserve_list[i] = 
+                    (int)simple_strtoul(cur_str, NULL, 0);
+            }
+            if (!cur_str)
+                break;
+            argv = ++cur_str;
+            continue;
+        }
+
+        if ((argv = strchr(argv, ',')))
+            ++argv;
+    }
+}
+
+GDTH_INITFUNC(int, option_setup(char *str))
+{
+    int ints[MAXHA];
+    char *cur = str;
+    int i = 1;
+
+    TRACE2(("option_setup() str %s\n", str ? str:"NULL")); 
+
+    while (cur && isdigit(*cur) && i <= MAXHA) {
+        ints[i++] = simple_strtoul(cur, NULL, 0);
+        if ((cur = strchr(cur, ',')) != NULL) cur++;
+    }
+
+    ints[0] = i - 1;
+    internal_setup(cur, ints);
+    return 1;
+}
+
+GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
 {
     struct Scsi_Host *shp;
     gdth_ha_str *ha;
@@ -3125,18 +3913,23 @@
             break;
         if (gdth_search_isa(isa_bios)) {        /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
-            if(shp == NULL)
-            	continue;
             ha = HADATA(shp);
             if (!gdth_init_isa(isa_bios,ha)) {
                 scsi_unregister(shp);
                 continue;
             }
+#ifdef __ia64__
+            break;
+#else
             /* controller found and initialized */
             printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
                    isa_bios,ha->irq,ha->drq);
 
+#if LINUX_VERSION_CODE >= 0x010346 
             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
+#else
+            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
+#endif
             {
                 printk("GDT-ISA: Unable to allocate IRQ\n");
                 scsi_unregister(shp);
@@ -3144,7 +3937,11 @@
             }
             if (request_dma(ha->drq,"gdth")) {
                 printk("GDT-ISA: Unable to allocate DMA channel\n");
+#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
+#else
+                free_irq(ha->irq);
+#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3161,7 +3958,12 @@
             NUMDATA(shp)->busnum= 0;
 
             ha->pccb = CMDDATA(shp);
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= 0x020322
+            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
+                                                     GDTH_SCRATCH_ORD);
+#else
+            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+#endif
             ha->scratch_busy = FALSE;
             ha->req_first = NULL;
             ha->tid_cnt = MAX_HDRIVES;
@@ -3176,8 +3978,16 @@
                 --gdth_ctr_count;
                 --gdth_ctr_vcount;
                 if (ha->pscratch != NULL)
+#if LINUX_VERSION_CODE >= 0x020322
                     free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+#else
+                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+#endif
+#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
+#else
+                free_irq(ha->irq);
+#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3185,11 +3995,29 @@
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
+#if LINUX_VERSION_CODE >= 0x020000
             shp->max_id      = ha->tid_cnt;
             shp->max_lun     = MAXLUN;
-            shp->max_channel = ha->bus_cnt;
+            shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
+            if (virt_ctr)  
+#endif
+            {
+                virt_ctr = 1;
+                /* register addit. SCSI channels as virtual controllers */
+                for (b = 1; b < ha->bus_cnt + 1; ++b) {
+                    shp = scsi_register(shtp,sizeof(gdth_num_str));
+                    shp->unchecked_isa_dma = 1;
+                    shp->irq = ha->irq;
+                    shp->dma_channel = ha->drq;
+                    gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+                    NUMDATA(shp)->hanum = (ushort)hanum;
+                    NUMDATA(shp)->busnum = b;
+                }
+            }  
+
             GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
+#endif /* !__ia64__ */
         }
     }
 
@@ -3199,8 +4027,6 @@
             break;
         if (gdth_search_eisa(eisa_slot)) {      /* controller found */
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
-            if(shp == NULL)
-            	continue;
             ha = HADATA(shp);
             if (!gdth_init_eisa(eisa_slot,ha)) {
                 scsi_unregister(shp);
@@ -3210,7 +4036,11 @@
             printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
                    eisa_slot>>12,ha->irq);
 
+#if LINUX_VERSION_CODE >= 0x010346 
             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
+#else
+            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
+#endif
             {
                 printk("GDT-EISA: Unable to allocate IRQ\n");
                 scsi_unregister(shp);
@@ -3229,7 +4059,12 @@
                     NUMDATA(shp)->hanum));
 
             ha->pccb = CMDDATA(shp);
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= 0x020322
+            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
+                                                     GDTH_SCRATCH_ORD);
+#else
+            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+#endif
             ha->scratch_busy = FALSE;
             ha->req_first = NULL;
             ha->tid_cnt = MAX_HDRIVES;
@@ -3244,8 +4079,16 @@
                 --gdth_ctr_count;
                 --gdth_ctr_vcount;
                 if (ha->pscratch != NULL)
+#if LINUX_VERSION_CODE >= 0x020322
                     free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+#else
+                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+#endif
+#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
+#else
+                free_irq(ha->irq);
+#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3253,16 +4096,37 @@
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
+#if LINUX_VERSION_CODE >= 0x020000
             shp->max_id      = ha->tid_cnt;
             shp->max_lun     = MAXLUN;
-            shp->max_channel = ha->bus_cnt;
+            shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
+            if (virt_ctr)  
+#endif
+            {
+                virt_ctr = 1;
+                /* register addit. SCSI channels as virtual controllers */
+                for (b = 1; b < ha->bus_cnt + 1; ++b) {
+                    shp = scsi_register(shtp,sizeof(gdth_num_str));
+                    shp->unchecked_isa_dma = 0;
+                    shp->irq = ha->irq;
+                    shp->dma_channel = 0xff;
+                    gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+                    NUMDATA(shp)->hanum = (ushort)hanum;
+                    NUMDATA(shp)->busnum = b;
+                }
+            }  
+
             GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
     }
 
     /* scanning for PCI controllers */
+#if LINUX_VERSION_CODE >= 0x2015C
     if (pci_present())
+#else
+    if (pcibios_present())
+#endif
     {
         gdth_pci_str pcistr[MAXHA];
 
@@ -3272,8 +4136,6 @@
             if (gdth_ctr_count >= MAXHA)
                 break;
             shp = scsi_register(shtp,sizeof(gdth_ext_str));
-            if(shp == NULL)
-            	continue;
             ha = HADATA(shp);
             if (!gdth_init_pci(&pcistr[ctr],ha)) {
                 scsi_unregister(shp);
@@ -3283,14 +4145,18 @@
             printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
                    pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
 
+#if LINUX_VERSION_CODE >= 0x010346 
             if (request_irq(ha->irq, gdth_interrupt,
                             SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
+#else
+            if (request_irq(ha->irq, gdth_interrupt,
+                            SA_INTERRUPT|SA_SHIRQ, "gdth")) 
+#endif
             {
                 printk("GDT-PCI: Unable to allocate IRQ\n");
                 scsi_unregister(shp);
                 continue;
             }
-	    scsi_set_pci_device(shp, pcistr[ctr].pdev);
             shp->unchecked_isa_dma = 0;
             shp->irq = ha->irq;
             shp->dma_channel = 0xff;
@@ -3302,7 +4168,12 @@
             NUMDATA(shp)->busnum= 0;
 
             ha->pccb = CMDDATA(shp);
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= 0x020322
+            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
+                                                     GDTH_SCRATCH_ORD);
+#else
+            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+#endif
             ha->scratch_busy = FALSE;
             ha->req_first = NULL;
             ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
@@ -3317,8 +4188,16 @@
                 --gdth_ctr_count;
                 --gdth_ctr_vcount;
                 if (ha->pscratch != NULL)
+#if LINUX_VERSION_CODE >= 0x020322
                     free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+#else
+                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+#endif
+#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
+#else
+                free_irq(ha->irq);
+#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3326,9 +4205,26 @@
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
+#if LINUX_VERSION_CODE >= 0x020000
             shp->max_id      = ha->tid_cnt;
             shp->max_lun     = MAXLUN;
-            shp->max_channel = ha->bus_cnt;
+            shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
+            if (virt_ctr)  
+#endif
+            {
+                virt_ctr = 1;
+                /* register addit. SCSI channels as virtual controllers */
+                for (b = 1; b < ha->bus_cnt + 1; ++b) {
+                    shp = scsi_register(shtp,sizeof(gdth_num_str));
+                    shp->unchecked_isa_dma = 0;
+                    shp->irq = ha->irq;
+                    shp->dma_channel = 0xff;
+                    gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+                    NUMDATA(shp)->hanum = (ushort)hanum;
+                    NUMDATA(shp)->busnum = b;
+                }
+            }  
+
             GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
@@ -3344,7 +4240,9 @@
         gdth_timer.function = gdth_timeout;
         add_timer(&gdth_timer);
 #endif
+#if LINUX_VERSION_CODE >= 0x020100
         register_reboot_notifier(&gdth_notifier);
+#endif
     }
     gdth_polling = FALSE;
     return gdth_ctr_vcount;
@@ -3360,15 +4258,27 @@
     if (NUMDATA(shp)->busnum == 0) {
         hanum = NUMDATA(shp)->hanum;
         ha    = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= 0x010300
         gdth_flush(hanum);
+#endif
 
         if (shp->irq) {
+#if LINUX_VERSION_CODE >= 0x010346
             free_irq(shp->irq,NULL);
+#else
+            free_irq(shp->irq);
+#endif
         }
+#ifndef __ia64__
         if (shp->dma_channel != 0xff) {
             free_dma(shp->dma_channel);
         }
+#endif
+#if LINUX_VERSION_CODE >= 0x020322
         free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
+#else
+        scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+#endif
         gdth_ctr_released++;
         TRACE2(("gdth_release(): HA %d of %d\n", 
                 gdth_ctr_released, gdth_ctr_count));
@@ -3377,7 +4287,9 @@
 #ifdef GDTH_STATISTICS
             del_timer(&gdth_timer);
 #endif
+#if LINUX_VERSION_CODE >= 0x020100
             unregister_reboot_notifier(&gdth_notifier);
+#endif
         }
     }
 
@@ -3437,12 +4349,17 @@
     return SCSI_ABORT_SNOOZE;
 }
 
+#if LINUX_VERSION_CODE >= 0x010346
 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
+#else
+int gdth_reset(Scsi_Cmnd *scp)
+#endif
 {
     TRACE2(("gdth_reset()\n"));
     return SCSI_RESET_PUNT;
 }
 
+#if LINUX_VERSION_CODE >= 0x02015F
 /* new error handling */
 int gdth_eh_abort(Scsi_Cmnd *scp)
 {
@@ -3462,28 +4379,50 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *cmnd;
+    unchar b;
 
     TRACE2(("gdth_eh_bus_reset()\n"));
     hanum = NUMDATA(scp->host)->hanum;
+    b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
     ha    = HADATA(gdth_ctr_tab[hanum]);
-    if (scp->channel == ha->virt_bus)
-        return FAILED;
 
+    /* clear command tab */
     GDTH_LOCK_HA(ha, flags);
-    for (i = 0; i < MAXID; ++i)
-        ha->raw[BUS_L2P(ha,scp->channel)].io_cnt[i] = 0;
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         cmnd = ha->cmd_tab[i].cmnd;
-        if (!SPECIAL_SCP(cmnd) && cmnd->channel == scp->channel)
+        if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
             ha->cmd_tab[i].cmnd = UNUSED_CMND;
     }
-    gdth_polling = TRUE;
-    while (gdth_test_busy(hanum))
-        gdth_delay(0);
-    gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
-                      BUS_L2P(ha,scp->channel), 0, 0);
-    gdth_polling = FALSE;
     GDTH_UNLOCK_HA(ha, flags);
+
+    if (b == ha->virt_bus) {
+        /* host drives */
+        for (i = 0; i < MAX_HDRIVES; ++i) {
+            if (ha->hdr[i].present) {
+                GDTH_LOCK_HA(ha, flags);
+                gdth_polling = TRUE;
+                while (gdth_test_busy(hanum))
+                    gdth_delay(0);
+                if (gdth_internal_cmd(hanum, CACHESERVICE, 
+                                      GDT_CLUST_RESET, i, 0, 0))
+                    ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED;
+                gdth_polling = FALSE;
+                GDTH_UNLOCK_HA(ha, flags);
+            }
+        }
+    } else {
+        /* raw devices */
+        GDTH_LOCK_HA(ha, flags);
+        for (i = 0; i < MAXID; ++i)
+            ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0;
+        gdth_polling = TRUE;
+        while (gdth_test_busy(hanum))
+            gdth_delay(0);
+        gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
+                          BUS_L2P(ha,b), 0, 0);
+        gdth_polling = FALSE;
+        GDTH_UNLOCK_HA(ha, flags);
+    }
     return SUCCESS;
 }
 
@@ -3492,27 +4431,32 @@
     TRACE2(("gdth_eh_host_reset()\n"));
     return FAILED;
 }
+#endif
 
+#if LINUX_VERSION_CODE >= 0x010300
 int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
+#else
+int gdth_bios_param(Disk *disk,int dev,int *ip)
+#endif
 {
-    unchar t;
+    unchar b, t;
     int hanum;
     gdth_ha_str *ha;
 
     hanum = NUMDATA(disk->device->host)->hanum;
+    b = virt_ctr ? NUMDATA(disk->device->host)->busnum : disk->device->channel;
     t = disk->device->id;
-    TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", 
-            hanum, disk->device->channel, t));
+    TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); 
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-    if (disk->device->channel != ha->virt_bus || ha->hdr[t].heads == 0) {
+    if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
         /* raw device or host drive without mapping information */
-	TRACE2(("Evaluate mapping\n"));
-	gdth_eval_mapping(disk->capacity,&ip[2],&ip[0],&ip[1]);
+        TRACE2(("Evaluate mapping\n"));
+        gdth_eval_mapping(disk->capacity,&ip[2],&ip[0],&ip[1]);
     } else {
-	ip[0] = ha->hdr[t].heads;
-	ip[1] = ha->hdr[t].secs;
-	ip[2] = disk->capacity / ip[0] / ip[1];
+        ip[0] = ha->hdr[t].heads;
+        ip[1] = ha->hdr[t].secs;
+        ip[2] = disk->capacity / ip[0] / ip[1];
     }
 
     TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
@@ -3521,24 +4465,6 @@
 }
 
 
-static void internal_done(Scsi_Cmnd *scp)
-{
-    scp->SCp.sent_command++;
-}
-
-int gdth_command(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_command()\n"));
-
-    scp->SCp.sent_command = 0;
-    gdth_queuecommand(scp,internal_done);
-
-    while (!scp->SCp.sent_command)
-        barrier();
-    return scp->result;
-}
-
-
 int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
 {
     int hanum;
@@ -3550,171 +4476,173 @@
     scp->scsi_done = (void *)done;
     scp->SCp.have_data_in = 1;
     scp->SCp.phase = -1;
-    scp->SCp.Status = -1;
+    scp->SCp.sent_command = -1;
     hanum = NUMDATA(scp->host)->hanum;
 #ifdef GDTH_STATISTICS
     ++act_ios;
 #endif
 
     priority = DEFAULT_PRI;
+#if LINUX_VERSION_CODE >= 0x010300
     if (scp->done == gdth_scsi_done)
         priority = scp->SCp.this_residual;
+#endif
     gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
     gdth_putq( hanum, scp, priority );
     gdth_next( hanum );
     return 0;
 }
 
+#if LINUX_VERSION_CODE >= 0x010300
 /* flush routine */
 static void gdth_flush(int hanum)
 {
     int             i;
     gdth_ha_str     *ha;
-    Scsi_Cmnd     * scp;
-    Scsi_Device   * sdev;
     gdth_cmd_str    gdtcmd;
+#if LINUX_VERSION_CODE >= 0x020322
+    Scsi_Cmnd       *scp;
+    Scsi_Device     *sdev;
+#else
+    Scsi_Cmnd       scp;
+    Scsi_Device     sdev;
+#endif
+    char            cmnd[MAX_COMMAND_SIZE];   
+    memset(cmnd, 0xff, 12);
 
     TRACE2(("gdth_flush() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
+#if LINUX_VERSION_CODE >= 0x020322
     sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-    if (!sdev)
-	return;
-
     scp  = scsi_allocate_device(sdev, 1, FALSE);
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+#else
+    memset(&sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    sdev.host = scp.host = gdth_ctr_tab[hanum];
+    sdev.id = scp.target = sdev.host->this_id;
+    scp.device = &sdev;
+#endif
 
-    if (scp) {
-        scp->cmd_len = 12;
-        scp->use_sg = 0;
-
-        for (i = 0; i < MAX_HDRIVES; ++i) {
-            if (ha->hdr[i].present) {
-                gdtcmd.BoardNode = LOCALBOARD;
-                gdtcmd.Service = CACHESERVICE;
-                gdtcmd.OpCode = GDT_FLUSH;
-                gdtcmd.u.cache.DeviceNo = i;
-                gdtcmd.u.cache.BlockNo = 1;
-                gdtcmd.u.cache.sg_canz = 0;
-                TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
-                 gdth_do_cmd(scp, &gdtcmd, 30);
-            }
+    for (i = 0; i < MAX_HDRIVES; ++i) {
+        if (ha->hdr[i].present) {
+            gdtcmd.BoardNode = LOCALBOARD;
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_FLUSH;
+            gdtcmd.u.cache.DeviceNo = i;
+            gdtcmd.u.cache.BlockNo = 1;
+            gdtcmd.u.cache.sg_canz = 0;
+            TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+#endif
         }
-    	scsi_release_command(scp);
     }
+#if LINUX_VERSION_CODE >= 0x020322
+    scsi_release_command(scp);
     scsi_free_host_dev(sdev);
+#endif
 }
 
 /* shutdown routine */
+#if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
+#else
+void gdth_halt(void)
+#endif
 {
     int             hanum;
 #ifndef __alpha__
-    Scsi_Cmnd     * scp;
-    Scsi_Device   * sdev;
     gdth_cmd_str    gdtcmd;
+#if LINUX_VERSION_CODE >= 0x020322
+    Scsi_Cmnd       *scp;
+    Scsi_Device     *sdev;
+#else
+    Scsi_Cmnd       scp;
+    Scsi_Device     sdev;
+#endif
+    char            cmnd[MAX_COMMAND_SIZE];   
 #endif
 
-    TRACE2(("gdth_halt() event %d\n",event));
+#if LINUX_VERSION_CODE >= 0x020100
+    TRACE2(("gdth_halt() event %d\n",(int)event));
     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
         return NOTIFY_DONE;
+#else
+    TRACE2(("gdth_halt()\n"));
+    if (halt_called) {
+        TRACE2(("already called\n"));
+        return;
+    }
+    halt_called = TRUE;
+#endif
     printk("GDT: Flushing all host drives .. ");
     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
         gdth_flush(hanum);
 
 #ifndef __alpha__
         /* controller reset */
-	sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-	scp  = scsi_allocate_device(sdev, 1, FALSE);
+        memset(cmnd, 0xff, 12);
+#if LINUX_VERSION_CODE >= 0x020322
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
         scp->cmd_len = 12;
         scp->use_sg = 0;
+#else
+        memset(&sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        sdev.host = scp.host = gdth_ctr_tab[hanum];
+        sdev.id = scp.target = sdev.host->this_id;
+        scp.device = &sdev;
+#endif
 
         gdtcmd.BoardNode = LOCALBOARD;
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_RESET;
         TRACE2(("gdth_halt(): reset controller %d\n", hanum));
-        gdth_do_cmd(scp, &gdtcmd, 10);
-	scsi_release_command(scp);
-	scsi_free_host_dev(sdev);
+#if LINUX_VERSION_CODE >= 0x020322
+        gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#else
+        gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
+#endif
 #endif
     }
-
     printk("Done.\n");
 
 #ifdef GDTH_STATISTICS
     del_timer(&gdth_timer);
 #endif
+#if LINUX_VERSION_CODE >= 0x020100
+#if LINUX_VERSION_CODE < 0x020322
     unregister_reboot_notifier(&gdth_notifier);
+#endif
     return NOTIFY_OK;
+#endif
 }
+#endif
 
-/* called from init/main.c */
-void __init gdth_setup(char *str,int *ints)
-{
-    int i, argc;
-    char *cur_str, *argv;
 
+#if LINUX_VERSION_CODE < 0x020400 && !defined(MODULE)
+
+GDTH_INITFUNC(void, gdth_setup(char *str,int *ints)) 
+{    
     TRACE2(("gdth_setup() str %s ints[0] %d\n", 
             str ? str:"NULL", ints ? ints[0]:0));
-
-    /* read irq[] from ints[] */
-    if (ints) {
-        argc = ints[0];
-        if (argc > 0) {
-            if (argc > MAXHA)
-                argc = MAXHA;
-            for (i = 0; i < argc; ++i)
-                irq[i] = ints[i+1];
-        }
-    }
-
-    /* analyse string */
-    argv = str;
-    while (argv && (cur_str = strchr(argv, ':'))) {
-        int val = 0, c = *++cur_str;
-        
-        if (c == 'n' || c == 'N')
-            val = 0;
-        else if (c == 'y' || c == 'Y')
-            val = 1;
-        else
-            val = (int)simple_strtoul(cur_str, NULL, 0);
-
-        if (!strncmp(argv, "disable:", 8))
-            disable = val;
-        else if (!strncmp(argv, "reserve_mode:", 13))
-            reserve_mode = val;
-        else if (!strncmp(argv, "reverse_scan:", 13))
-            reverse_scan = val;
-        else if (!strncmp(argv, "hdr_channel:", 12))
-            hdr_channel = val;
-        else if (!strncmp(argv, "max_ids:", 8))
-            max_ids = val;
-        else if (!strncmp(argv, "rescan:", 7))
-            rescan = val;
-        else if (!strncmp(argv, "reserve_list:", 13)) {
-            reserve_list[0] = val;
-            for (i = 1; i < MAX_RES_ARGS; i++) {
-                cur_str = strchr(cur_str, ',');
-                if (!cur_str)
-                    break;
-                if (!isdigit((int)*++cur_str)) {
-                    --cur_str;          
-                    break;
-                }
-                reserve_list[i] = 
-                    (int)simple_strtoul(cur_str, NULL, 0);
-            }
-            if (!cur_str)
-                break;
-            argv = ++cur_str;
-            continue;
-        }
-
-        if ((argv = strchr(argv, ',')))
-            ++argv;
-    }
+    internal_setup(str, ints);
 }
 
+#else
 
-static Scsi_Host_Template driver_template = GDTH;
+Scsi_Host_Template driver_template = GDTH;
 #include "scsi_module.c"
+#ifndef MODULE
+__setup("gdth=", option_setup);
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h
--- v2.4.4/linux/drivers/scsi/gdth.h	Mon Dec 11 13:19:43 2000
+++ linux/drivers/scsi/gdth.h	Sat May 19 17:43:06 2001
@@ -4,13 +4,13 @@
 /*
  * Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux
  * 
- * gdth.h Copyright (C) 1995-99 ICP vortex Computersysteme GmbH, Achim Leubner
+ * gdth.h Copyright (C) 1995-01 ICP vortex Computersysteme GmbH, Achim Leubner
  * See gdth.c for further informations and 
  * below for supported controller types
  *
  * <achim@vortex.de>
  *
- * $Id: gdth.h,v 1.21 1999/03/26 09:12:24 achim Exp $
+ * $Id: gdth.h,v 1.38 2001/03/15 15:06:23 achim Exp $
  */
 
 #include <linux/version.h>
@@ -29,9 +29,9 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "1.14"
+#define GDTH_VERSION_STR        "1.28"
 #define GDTH_VERSION            1
-#define GDTH_SUBVERSION         14
+#define GDTH_SUBVERSION         28
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
@@ -126,7 +126,7 @@
 #endif
 
 /* limits */
-#define GDTH_SCRATCH    PAGE_SIZE                    /* 4KB scratch buffer */
+#define GDTH_SCRATCH    PAGE_SIZE               /* 4KB scratch buffer */
 #define GDTH_SCRATCH_ORD 0                      /* order 0 means 1 page */
 #define GDTH_MAXCMDS    124
 #define GDTH_MAXC_P_L   16                      /* max. cmds per lun */
@@ -136,7 +136,8 @@
 #define MAXID           127
 #define MAXLUN          8
 #define MAXBUS          6
-#define MAX_HDRIVES     35                      /* max. host drive count */
+#define MAX_HDRIVES     100                     /* max. host drive count */
+#define MAX_LDRIVES     255                     /* max. log. drive count */
 #define MAX_EVENTS      100                     /* event buffer count */
 #define MAX_RES_ARGS    40                      /* device reservation, 
                                                    must be a multiple of 4 */
@@ -174,7 +175,13 @@
 #define IC_QUEUE_BYTES  4
 #define DPMEM_COMMAND_OFFSET    IC_HEADER_BYTES+IC_QUEUE_BYTES*MAXOFFSETS
 
-/* cache/raw service commands */
+/* cluster_type constants */
+#define CLUSTER_DRIVE         1
+#define CLUSTER_MOUNTED       2
+#define CLUSTER_RESERVED      4
+#define CLUSTER_RESERVE_STATE (CLUSTER_DRIVE|CLUSTER_MOUNTED|CLUSTER_RESERVED)
+
+/* commands for all services, cache service */
 #define GDT_INIT        0                       /* service initialization */
 #define GDT_READ        1                       /* read command */
 #define GDT_WRITE       2                       /* write command */
@@ -190,8 +197,13 @@
 #define GDT_READ_THR    17                      /* read through */
 #define GDT_EXT_INFO    18                      /* extended info */
 #define GDT_RESET       19                      /* controller reset */
+#define GDT_RESERVE_DRV 20                      /* reserve host drive */
+#define GDT_RELEASE_DRV 21                      /* release host drive */
+#define GDT_CLUST_INFO  22                      /* cluster info */
+#define GDT_RW_ATTRIBS  23                      /* R/W attribs (write thru,..)*/
+#define GDT_CLUST_RESET 24                      /* releases the cluster drives*/
 
-/* additional raw service commands */
+/* raw service commands */
 #define GDT_RESERVE     14                      /* reserve dev. to raw serv. */
 #define GDT_RELEASE     15                      /* release device */
 #define GDT_RESERVE_ALL 16                      /* reserve all devices */
@@ -200,6 +212,9 @@
 #define GDT_SCAN_START  19                      /* start device scan */
 #define GDT_SCAN_END    20                      /* stop device scan */  
 
+/* screen service commands */
+#define GDT_REALTIME    3                       /* realtime clock to screens. */
+
 /* IOCTL command defines */
 #define SCSI_DR_INFO    0x00                    /* SCSI drive info */                   
 #define SCSI_CHAN_CNT   0x05                    /* SCSI channel count */   
@@ -207,10 +222,11 @@
 #define SCSI_DEF_CNT    0x15                    /* grown/primary defects */
 #define DSK_STATISTICS  0x4b                    /* SCSI disk statistics */
 #define IOCHAN_DESC     0x5d                    /* description of IO channel */
-#define IOCHAN_RAW_DESC 0x5e                    /* description of raw IO channel */
+#define IOCHAN_RAW_DESC 0x5e                    /* description of raw IO chn. */
 #define L_CTRL_PATTERN  0x20000000L             /* SCSI IOCTL mask */
 #define ARRAY_INFO      0x12                    /* array drive info */
 #define ARRAY_DRV_LIST  0x0f                    /* array drive list */
+#define ARRAY_DRV_LIST2 0x34                    /* array drive list (new) */
 #define LA_CTRL_PATTERN 0x10000000L             /* array IOCTL mask */
 #define CACHE_DRV_CNT   0x01                    /* cache drive count */
 #define CACHE_DRV_LIST  0x02                    /* cache drive list */
@@ -223,19 +239,11 @@
 #define IO_CHANNEL      0x00020000L             /* default IO channel */
 #define INVALID_CHANNEL 0x0000ffffL             /* invalid channel */
 
-/* IOCTLs */
-#define GDTIOCTL_MASK       ('J'<<8)
-#define GDTIOCTL_GENERAL    (GDTIOCTL_MASK | 0) /* general IOCTL */
-#define GDTIOCTL_DRVERS     (GDTIOCTL_MASK | 1) /* get driver version */
-#define GDTIOCTL_CTRTYPE    (GDTIOCTL_MASK | 2) /* get controller type */
-#define GDTIOCTL_CTRCNT     (GDTIOCTL_MASK | 5) /* get controller count */
-#define GDTIOCTL_LOCKDRV    (GDTIOCTL_MASK | 6) /* lock host drive */
-#define GDTIOCTL_LOCKCHN    (GDTIOCTL_MASK | 7) /* lock channel */
-#define GDTIOCTL_EVENT      (GDTIOCTL_MASK | 8) /* read controller events */
-
 /* service errors */
 #define S_OK            1                       /* no error */
+#define S_GENERR        6                       /* general error */
 #define S_BSY           7                       /* controller busy */
+#define S_CACHE_UNKNOWN 12                      /* cache serv.: drive unknown */
 #define S_RAW_SCSI      12                      /* raw serv.: target error */
 #define S_RAW_ILL       0xff                    /* raw serv.: illegal */
 
@@ -250,8 +258,8 @@
 #define HIGH_PRI        0x08
 
 /* data directions */
-#define DATA_IN         0x01000000L             /* data from target */
-#define DATA_OUT        0x00000000L             /* data to target */
+#define GDTH_DATA_IN    0x01000000L             /* data from target */
+#define GDTH_DATA_OUT   0x00000000L             /* data to target */
 
 /* BMIC registers (EISA controllers) */
 #define ID0REG          0x0c80                  /* board ID */
@@ -299,7 +307,7 @@
     unchar      revision[4];                    /* revision */
     ulong32     sy_rate;                        /* current rate for sync. tr. */
     ulong32     sy_max_rate;                    /* max. rate for sync. tr. */
-    ulong32     no_ldrive;                      /* belongs to this logical drv.*/
+    ulong32     no_ldrive;                      /* belongs to this log. drv.*/
     ulong32     blkcnt;                         /* number of blocks */
     ushort      blksize;                        /* size of block in bytes */
     unchar      available;                      /* flag: access is available */
@@ -454,7 +462,15 @@
     unchar      is_parity;                      /* Flag: is parity drive? */
     unchar      is_hotfix;                      /* Flag: is hotfix drive? */
     unchar      res[3];
-} PACKED gdth_arraylist_str;
+} PACKED gdth_alist_str;
+
+typedef struct {
+    ulong32     entries_avail;                  /* allocated entries */
+    ulong32     entries_init;                   /* returned entries */
+    ulong32     first_entry;                    /* first entry number */
+    ulong32     list_offset;                    /* offset of following list */
+    gdth_alist_str list[1];                     /* list */
+} PACKED gdth_arcdl_str;
 
 /* cache info/config IOCTL */
 typedef struct {
@@ -586,8 +602,13 @@
         } PACKED ioctl;                         /* IOCTL command structure */
         struct {
             ushort      reserved;
-            ulong32     msg_handle;             /* message handle */
-            ulong32     msg_addr;               /* message buffer address */
+            union {
+                struct {
+                    ulong32  msg_handle;        /* message handle */
+                    ulong32  msg_addr;          /* message buffer address */
+                } PACKED msg;
+                unchar       data[12];          /* buffer for rtc data, ... */
+            } su;
         } PACKED screen;                        /* screen service cmd. str. */
         struct {
             ushort      reserved;
@@ -604,7 +625,7 @@
             unchar      priority;               /* only 0 used */
             ulong32     sense_len;              /* sense data length */
             ulong32     sense_data;             /* sense data addr. */
-            struct raw  *link_p;                /* linked cmds (not supp.) */
+            ulong32     link_p;                 /* linked cmds (not supp.) */
             ulong32     sg_ranz;                /* s/g element count */
             gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
         } PACKED raw;                           /* raw service cmd. struct. */
@@ -650,6 +671,8 @@
             ulong32         l1, l2, l3, l4;
         } PACKED test;
     } eu;
+    ulong32                 severity;
+    unchar                  event_string[256];          
 } PACKED gdth_evt_data;
 
 typedef struct {
@@ -799,7 +822,9 @@
     unchar              unused5[7];
     unchar              edoor_en_reg;           /* board interrupts enable */
     unchar              unused6[27];
-    ulong32             unused7[1004];          /* size: 4 KB */
+    ulong32             unused7[939];         
+    ulong32             severity;       
+    char                evt_str[256];           /* event string */
 } PACKED gdt6m_i960_regs;
 
 /* DPRAM PCI MPR controllers */
@@ -815,7 +840,9 @@
 
 /* PCI resources */
 typedef struct {
+#if LINUX_VERSION_CODE >= 0x02015C
     struct pci_dev      *pdev;
+#endif
     ushort              device_id;              /* device ID (0,..,9) */
     unchar              bus;                    /* PCI bus */
     unchar              device_fn;              /* PCI device/function no. */
@@ -831,6 +858,7 @@
     ushort              type;                   /* controller class */
     ushort              raw_feat;               /* feat. raw service (s/g,..) */
     ulong32             stype;                  /* controller subtype */
+    ushort              fw_vers;                /* firmware version */
     ushort              cache_feat;             /* feat. cache serv. (s/g,..) */
     ushort              bmic;                   /* BMIC address (EISA) */
     void                *brd;                   /* DPRAM address */
@@ -843,12 +871,13 @@
     unchar              irq;                    /* IRQ */
     unchar              drq;                    /* DRQ (ISA controllers) */
     ushort              status;                 /* command status */
+    ushort              service;                /* service/firmware ver./.. */
     ulong32             info;
     ulong32             info2;                  /* additional info */
     Scsi_Cmnd           *req_first;             /* top of request queue */
     struct {
         unchar          present;                /* Flag: host drive present? */
-        unchar          is_logdrv;              /* Flag: logical drive (master)? */
+        unchar          is_logdrv;              /* Flag: log. drive (master)? */
         unchar          is_arraydrv;            /* Flag: array drive? */
         unchar          is_master;              /* Flag: array drive master? */
         unchar          is_parity;              /* Flag: parity drive? */
@@ -861,13 +890,15 @@
         ulong32         size;                   /* capacity */
         unchar          ldr_no;                 /* log. drive no. */
         unchar          rw_attribs;             /* r/w attributes */
+        unchar          cluster_type;           /* cluster properties */
+        unchar          media_changed;          /* Flag:MOUNT/UNMOUNT occured */
         ulong32         start_sec;              /* start sector */
-    } hdr[MAX_HDRIVES];                         /* host drives */
+    } hdr[MAX_LDRIVES];                         /* host drives */
     struct {
         unchar          lock;                   /* channel locked? (hot plug) */
         unchar          pdev_cnt;               /* physical device count */
         unchar          local_no;               /* local channel number */
-	unchar          io_cnt[MAXID];          /* current IO count */
+        unchar          io_cnt[MAXID];          /* current IO count */
         ulong32         address;                /* channel address */
         ulong32         id_list[MAXID];         /* IDs of the phys. devices */
     } raw[MAXBUS];                              /* SCSI channels */
@@ -887,7 +918,10 @@
     gdth_cpar_str       cpar;                   /* controller cache par. */
     gdth_bfeat_str      bfeat;                  /* controller features */
     gdth_binfo_str      binfo;                  /* controller info */
+    gdth_evt_data       dvr;                    /* event structure */
+#if LINUX_VERSION_CODE >= 0x02015F
     spinlock_t          smp_lock;
+#endif
 } gdth_ha_str;
 
 /* structure for scsi_register(), SCSI bus != 0 */
@@ -965,12 +999,16 @@
 
 int gdth_detect(Scsi_Host_Template *);
 int gdth_release(struct Scsi_Host *);
-int gdth_command(Scsi_Cmnd *);
 int gdth_queuecommand(Scsi_Cmnd *,void (*done)(Scsi_Cmnd *));
 int gdth_abort(Scsi_Cmnd *);
+#if LINUX_VERSION_CODE >= 0x010346
 int gdth_reset(Scsi_Cmnd *, unsigned int reset_flags);
+#else
+int gdth_reset(Scsi_Cmnd *);
+#endif
 const char *gdth_info(struct Scsi_Host *);
 
+#if LINUX_VERSION_CODE >= 0x020322
 int gdth_bios_param(Disk *,kdev_t,int *);
 int gdth_proc_info(char *,char **,off_t,int,int,int);
 int gdth_eh_abort(Scsi_Cmnd *scp);
@@ -983,7 +1021,7 @@
                detect:          gdth_detect,                     \
                release:         gdth_release,                    \
                info:            gdth_info,                       \
-               command:         gdth_command,                    \
+               command:         NULL,                            \
                queuecommand:    gdth_queuecommand,               \
                eh_abort_handler: gdth_eh_abort,                  \
                eh_device_reset_handler: gdth_eh_device_reset,    \
@@ -1000,5 +1038,85 @@
                unchecked_isa_dma: 1,                             \
                use_clustering:  ENABLE_CLUSTERING,               \
                use_new_eh_code: 1       /* use new error code */ }    
+
+#elif LINUX_VERSION_CODE >= 0x02015F
+int gdth_bios_param(Disk *,kdev_t,int *);
+extern struct proc_dir_entry proc_scsi_gdth;
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+int gdth_eh_abort(Scsi_Cmnd *scp);
+int gdth_eh_device_reset(Scsi_Cmnd *scp);
+int gdth_eh_bus_reset(Scsi_Cmnd *scp);
+int gdth_eh_host_reset(Scsi_Cmnd *scp);
+#define GDTH { proc_dir:        &proc_scsi_gdth,                 \
+               proc_info:       gdth_proc_info,                  \
+               name:            "GDT SCSI Disk Array Controller",\
+               detect:          gdth_detect,                     \
+               release:         gdth_release,                    \
+               info:            gdth_info,                       \
+               command:         NULL,                            \
+               queuecommand:    gdth_queuecommand,               \
+               eh_abort_handler: gdth_eh_abort,                  \
+               eh_device_reset_handler: gdth_eh_device_reset,    \
+               eh_bus_reset_handler: gdth_eh_bus_reset,          \
+               eh_host_reset_handler: gdth_eh_host_reset,        \
+               abort:           gdth_abort,                      \
+               reset:           gdth_reset,                      \
+               bios_param:      gdth_bios_param,                 \
+               can_queue:       GDTH_MAXCMDS,                    \
+               this_id:         -1,                              \
+               sg_tablesize:    GDTH_MAXSG,                      \
+               cmd_per_lun:     GDTH_MAXC_P_L,                   \
+               present:         0,                               \
+               unchecked_isa_dma: 1,                             \
+               use_clustering:  ENABLE_CLUSTERING,               \
+               use_new_eh_code: 1       /* use new error code */ }    
+
+#elif LINUX_VERSION_CODE >= 0x010300
+int gdth_bios_param(Disk *,kdev_t,int *);
+extern struct proc_dir_entry proc_scsi_gdth;
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+#define GDTH { NULL, NULL,                              \
+                   &proc_scsi_gdth,                     \
+                   gdth_proc_info,                      \
+                   "GDT SCSI Disk Array Controller",    \
+                   gdth_detect,                         \
+                   gdth_release,                        \
+                   gdth_info,                           \
+                   NULL,                                \
+                   gdth_queuecommand,                   \
+                   gdth_abort,                          \
+                   gdth_reset,                          \
+                   NULL,                                \
+                   gdth_bios_param,                     \
+                   GDTH_MAXCMDS,                        \
+                   -1,                                  \
+                   GDTH_MAXSG,                          \
+                   GDTH_MAXC_P_L,                       \
+                   0,                                   \
+                   1,                                   \
+                   ENABLE_CLUSTERING}
+
+#else
+int gdth_bios_param(Disk *,int,int *);
+#define GDTH { NULL, NULL,                              \
+                   "GDT SCSI Disk Array Controller",    \
+                   gdth_detect,                         \
+                   gdth_release,                        \
+                   gdth_info,                           \
+                   NULL,                                \
+                   gdth_queuecommand,                   \
+                   gdth_abort,                          \
+                   gdth_reset,                          \
+                   NULL,                                \
+                   gdth_bios_param,                     \
+                   GDTH_MAXCMDS,                        \
+                   -1,                                  \
+                   GDTH_MAXSG,                          \
+                   GDTH_MAXC_P_L,                       \
+                   0,                                   \
+                   1,                                   \
+                   ENABLE_CLUSTERING}
+#endif
+
 #endif
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/gdth_ioctl.h linux/drivers/scsi/gdth_ioctl.h
--- v2.4.4/linux/drivers/scsi/gdth_ioctl.h	Mon Jan 11 10:17:20 1999
+++ linux/drivers/scsi/gdth_ioctl.h	Sat May 19 17:43:06 2001
@@ -2,7 +2,7 @@
 #define _GDTH_IOCTL_H
 
 /* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.2 1998/12/17 15:42:49 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.9 2001/01/10 14:39:37 achim Exp $
  */
 
 /* IOCTLs */
@@ -11,13 +11,19 @@
 #define GDTIOCTL_DRVERS     (GDTIOCTL_MASK | 1) /* get driver version */
 #define GDTIOCTL_CTRTYPE    (GDTIOCTL_MASK | 2) /* get controller type */
 #define GDTIOCTL_OSVERS     (GDTIOCTL_MASK | 3) /* get OS version */
+#define GDTIOCTL_HDRLIST    (GDTIOCTL_MASK | 4) /* get host drive list */
 #define GDTIOCTL_CTRCNT     (GDTIOCTL_MASK | 5) /* get controller count */
 #define GDTIOCTL_LOCKDRV    (GDTIOCTL_MASK | 6) /* lock host drive */
 #define GDTIOCTL_LOCKCHN    (GDTIOCTL_MASK | 7) /* lock channel */
 #define GDTIOCTL_EVENT      (GDTIOCTL_MASK | 8) /* read controller events */
+#define GDTIOCTL_SCSI       (GDTIOCTL_MASK | 9) /* SCSI command */
+#define GDTIOCTL_RESET_BUS  (GDTIOCTL_MASK |10) /* reset SCSI bus */
+#define GDTIOCTL_RESCAN     (GDTIOCTL_MASK |11) /* rescan host drives */
+#define GDTIOCTL_RESET_DRV  (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */
 
-#define GDTIOCTL_MAGIC      0xaffe0001UL
-
+#define GDTIOCTL_MAGIC      0xaffe0004
+#define EVENT_SIZE          294 
+#define MAX_HDRIVES         100                     
 
 /* IOCTL structure (write) */
 typedef struct {
@@ -34,7 +40,7 @@
         struct {
             unchar          lock;               /* lock/unlock */
             unchar          drive_cnt;          /* drive count */
-            ushort          drives[35];         /* drives */
+            ushort          drives[MAX_HDRIVES];/* drives */
         } lockdrv;
         struct {
             unchar          lock;               /* lock/unlock */
@@ -43,8 +49,19 @@
         struct {
             int             erase;              /* erase event ? */
             int             handle;
-            unchar          evt[34];            /* event structure */
+            unchar          evt[EVENT_SIZE];    /* event structure */
         } event;
+        struct {
+            unchar          bus;                /* SCSI bus */
+            unchar          target;             /* target ID */
+            unchar          lun;                /* LUN */
+            unchar          cmd_len;            /* command length */
+            unchar          cmd[12];            /* SCSI command */
+        } scsi;
+        struct {
+            ushort          hdr_no;             /* host drive number */
+            unchar          flag;               /* old meth./add/remove */
+        } rescan;
     } iu;
 } gdth_iowr_str;
 
@@ -77,8 +94,14 @@
         } ctrcnt;
         struct {
             int             handle;
-            unchar          evt[34];            /* event structure */
+            unchar          evt[EVENT_SIZE];    /* event structure */
         } event;
+        struct {
+            unchar          bus;                /* SCSI bus, 0xff: invalid */
+            unchar          target;             /* target ID */
+            unchar          lun;                /* LUN */
+            unchar          cluster_type;       /* cluster properties */
+        } hdr_list[MAX_HDRIVES];                /* index is host drive number */
     } iu;
 } gdth_iord_str;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c
--- v2.4.4/linux/drivers/scsi/gdth_proc.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/gdth_proc.c	Sat May 19 17:43:06 2001
@@ -1,5 +1,5 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.13 1999/03/22 16:12:53 achim Exp $
+ * $Id: gdth_proc.c,v 1.27 2001/03/14 10:47:00 achim Exp $
  */
 
 #include "gdth_ioctl.h"
@@ -31,27 +31,30 @@
 static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
 {
     int             ret_val;
-    Scsi_Cmnd     * scp;
-    Scsi_Device   * sdev;
+#if LINUX_VERSION_CODE >= 0x020322
+    Scsi_Cmnd       *scp;
+    Scsi_Device     *sdev;
+#else
+    Scsi_Cmnd       scp;
+    Scsi_Device     sdev;
+#endif
     gdth_iowr_str   *piowr;
 
     TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
     piowr = (gdth_iowr_str *)buffer;
 
+#if LINUX_VERSION_CODE >= 0x020322
     sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    
-    if(sdev==NULL)
-    	return -ENOMEM;
-
     scp  = scsi_allocate_device(sdev, 1, FALSE);
-    
-    if(scp==NULL)
-    {
-	scsi_free_host_dev(sdev);
-        return -ENOMEM;
-    }
     scp->cmd_len = 12;
     scp->use_sg = 0;
+#else
+    memset(&sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    sdev.host = scp.host = gdth_ctr_vtab[vh];
+    sdev.id = scp.target = sdev.host->this_id;
+    scp.device = &sdev;
+#endif
 
     if (length >= 4) {
         if (strncmp(buffer,"gdth",4) == 0) {
@@ -61,20 +64,29 @@
         } else if (piowr->magic == GDTIOCTL_MAGIC) {
             ret_val = gdth_set_bin_info( buffer, length, hanum, scp );
         } else {
-            printk("GDT: Wrong signature: %6s\n",buffer);
+            printk("GDT: Wrong signature %x (%x required)!\n",
+                   piowr->magic, GDTIOCTL_MAGIC);
+            if (piowr->magic > GDTIOCTL_MAGIC)
+                printk("GDT: Please update your driver.\n");
+            else
+                printk("GDT: Please update your tool.\n");
             ret_val = -EINVAL;
         }
     } else {
         ret_val = -EINVAL;
     }
-
+#if LINUX_VERSION_CODE >= 0x020322
     scsi_release_command(scp);
     scsi_free_host_dev(sdev);
-
+#endif
     return ret_val;
 }
          
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd * scp)
+#if LINUX_VERSION_CODE >= 0x020322
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
+#else
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
+#endif
 {
     int             orig_length, drive, wb_mode;
     int             i, found;
@@ -82,6 +94,10 @@
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
 
+    char            cmnd[MAX_COMMAND_SIZE];
+    memset(cmnd, 0xff, 12);
+    memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
+
     TRACE2(("gdth_set_asc_info() ha %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
     orig_length = length + 5;
@@ -108,13 +124,15 @@
                 if (drive != -1 && i != drive)
                     continue;
                 found = TRUE;
-                gdtcmd.BoardNode = LOCALBOARD;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_FLUSH;
                 gdtcmd.u.cache.DeviceNo = i;
                 gdtcmd.u.cache.BlockNo = 1;
-                gdtcmd.u.cache.sg_canz = 0;
-                gdth_do_cmd(scp, &gdtcmd, 30);
+#if LINUX_VERSION_CODE >= 0x020322
+                gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+#else
+                gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+#endif
             }
         }
         if (!found)
@@ -159,7 +177,6 @@
             return(-EBUSY);
         pcpar = (gdth_cpar_str *)ha->pscratch;
         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
-        gdtcmd.BoardNode = LOCALBOARD;
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_IOCTL;
         gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar);
@@ -167,7 +184,11 @@
         gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
         gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
         pcpar->write_back = wb_mode==1 ? 0:1;
-        gdth_do_cmd(scp, &gdtcmd, 30);
+#if LINUX_VERSION_CODE >= 0x020322
+        gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+#else
+        gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+#endif
         gdth_ioctl_free(hanum);
         printk("Done.\n");
         return(orig_length);
@@ -177,17 +198,27 @@
     return(-EINVAL);
 }
 
-static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd * scp)
+#if LINUX_VERSION_CODE >= 0x020322
+static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
+#else
+static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
+#endif
 {
     unchar          i, j;
+    ushort          k, hdr_cnt, status;
     gdth_ha_str     *ha;
     gdth_iowr_str   *piowr;
     gdth_iord_str   *piord;
     gdth_cmd_str    *pcmd;
     gdth_evt_str    *pevt;
-    ulong32         *ppadd, add_size;
-    ulong32         *ppadd2, add_size2;
+    ulong32         *ppadd, add_size, *ppadd2, add_size2, info;
     ulong           flags;
+    gdth_cmd_str    gdtcmd;
+    int             drv_cyls, drv_hds, drv_secs;
+ 
+    char            cmnd[MAX_COMMAND_SIZE];   
+    memset(cmnd, 0xff, 12);
+    memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
 
     TRACE2(("gdth_set_bin_info() ha %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -250,8 +281,13 @@
             *ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
         }
         /* do IOCTL */
-        gdth_do_cmd(scp, pcmd, piowr->timeout);
-        piord->status = (ulong32)scp->SCp.Message;
+#if LINUX_VERSION_CODE >= 0x020322
+        gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
+        piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
+#else
+        gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
+        piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
+#endif
         break;
 
       case GDTIOCTL_DRVERS:
@@ -371,10 +407,10 @@
                 pevt->event_data.size = sizeof(pevt->event_data.eu.async);
                 gdth_log_event(&pevt->event_data, NULL);
             }
-	    GDTH_LOCK_HA(ha, flags);
+            GDTH_LOCK_HA(ha, flags);
             gdth_store_event(ha, pevt->event_source, pevt->event_idx,
                              &pevt->event_data);
-	    GDTH_UNLOCK_HA(ha, flags);
+            GDTH_UNLOCK_HA(ha, flags);
         } else if (piowr->iu.event.erase == 0xfe) {
             gdth_clear_events();
         } else if (piowr->iu.event.erase == 0) {
@@ -390,11 +426,236 @@
         piord->status = S_OK;
         break;
 
+      case GDTIOCTL_SCSI:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+        memcpy(cmnd, piowr->iu.scsi.cmd, 12);
+#if LINUX_VERSION_CODE >= 0x020322
+        scp->target = piowr->iu.scsi.target;
+        scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+        scp->cmd_len = piowr->iu.scsi.cmd_len;
+        gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
+        piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
+#else
+        scp.target = piowr->iu.scsi.target;
+        scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+        scp.cmd_len = piowr->iu.scsi.cmd_len;
+        gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
+        piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
+#endif
+        break;
+
+      case GDTIOCTL_RESET_BUS:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+#if LINUX_VERSION_CODE >= 0x020322
+        scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+        piord->status = (ulong32)gdth_eh_bus_reset( scp );
+        if (piord->status == SUCCESS)
+            piord->status = S_OK;
+        else
+            piord->status = S_GENERR;
+#elif LINUX_VERSION_CODE >= 0x02015F
+        scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
+        piord->status = (ulong32)gdth_eh_bus_reset( &scp );
+        if (piord->status == SUCCESS)
+            piord->status = S_OK;
+        else
+            piord->status = S_GENERR;
+#else
+        piord->status = S_OK;
+#endif
+        break;
+
+      case GDTIOCTL_HDRLIST:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+        piord->status = S_OK;
+        for (i = 0; i < MAX_HDRIVES; ++i) {
+            if (ha->hdr[i].present) {
+                piord->iu.hdr_list[i].bus = ha->virt_bus;
+                piord->iu.hdr_list[i].target = i;
+                piord->iu.hdr_list[i].lun = 0;
+                piord->iu.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+                if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {  
+                    gdtcmd.Service = CACHESERVICE;
+                    gdtcmd.OpCode = GDT_CLUST_INFO;
+                    gdtcmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020322
+                    gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                    if (scp->SCp.Status == S_OK)
+                        piord->iu.hdr_list[i].cluster_type = 
+                            (unchar)scp->SCp.Message;
+#else
+                    gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                    if (scp.SCp.Status == S_OK)
+                        piord->iu.hdr_list[i].cluster_type = 
+                            (unchar)scp.SCp.Message;
+#endif
+                }
+            } else {
+                piord->iu.hdr_list[i].bus = 0xff;
+            }
+        }
+        break;
+
+      case GDTIOCTL_RESCAN:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+        piord->status = S_OK;
+        if (piowr->iu.rescan.flag == 0) {
+            /* old method: scan all host drives 
+               re-initialize cache service to get host drive count
+            */
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_INIT;
+            gdtcmd.u.cache.DeviceNo = LINUX_OS;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status; 
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            if (status != S_OK)
+                break;
+            k = 0;
+            hdr_cnt = (ushort)info;
+        } else {
+            k = piowr->iu.rescan.hdr_no;
+            hdr_cnt = k + 1;
+        }
+        if (hdr_cnt > MAX_HDRIVES)
+            hdr_cnt = MAX_HDRIVES;
+        /* scanning for host drives */
+        for (; k < hdr_cnt; ++k) {
+            /* info about host drive */
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_INFO;
+            gdtcmd.u.cache.DeviceNo = k;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status; 
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            piord->iu.hdr_list[k].bus = ha->virt_bus;
+            piord->iu.hdr_list[k].target = k;
+            piord->iu.hdr_list[k].lun = 0;
+            if (status != S_OK) {
+                ha->hdr[k].present = FALSE;
+            } else {
+                ha->hdr[k].present = TRUE;
+                ha->hdr[k].size = info;
+                /* evaluate mapping (sectors per head, heads per cylinder) */
+                ha->hdr[k].size &= ~SECS32;
+                gdth_eval_mapping(ha->hdr[k].size,&drv_cyls,&drv_hds,&drv_secs);
+                ha->hdr[k].heads = (unchar)drv_hds;
+                ha->hdr[k].secs = (unchar)drv_secs;
+                /* round size */
+                ha->hdr[k].size = drv_cyls * drv_hds * drv_secs;
+            }
+            GDTH_UNLOCK_HA(ha, flags);
+            if (status != S_OK)
+                continue;       /* next host drive */
+
+            /* devtype, cluster info, R/W attributes */
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_DEVTYPE;
+            gdtcmd.u.cache.DeviceNo = k;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status; 
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[k].devtype = 0;
+            if (status == S_OK)
+                ha->hdr[k].devtype = (ushort)info;
+            GDTH_UNLOCK_HA(ha, flags);
+
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_CLUST_INFO;
+            gdtcmd.u.cache.DeviceNo = k;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status; 
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[k].cluster_type = 0;
+            if (status == S_OK && !shared_access)
+                ha->hdr[k].cluster_type = (ushort)info;
+            GDTH_UNLOCK_HA(ha, flags);
+            piord->iu.hdr_list[k].cluster_type = ha->hdr[k].cluster_type;
+
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_RW_ATTRIBS;
+            gdtcmd.u.cache.DeviceNo = k;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp->SCp.Status; 
+            info = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            status = (ushort)scp.SCp.Status;
+            info = (ulong32)scp.SCp.Message;
+#endif
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[k].rw_attribs = 0;
+            if (status == S_OK)
+                ha->hdr[k].rw_attribs = (ushort)info;
+            GDTH_UNLOCK_HA(ha, flags);
+        }
+        break;
+
+      case GDTIOCTL_RESET_DRV:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+        piord->status = S_OK;
+        i = piowr->iu.scsi.target;
+        if (ha->hdr[i].present) {
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_CLUST_RESET;
+            gdtcmd.u.cache.DeviceNo = i;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
+#endif
+        }
+        break;
+
       default:
         return(-EINVAL);
     }
-    /* we return a buffer ID to detect the right buffer during READ-IOCTL */
-    return 1;
+    return length;
 }
 
 static int gdth_get_info(char *buffer,char **start,off_t offset,
@@ -410,8 +671,13 @@
 
     gdth_cmd_str gdtcmd;
     gdth_evt_str estr;
-    Scsi_Cmnd  * scp;
+#if LINUX_VERSION_CODE >= 0x020322
+    Scsi_Cmnd *scp;
     Scsi_Device *sdev;
+#else
+    Scsi_Cmnd scp;
+    Scsi_Device sdev;
+#endif
     char hrec[161];
     struct timeval tv;
 
@@ -422,17 +688,28 @@
     gdth_cdrinfo_str *pcdi;
     gdth_hget_str *phg;
 
+    char cmnd[MAX_COMMAND_SIZE];
+    memset(cmnd, 0xff, 12);
+    memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
+
     TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
     ha = HADATA(gdth_ctr_tab[hanum]);
-    id = length;
 
+#if LINUX_VERSION_CODE >= 0x020322
     sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
     scp  = scsi_allocate_device(sdev, 1, FALSE);
     scp->cmd_len = 12;
     scp->use_sg = 0;
+#else
+    memset(&sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    sdev.host = scp.host = gdth_ctr_vtab[vh];
+    sdev.id = scp.target = sdev.host->this_id;
+    scp.device = &sdev;
+#endif
 
-    /* look for buffer ID in length */
-    if (id > 1) {
+    /* ioctl from tool? */
+    if (!gdth_ioctl_check_bin(hanum, (ushort)length)) {
         /* request is i.e. "cat /proc/scsi/gdth/0" */ 
         /* format: %-15s\t%-10s\t%-15s\t%s */
         /* driver parameters */
@@ -457,17 +734,13 @@
                        max_ids, hdr_channel);
         len += size;  pos = begin + len;
 
-        if (pos < offset) {
-            len = 0;
-            begin = pos;
-        }
-        if (pos > offset + length)
-            goto stop_output;
-
         /* controller information */
         size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
         len += size;  pos = begin + len;
-        strcpy(hrec, ha->binfo.type_string);
+        if (virt_ctr)
+            sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
+        else
+            strcpy(hrec, ha->binfo.type_string);
         size = sprintf(buffer+len,
                        " Number:       \t%d         \tName:          \t%s\n",
                        hanum, hrec);
@@ -503,17 +776,10 @@
                            ha->binfo.ser_no, ha->binfo.memsize / 1024);
             len += size;  pos = begin + len;
 
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-            if (pos > offset + length)
-                goto stop_output;
-
             /* 2. about physical devices */
             size = sprintf(buffer+len,"\nPhysical Devices:");
             len += size;  pos = begin + len;
-	    flag = FALSE;
+            flag = FALSE;
             
             if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
                 goto stop_output;
@@ -521,7 +787,6 @@
                 /* 2.a statistics (and retries/reassigns) */
                 TRACE2(("pdr_statistics() chn %d\n",i));                
                 pds = (gdth_dskstat_str *)(ha->pscratch + GDTH_SCRATCH/4);
-                gdtcmd.BoardNode = LOCALBOARD;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
                 gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
@@ -535,11 +800,16 @@
                     sizeof(pds->list[0]);
                 if (pds->entries > cnt)
                     pds->entries = cnt;
-                gdth_do_cmd(scp, &gdtcmd, 30);
-                if (scp->SCp.Message != S_OK) 
+#if LINUX_VERSION_CODE >= 0x020322
+                gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                if (scp->SCp.Status != S_OK) 
+#else
+                gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                if (scp.SCp.Status != S_OK) 
+#endif
+                { 
                     pds->count = 0;
-                TRACE2(("pdr_statistics() entries %d status %d\n",
-                        pds->count, scp->SCp.Message));
+                }
 
                 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
                 for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
@@ -547,7 +817,6 @@
                     TRACE2(("scsi_drv_info() chn %d dev %d\n",
                         i, ha->raw[i].id_list[j]));             
                     pdi = (gdth_diskinfo_str *)ha->pscratch;
-                    gdtcmd.BoardNode = LOCALBOARD;
                     gdtcmd.Service = CACHESERVICE;
                     gdtcmd.OpCode = GDT_IOCTL;
                     gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
@@ -555,8 +824,14 @@
                     gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
                     gdtcmd.u.ioctl.channel = 
                         ha->raw[i].address | ha->raw[i].id_list[j];
-                    gdth_do_cmd(scp, &gdtcmd, 30);
-                    if (scp->SCp.Message == S_OK) {
+#if LINUX_VERSION_CODE >= 0x020322
+                    gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                    if (scp->SCp.Status == S_OK) 
+#else
+                    gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                    if (scp.SCp.Status == S_OK) 
+#endif
+                    {
                         strncpy(hrec,pdi->vendor,8);
                         strncpy(hrec+8,pdi->product,16);
                         strncpy(hrec+24,pdi->revision,4);
@@ -565,7 +840,7 @@
                                        "\n Chn/ID/LUN:   \t%c/%02d/%d    \tName:          \t%s\n",
                                        'A'+i,pdi->target_id,pdi->lun,hrec);
                         len += size;  pos = begin + len;
-			flag = TRUE;
+                        flag = TRUE;
                         pdi->no_ldrive &= 0xffff;
                         if (pdi->no_ldrive == 0xffff)
                             strcpy(hrec,"--");
@@ -597,7 +872,6 @@
                         TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
                                 i, ha->raw[i].id_list[j]));             
                         pdef = (gdth_defcnt_str *)ha->pscratch;
-                        gdtcmd.BoardNode = LOCALBOARD;
                         gdtcmd.Service = CACHESERVICE;
                         gdtcmd.OpCode = GDT_IOCTL;
                         gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
@@ -606,37 +880,43 @@
                         gdtcmd.u.ioctl.channel = 
                             ha->raw[i].address | ha->raw[i].id_list[j];
                         pdef->sddc_type = 0x08;
-                        gdth_do_cmd(scp, &gdtcmd, 30);
-                        if (scp->SCp.Message == S_OK) {
+#if LINUX_VERSION_CODE >= 0x020322
+                        gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                        if (scp->SCp.Status == S_OK) 
+#else
+                        gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                        if (scp.SCp.Status == S_OK) 
+#endif
+                        {
                             size = sprintf(buffer+len,
                                            " Grown Defects:\t%d\n",
                                            pdef->sddc_cnt);
                             len += size;  pos = begin + len;
                         }
                     }
+                    if (pos < offset) {
+                        len = 0;
+                        begin = pos;
+                    }
+                    if (pos > offset + length)
+                        goto stop_output;
                 }
             }
             gdth_ioctl_free(hanum);
 
-	    if (!flag) {
-		size = sprintf(buffer+len, "\n --\n");
-		len += size;  pos = begin + len;
-	    }
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
+            if (!flag) {
+                size = sprintf(buffer+len, "\n --\n");
+                len += size;  pos = begin + len;
             }
-            if (pos > offset + length)
-                goto stop_output;
 
             /* 3. about logical drives */
             size = sprintf(buffer+len,"\nLogical Drives:");
             len += size;  pos = begin + len;
-	    flag = FALSE;
+            flag = FALSE;
 
             if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
                 goto stop_output;
-            for (i = 0; i < MAX_HDRIVES; ++i) {
+            for (i = 0; i < MAX_LDRIVES; ++i) {
                 if (!ha->hdr[i].is_logdrv)
                     continue;
                 drv_no = i;
@@ -646,16 +926,22 @@
                     /* 3.a log. drive info */
                     TRACE2(("cache_drv_info() drive no %d\n",drv_no));
                     pcdi = (gdth_cdrinfo_str *)ha->pscratch;
-                    gdtcmd.BoardNode = LOCALBOARD;
                     gdtcmd.Service = CACHESERVICE;
                     gdtcmd.OpCode = GDT_IOCTL;
                     gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
                     gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
                     gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
                     gdtcmd.u.ioctl.channel = drv_no;
-                    gdth_do_cmd(scp, &gdtcmd, 30);
-                    if (scp->SCp.Message != S_OK)
+#if LINUX_VERSION_CODE >= 0x020322
+                    gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                    if (scp->SCp.Status != S_OK)
+#else
+                    gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                    if (scp.SCp.Status != S_OK)
+#endif
+                    {
                         break;
+                    }
                     pcdi->ld_dtype >>= 16;
                     j++;
                     if (pcdi->ld_dtype > 2) {
@@ -674,7 +960,7 @@
                                        "\n Number:       \t%-2d        \tStatus:        \t%s\n",
                                        drv_no, hrec);
                         len += size;  pos = begin + len;
-			flag = TRUE;
+                        flag = TRUE;
                         no_mdrv = pcdi->cd_ldcnt;
                         if (no_mdrv > 1 || pcdi->ld_slave != -1) {
                             is_mirr = TRUE;
@@ -700,6 +986,12 @@
                         len += size;  pos = begin + len;
                     }
                     drv_no = pcdi->ld_slave;
+                    if (pos < offset) {
+                        len = 0;
+                        begin = pos;
+                    }
+                    if (pos > offset + length)
+                        goto stop_output;
                 } while (drv_no != -1);
                 
                 if (is_mirr) {
@@ -716,42 +1008,47 @@
                 size = sprintf(buffer+len,
                                " To Array Drv.:\t%s\n", hrec);
                 len += size;  pos = begin + len;
+                if (pos < offset) {
+                    len = 0;
+                    begin = pos;
+                }
+                if (pos > offset + length)
+                    goto stop_output;
             }       
             gdth_ioctl_free(hanum);
         
-	    if (!flag) {
-		size = sprintf(buffer+len, "\n --\n");
-		len += size;  pos = begin + len;
-	    }	
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
-            }
-            if (pos > offset + length)
-                goto stop_output;
+            if (!flag) {
+                size = sprintf(buffer+len, "\n --\n");
+                len += size;  pos = begin + len;
+            }   
 
             /* 4. about array drives */
             size = sprintf(buffer+len,"\nArray Drives:");
             len += size;  pos = begin + len;
-	    flag = FALSE;
+            flag = FALSE;
 
             if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
                 goto stop_output;
-            for (i = 0; i < MAX_HDRIVES; ++i) {
+            for (i = 0; i < MAX_LDRIVES; ++i) {
                 if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
                     continue;
                 /* 4.a array drive info */
                 TRACE2(("array_info() drive no %d\n",i));
                 pai = (gdth_arrayinf_str *)ha->pscratch;
-                gdtcmd.BoardNode = LOCALBOARD;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
                 gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
                 gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
                 gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
                 gdtcmd.u.ioctl.channel = i;
-                gdth_do_cmd(scp, &gdtcmd, 30);
-                if (scp->SCp.Message == S_OK) {
+#if LINUX_VERSION_CODE >= 0x020322
+                gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                if (scp->SCp.Status == S_OK) 
+#else
+                gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                if (scp.SCp.Status == S_OK) 
+#endif
+                {
                     if (pai->ai_state == 0)
                         strcpy(hrec, "idle");
                     else if (pai->ai_state == 2)
@@ -787,36 +1084,35 @@
                                    pai->ai_size/(1024*1024/pai->ai_secsize),
                                    hrec);
                     len += size;  pos = begin + len;
+                    if (pos < offset) {
+                        len = 0;
+                        begin = pos;
+                    }
+                    if (pos > offset + length)
+                        goto stop_output;
                 }
             }
             gdth_ioctl_free(hanum);
         
-	    if (!flag) {
-		size = sprintf(buffer+len, "\n --\n");
-		len += size;  pos = begin + len;
-	    }
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
+            if (!flag) {
+                size = sprintf(buffer+len, "\n --\n");
+                len += size;  pos = begin + len;
             }
-            if (pos > offset + length)
-                goto stop_output;
 
             /* 5. about host drives */
             size = sprintf(buffer+len,"\nHost Drives:");
             len += size;  pos = begin + len;
-	    flag = FALSE;
+            flag = FALSE;
 
             if (!gdth_ioctl_alloc(hanum, GDTH_SCRATCH))
                 goto stop_output;
-            for (i = 0; i < MAX_HDRIVES; ++i) {
+            for (i = 0; i < MAX_LDRIVES; ++i) {
                 if (!ha->hdr[i].is_logdrv || 
                     (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
                     continue;
                 /* 5.a get host drive list */
                 TRACE2(("host_get() drv_no %d\n",i));           
                 phg = (gdth_hget_str *)ha->pscratch;
-                gdtcmd.BoardNode = LOCALBOARD;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
                 gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
@@ -825,23 +1121,27 @@
                 gdtcmd.u.ioctl.channel = i;
                 phg->entries = MAX_HDRIVES;
                 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 
-                gdth_do_cmd(scp, &gdtcmd, 30);
-                if (scp->SCp.Message != S_OK) {
+#if LINUX_VERSION_CODE >= 0x020322
+                gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+                if (scp->SCp.Status != S_OK) 
+#else
+                gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+                if (scp.SCp.Status != S_OK) 
+#endif
+                {
                     ha->hdr[i].ldr_no = i;
                     ha->hdr[i].rw_attribs = 0;
                     ha->hdr[i].start_sec = 0;
                 } else {
                     for (j = 0; j < phg->entries; ++j) {
                         k = phg->entry[j].host_drive;
-                        if (k >= MAX_HDRIVES)
+                        if (k >= MAX_LDRIVES)
                             continue;
                         ha->hdr[k].ldr_no = phg->entry[j].log_drive;
                         ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
                         ha->hdr[k].start_sec = phg->entry[j].start_sec;
                     }
                 }
-                TRACE2(("host_get entries %d status %d\n",
-                        phg->entries, scp->SCp.Message));
             }
             gdth_ioctl_free(hanum);
 
@@ -853,24 +1153,24 @@
                                "\n Number:       \t%-2d        \tArr/Log. Drive:\t%d\n",
                                i, ha->hdr[i].ldr_no);
                 len += size;  pos = begin + len;
-		flag = TRUE;
+                flag = TRUE;
 
                 size = sprintf(buffer+len,
                                " Capacity [MB]:\t%-6d    \tStart Sector:  \t%d\n",
                                ha->hdr[i].size/2048, ha->hdr[i].start_sec);
                 len += size;  pos = begin + len;
+                if (pos < offset) {
+                    len = 0;
+                    begin = pos;
+                }
+                if (pos > offset + length)
+                    goto stop_output;
             }
         
-	    if (!flag) {
-		size = sprintf(buffer+len, "\n --\n");
-		len += size;  pos = begin + len;
-	    }
-            if (pos < offset) {
-                len = 0;
-                begin = pos;
+            if (!flag) {
+                size = sprintf(buffer+len, "\n --\n");
+                len += size;  pos = begin + len;
             }
-            if (pos > offset + length)
-                goto stop_output;
         }
 
         /* controller events */
@@ -886,7 +1186,7 @@
                 gdth_log_event(&estr.event_data, hrec);
                 do_gettimeofday(&tv);
                 sec = (int)(tv.tv_sec - estr.first_stamp);
-		if (sec < 0) sec = 0;
+                if (sec < 0) sec = 0;
                 size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
                                sec/3600, sec%3600/60, sec%60, hrec);
                 len += size;  pos = begin + len;
@@ -908,21 +1208,14 @@
         length = piord->size;
         memcpy(buffer+len, (char *)piord, length);
         gdth_ioctl_free(hanum);
-        len += length; pos = begin + len;
-
-        if (pos < offset) {
-            len = 0;
-            begin = pos;
-        }
-        if (pos > offset + length)
-            goto stop_output;
+        len = length; 
     }
 
 stop_output:
-
+#if LINUX_VERSION_CODE >= 0x020322
     scsi_release_command(scp);
     scsi_free_host_dev(sdev);
-
+#endif
     *start = buffer +(offset-begin);
     len -= (offset-begin);
     if (len > length)
@@ -932,18 +1225,33 @@
     return(len);
 }
 
-static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *gdtcmd,int timeout)
+static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, 
+                        char *cmnd, int timeout)
 {
-    char cmnd[MAX_COMMAND_SIZE];
+    unsigned bufflen;
+#if LINUX_VERSION_CODE >= 0x020322
     DECLARE_MUTEX_LOCKED(sem);
+#else
+    struct semaphore sem = MUTEX_LOCKED;
+#endif
 
     TRACE2(("gdth_do_cmd()\n"));
-    memset(cmnd, 0, MAX_COMMAND_SIZE);
+    if (gdtcmd != NULL) { 
+        scp->SCp.this_residual = IOCTL_PRI;
+        bufflen = sizeof(gdth_cmd_str);
+    } else {
+        scp->SCp.this_residual = DEFAULT_PRI;
+        bufflen = 0;
+    }
     scp->request.rq_status = RQ_SCSI_BUSY;
     scp->request.sem = &sem;
-    scp->SCp.this_residual = IOCTL_PRI;
-    scsi_do_cmd(scp, cmnd, gdtcmd, sizeof(gdth_cmd_str), 
-                gdth_scsi_done, timeout*HZ, 1);
+#if LINUX_VERSION_CODE >= 0x020322
+    scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
+#else
+    GDTH_LOCK_SCSI_DOCMD();
+    scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
+    GDTH_UNLOCK_SCSI_DOCMD();
+#endif
     down(&sem);
 }
 
@@ -992,21 +1300,41 @@
     GDTH_UNLOCK_HA(ha, flags);
 }
 
+static int gdth_ioctl_check_bin(int hanum, ushort size)
+{
+    gdth_ha_str *ha;
+    ulong flags;
+    int ret_val;
+
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    GDTH_LOCK_HA(ha, flags);
+
+    ret_val = FALSE;
+    if (ha->scratch_busy) {
+        if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size)
+            ret_val = TRUE;
+    }
+    GDTH_UNLOCK_HA(ha, flags);
+    return ret_val;
+}
+
+
 static void gdth_wait_completion(int hanum, int busnum, int id)
 {
     gdth_ha_str *ha;
     ulong flags;
     int i;
     Scsi_Cmnd *scp;
+    unchar b;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         scp = ha->cmd_tab[i].cmnd;
-        if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
-            scp->channel == (unchar)busnum)
-        {
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        if (!SPECIAL_SCP(scp) && scp->target == (unchar)id && 
+            b == (unchar)busnum) {
             scp->SCp.have_data_in = 0;
             GDTH_UNLOCK_HA(ha, flags);
             while (!scp->SCp.have_data_in)
@@ -1025,14 +1353,14 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
+    unchar b;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        if (scp->target == (unchar)id &&
-            scp->channel == (unchar)busnum)
-        {
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        if (scp->target == (unchar)id && b == (unchar)busnum) {
             TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
@@ -1045,14 +1373,14 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
+    unchar b;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        if (scp->target == (unchar)id &&
-            scp->channel == (unchar)busnum)
-        {
+        b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        if (scp->target == (unchar)id && b == (unchar)busnum) {
             TRACE2(("gdth_start_timeout(): update_timeout()\n"));
             gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
         }
@@ -1067,6 +1395,7 @@
     oldto = scp->timeout_per_command;
     scp->timeout_per_command = timeout;
 
+#if LINUX_VERSION_CODE >= 0x02014B
     if (timeout == 0) {
         del_timer(&scp->eh_timeout);
         scp->eh_timeout.data = (unsigned long) NULL;
@@ -1078,5 +1407,17 @@
         scp->eh_timeout.expires = jiffies + timeout;
         add_timer(&scp->eh_timeout);
     }
+#else
+    if (timeout > 0) {
+        if (timer_table[SCSI_TIMER].expires == 0) {
+            timer_table[SCSI_TIMER].expires = jiffies + timeout;
+            timer_active |= 1 << SCSI_TIMER;
+        } else {
+            if (jiffies + timeout < timer_table[SCSI_TIMER].expires)
+                timer_table[SCSI_TIMER].expires = jiffies + timeout;
+        }
+    }
+#endif
+
     return oldto;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/gdth_proc.h linux/drivers/scsi/gdth_proc.h
--- v2.4.4/linux/drivers/scsi/gdth_proc.h	Fri Jan 21 09:48:11 2000
+++ linux/drivers/scsi/gdth_proc.h	Sat May 19 17:43:06 2001
@@ -2,23 +2,31 @@
 #define _GDTH_PROC_H
 
 /* gdth_proc.h 
- * $Id: gdth_proc.h,v 1.6 1999/03/05 14:32:36 achim Exp $
+ * $Id: gdth_proc.h,v 1.10 2000/07/24 09:30:01 achim Exp $
  */
 
 static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd * scp);
-static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd * scp);
 static int gdth_get_info(char *buffer,char **start,off_t offset,
                          int length,int vh,int hanum,int busnum);
 
+#if LINUX_VERSION_CODE >= 0x020322
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
+static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
+#else 
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
+static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
+#endif
+static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
+                        char *cmnd, int timeout);
+
 static int gdth_ioctl_alloc(int hanum, ushort size);
 static void gdth_ioctl_free(int hanum);
+static int gdth_ioctl_check_bin(int hanum, ushort size);
 static void gdth_wait_completion(int hanum, int busnum, int id);
 static void gdth_stop_timeout(int hanum, int busnum, int id);
 static void gdth_start_timeout(int hanum, int busnum, int id);
 static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
 
-static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *cmd,int timeout);
 void gdth_scsi_done(Scsi_Cmnd *scp);
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c
--- v2.4.4/linux/drivers/scsi/ibmmca.c	Fri Mar  2 18:38:38 2001
+++ linux/drivers/scsi/ibmmca.c	Tue May  1 16:05:00 2001
@@ -50,7 +50,7 @@
 
 /* driver debugging - #undef all for normal operation */
 /* if defined: count interrupts and ignore this special one: */
-#undef	IM_DEBUG_TIMEOUT	50            
+#undef	IM_DEBUG_TIMEOUT	//50            
 #define TIMEOUT_PUN	0
 #define TIMEOUT_LUN	0
 /* verbose interrupt: */
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- v2.4.4/linux/drivers/scsi/ips.c	Fri Apr 27 13:59:18 2001
+++ linux/drivers/scsi/ips.c	Sat May 19 17:43:06 2001
@@ -86,6 +86,20 @@
 /*            Merge in changes through kernel 2.4.0test1ac21                 */
 /* 4.20.13  - Fix some failure cases / reset code                            */
 /*          - Hook into the reboot_notifier to flush the controller cache    */
+/* 4.50.01  - Fix problem when there is a hole in logical drive numbering   */
+/* 4.70.09  - Use a Common ( Large Buffer ) for Flashing from the JCRM CD    */
+/*          - Add IPSSEND Flash Support                                      */
+/*          - Set Sense Data for Unknown SCSI Command                        */
+/*          - Use Slot Number from NVRAM Page 5                              */
+/*          - Restore caller's DCDB Structure                                */
+/* 4.70.12  - Corrective actions for bad controller ( during initialization )*/
+/* 4.70.13  - Don't Send CDB's if we already know the device is not present  */
+/*          - Don't release HA Lock in ips_next() until SC taken off queue   */
+/*          - Unregister SCSI device in ips_release()                        */
+/* 4.70.15  - Fix Breakup for very large ( non-SG ) requests in ips_done()   */
+/* 4.71.00  - Change all memory allocations to not use GFP_DMA flag          */
+/*            Code Clean-Up for 2.4.x kernel                                 */
+/* 4.72.00  - Allow for a Scatter-Gather Element to exceed MAX_XFER Size     */
 /*                                                                           */
 /*****************************************************************************/
 
@@ -110,10 +124,8 @@
  * nocmdline            - Turn off passthru support
  * noi2o                - Don't use I2O Queues (ServeRAID 4 only)
  * nommap               - Don't use memory mapped I/O
+ * ioctlsize            - Initial size of the IOCTL buffer
  */
-  
-
-#include <linux/module.h>
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
@@ -122,7 +134,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/ioport.h>
+#include <linux/ioport.h> 
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
@@ -130,6 +142,8 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/reboot.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
 
 #include <linux/blk.h>
 #include <linux/types.h>
@@ -143,6 +157,8 @@
 #include "hosts.h"
 #include "ips.h"
 
+#include <linux/module.h>
+
 #include <linux/stat.h>
 #include <linux/config.h>
 
@@ -166,8 +182,9 @@
 /*
  * DRIVER_VER
  */
-#define IPS_VERSION_HIGH        "4.20"
-#define IPS_VERSION_LOW         ".20 "
+#define IPS_VERSION_HIGH        "4.72"
+#define IPS_VERSION_LOW         ".00 "
+
 
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
 struct proc_dir_entry proc_scsi_ips = {
@@ -214,6 +231,10 @@
 static int          ips_force_i2o = 1;               /* Always use I2O command delivery */
 static int          ips_resetcontroller = 1;         /* Reset the controller            */
 static int          ips_cmdline = 1;                 /* Support for passthru            */
+static int          ips_ioctlsize = IPS_IOCTL_SIZE;  /* Size of the ioctl buffer        */
+static int          ips_cd_boot = 0;                 /* Booting from ServeRAID Manager CD */
+static char        *ips_FlashData = NULL;            /* CD Boot - Flash Data Buffer      */
+static int          ips_FlashDataInUse = 0;          /* CD Boot - Flash Data In Use Flag */
 
 #ifdef IPS_DEBUG
 static int          ips_debug = 0;                   /* Debug mode                      */
@@ -224,7 +245,7 @@
  */
 static int ips_halt(struct notifier_block *nb, ulong event, void *buf);
 
-#define MAX_ADAPTER_NAME 9
+#define MAX_ADAPTER_NAME 11
 
 static char ips_adapter_name[][30] = {
    "ServeRAID",
@@ -235,7 +256,9 @@
    "ServeRAID 3L",
    "ServeRAID 4H",
    "ServeRAID 4M",
-   "ServeRAID 4L"
+   "ServeRAID 4L",
+   "ServeRAID 4Mx",
+   "ServeRAID 4Lx"
 };
 
 static struct notifier_block ips_notifier = {
@@ -347,6 +370,12 @@
 static u32 ips_statupd_copperhead(ips_ha_t *);
 static u32 ips_statupd_copperhead_memio(ips_ha_t *);
 static u32 ips_statupd_morpheus(ips_ha_t *);
+static void ips_flash_bios_section(void *);
+static void ips_flash_bios_segment(void *);
+static void ips_scheduled_flash_bios(void *);
+static void ips_create_nvrampage5(ips_ha_t *, IPS_NVRAM_P5 *);
+static void ips_get_bios_version(ips_ha_t *, int);
+static void ips_identify_controller(ips_ha_t *);
 static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
 static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);
 static void ips_enable_int_copperhead(ips_ha_t *);
@@ -380,15 +409,15 @@
 static inline ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *);
 static inline ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t *);
 static int ips_erase_bios(ips_ha_t *);
-static int ips_program_bios(ips_ha_t *, char *, int);
-static int ips_verify_bios(ips_ha_t *, char *, int);
+static int ips_program_bios(ips_ha_t *, char *, u32, u32);
+static int ips_verify_bios(ips_ha_t *, char *, u32, u32);
 static int ips_erase_bios_memio(ips_ha_t *);
-static int ips_program_bios_memio(ips_ha_t *, char *, int);
-static int ips_verify_bios_memio(ips_ha_t *, char *, int);
+static int ips_program_bios_memio(ips_ha_t *, char *, u32, u32);
+static int ips_verify_bios_memio(ips_ha_t *, char *, u32, u32);
 
 #ifndef NO_IPS_CMDLINE
 static int ips_is_passthru(Scsi_Cmnd *);
-static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *);
+static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
 static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
 static int ips_newusrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
 static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
@@ -432,6 +461,8 @@
       {"noi2o", &ips_force_i2o, 0},
       {"nommap", &ips_force_memio, 0},
       {"nocmdline", &ips_cmdline, 0},
+      {"ioctlsize", &ips_ioctlsize, IPS_IOCTL_SIZE},
+      {"cdboot", &ips_cd_boot, 0},
    };
 
    METHOD_TRACE("ips_setup", 1);
@@ -498,8 +529,10 @@
    u8                func;
    u8                irq;
    u16               deviceID[2];
+   u16               subdevice_id;
    int               i;
    int               j;
+   u32               count;
    char             *ioremap_ptr;
    char             *mem_ptr;
    struct pci_dev   *dev[2];
@@ -522,6 +555,16 @@
 #endif
 #endif
 
+   /* If Booting from the ServeRAID Manager CD, Allocate a large Flash  */
+   /* Buffer ( so we won't need to allocate one for each adapter ).     */
+    if ( ips_cd_boot ) {                                                            
+      ips_FlashData = ( char * ) __get_free_pages( GFP_KERNEL, 7 ); 
+      if (ips_FlashData == NULL) {
+         /* The validity of this pointer is checked in ips_make_passthru() before it is used */
+         printk( KERN_WARNING "ERROR: Can't Allocate Large Buffer for Flashing\n" );
+      }
+   }                                                                               
+
    SHT->proc_info = ips_proc_info;
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
    SHT->proc_dir = &proc_scsi_ips;
@@ -530,53 +573,53 @@
 #endif
 
 #if defined(CONFIG_PCI)
- 
+
    /* initalize number of controllers */
    ips_num_controllers = 0;
    ips_next_controller = 0;
    ips_released_controllers = 0;
- 
+
    if (!pci_present())
       return (0);
 
-   morpheus = pci_find_device(IPS_VENDORID, IPS_MORPHEUS_DEVICEID, morpheus);
-   trombone = pci_find_device(IPS_VENDORID, IPS_COPPERHEAD_DEVICEID, trombone);
-  
+   morpheus = pci_find_device(IPS_VENDORID, IPS_DEVICEID_MORPHEUS, morpheus);
+   trombone = pci_find_device(IPS_VENDORID, IPS_DEVICEID_COPPERHEAD, trombone);
+
    /* determine which controller to probe first */
    if (!morpheus) {
       /* we only have trombone */
       dev[0] = trombone;
       dev[1] = NULL;
-      deviceID[0] = IPS_COPPERHEAD_DEVICEID;
+      deviceID[0] = IPS_DEVICEID_COPPERHEAD;
    } else if (!trombone) {
       /* we only have morpheus */
       dev[0] = morpheus;
       dev[1] = NULL;
-      deviceID[0] = IPS_MORPHEUS_DEVICEID;
+      deviceID[0] = IPS_DEVICEID_MORPHEUS;
    } else {
       /* we have both in the system */
       if (trombone->bus < morpheus->bus) {
          dev[0] = trombone;
          dev[1] = morpheus;
-         deviceID[0] = IPS_COPPERHEAD_DEVICEID;
-         deviceID[1] = IPS_MORPHEUS_DEVICEID;
+         deviceID[0] = IPS_DEVICEID_COPPERHEAD;
+         deviceID[1] = IPS_DEVICEID_MORPHEUS;
       } else if (trombone->bus > morpheus->bus) {
          dev[0] = morpheus;
          dev[1] = trombone;
-         deviceID[0] = IPS_MORPHEUS_DEVICEID;
-         deviceID[1] = IPS_COPPERHEAD_DEVICEID;
+         deviceID[0] = IPS_DEVICEID_MORPHEUS;
+         deviceID[1] = IPS_DEVICEID_COPPERHEAD;
       } else {
          /* further detection required */
          if (trombone->devfn < morpheus->devfn) {
             dev[0] = trombone;
             dev[1] = morpheus;
-            deviceID[0] = IPS_COPPERHEAD_DEVICEID;
-            deviceID[1] = IPS_MORPHEUS_DEVICEID;
+            deviceID[0] = IPS_DEVICEID_COPPERHEAD;
+            deviceID[1] = IPS_DEVICEID_MORPHEUS;
          } else {
             dev[0] = morpheus;
             dev[1] = trombone;
-            deviceID[0] = IPS_MORPHEUS_DEVICEID;
-            deviceID[1] = IPS_COPPERHEAD_DEVICEID;
+            deviceID[0] = IPS_DEVICEID_MORPHEUS;
+            deviceID[1] = IPS_DEVICEID_COPPERHEAD;
          }
       }
    }
@@ -711,14 +754,14 @@
 
          /* get planer status */
          if (pci_read_config_word(dev[i], 0x04, &planer)) {
-           printk(KERN_WARNING "(%s%d) can't get planer status.\n",
+            printk(KERN_WARNING "(%s%d) can't get planer status.\n",
                    ips_name, ips_next_controller);
 
             ips_next_controller++;
 
             continue;
          }
- 
+
          /* check to see if an onboard planer controller is disabled */
          if (!(planer & 0x000C)) {
 
@@ -743,6 +786,20 @@
             continue;
          }
 
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,15)
+         /* get the subdevice id */
+         if (pci_read_config_word(dev[i], 0x2e, &subdevice_id)) {
+            printk(KERN_WARNING "(%s%d) can't get subdevice id.\n",
+                   ips_name, ips_next_controller);
+
+            ips_next_controller++;
+
+            continue;
+         }
+#else
+         subdevice_id = dev[i]->subsystem_device;
+#endif
+
          /* found a controller */
          sh = scsi_register(SHT, sizeof(ips_ha_t));
 
@@ -771,7 +828,7 @@
          ips_num_controllers++;
          ha->active = 1;
 
-         ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_ATOMIC|GFP_DMA);
+         ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_ATOMIC);
 
          if (!ha->enq) {
             printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n",
@@ -779,26 +836,33 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
             continue;
          }
 
-         ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_ATOMIC|GFP_DMA);
+         ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_ATOMIC);
 
          if (!ha->adapt) {
             printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n",
                    ips_name, ips_next_controller);
+
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
             continue;
          }
 
-         ha->conf = kmalloc(sizeof(IPS_CONF), GFP_ATOMIC|GFP_DMA);
+         ha->conf = kmalloc(sizeof(IPS_CONF), GFP_ATOMIC);
 
          if (!ha->conf) {
             printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n",
@@ -806,13 +870,16 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
             continue;
          }
 
-         ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_ATOMIC|GFP_DMA);
+         ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_ATOMIC);
 
          if (!ha->nvram) {
             printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n",
@@ -820,13 +887,16 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
             continue;
          }
 
-         ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_ATOMIC|GFP_DMA);
+         ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_ATOMIC);
 
          if (!ha->subsys) {
             printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n",
@@ -834,13 +904,16 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
             continue;
          }
 
-         ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_ATOMIC|GFP_DMA);
+         ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_ATOMIC);
 
          if (!ha->dummy) {
             printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n",
@@ -848,24 +921,29 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
             continue;
          }
 
-         ha->ioctl_data = kmalloc(IPS_IOCTL_SIZE, GFP_ATOMIC|GFP_DMA);
-         ha->ioctl_datasize = IPS_IOCTL_SIZE;
+         for (count = PAGE_SIZE, ha->ioctl_order = 0;
+              count < ips_ioctlsize;
+              ha->ioctl_order++, count <<= 1);
+
+         ha->ioctl_data = (char *) __get_free_pages(GFP_KERNEL, ha->ioctl_order);
+         ha->ioctl_datasize = count;
+
          if (!ha->ioctl_data) {
-            printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data - skipping controller\n",
+            printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data\n",
                    ips_name, ips_next_controller);
 
-            ha->active = 0;
-            ips_free(ha);
-            ips_next_controller++;
-            ips_num_controllers--;
-
-            continue;
+            ha->ioctl_data = NULL;
+            ha->ioctl_order = 0;
+            ha->ioctl_datasize = 0;
          }
 
          /* Store away needed values for later use */
@@ -879,7 +957,11 @@
          sh->cmd_per_lun = sh->hostt->cmd_per_lun;
          sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
          sh->use_clustering = sh->hostt->use_clustering;
-         scsi_set_pci_device(sh, dev[i]);
+/***** Implement the following if it gets into a future kernel
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,4)
+         sh->max_sectors = 128;
+#endif
+******/
 
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,32)
          sh->wish_block = FALSE;
@@ -895,7 +977,9 @@
          ha->ioremap_ptr = ioremap_ptr;
          ha->host_num = ips_next_controller;
          ha->revision_id = revision_id;
+         ha->slot_num = PCI_SLOT(dev[i]->devfn);
          ha->device_id = deviceID[i];
+         ha->subdevice_id = subdevice_id;
          ha->pcidev = dev[i];
 
          /*
@@ -962,6 +1046,9 @@
 
                ha->active = 0;
                ips_free(ha);
+               scsi_unregister(sh);
+               ips_ha[ips_next_controller] = 0;
+               ips_sh[ips_next_controller] = 0;
                ips_next_controller++;
                ips_num_controllers--;
 
@@ -976,6 +1063,9 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             ips_next_controller++;
             ips_num_controllers--;
 
@@ -985,7 +1075,7 @@
          /*
           * Allocate a temporary SCB for initialization
           */
-         ha->scbs = (ips_scb_t *) kmalloc(sizeof(ips_scb_t), GFP_ATOMIC|GFP_DMA);
+         ha->scbs = (ips_scb_t *) kmalloc(sizeof(ips_scb_t), GFP_ATOMIC);
          if (!ha->scbs) {
             /* couldn't allocate a temp SCB */
             printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
@@ -993,6 +1083,9 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             free_irq(ha->irq, ha);
             ips_next_controller++;
             ips_num_controllers--;
@@ -1001,7 +1094,7 @@
          }
 
          memset(ha->scbs, 0, sizeof(ips_scb_t));
-         ha->scbs->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC|GFP_DMA);
+         ha->scbs->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC);
          if (!ha->scbs->sg_list) {
             /* couldn't allocate a temp SCB S/G list */
             printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
@@ -1009,6 +1102,9 @@
 
             ha->active = 0;
             ips_free(ha);
+            scsi_unregister(sh);
+            ips_ha[ips_next_controller] = 0;
+            ips_sh[ips_next_controller] = 0;
             free_irq(ha->irq, ha);
             ips_next_controller++;
             ips_num_controllers--;
@@ -1027,6 +1123,13 @@
     * Controller init
     */
    for (i = 0; i < ips_next_controller; i++) {
+
+      if (ips_ha[i] == 0) {
+         printk(KERN_WARNING "(%s%d) ignoring bad controller\n",
+                ips_name, i);
+         continue;
+      }
+
       ha = ips_ha[i];
       sh = ips_sh[i];
 
@@ -1165,6 +1268,8 @@
    /* free IRQ */
    free_irq(ha->irq, ha);
 
+   scsi_unregister(sh);
+
    ips_released_controllers++;
 
    if (ips_num_controllers == ips_released_controllers)
@@ -1376,7 +1481,7 @@
    if (!ret) {
       Scsi_Cmnd *scsi_cmd;
 
-      printk(KERN_NOTICE 
+      printk(KERN_NOTICE
              "(%s%d) Controller reset failed - controller now offline.\n",
              ips_name, ha->host_num);
 
@@ -1408,7 +1513,7 @@
    if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
       Scsi_Cmnd *scsi_cmd;
 
-      printk(KERN_NOTICE 
+      printk(KERN_NOTICE
              "(%s%d) Controller reset failed - controller now offline.\n",
              ips_name, ha->host_num);
 
@@ -1622,17 +1727,29 @@
       kern_area = ha->ioctl_data;
       datasize = *((u32 *) &SC->cmnd[8]);
 
-      if (copy_to_user(user_area, kern_area, datasize) > 0) {
-         DEBUG_VAR(1, "(%s%d) passthru failed - unable to copy out user data",
-                   ips_name, ha->host_num);
+      if (datasize) {
+         if (copy_to_user(user_area, kern_area, datasize) > 0) {
+            DEBUG_VAR(1, "(%s%d) passthru failed - unable to copy out user data",
+                      ips_name, ha->host_num);
 
-         SC->result = DID_ERROR << 16;
-         SC->scsi_done(SC);
+            SC->result = DID_ERROR << 16;
+            SC->scsi_done(SC);
+         } else {
+            SC->scsi_done(SC);
+         }
       } else {
          SC->scsi_done(SC);
       }
    }
 
+   /* If We were using the CD Boot Flash Buffer, Restore the Old Values */
+   if ( ips_FlashData == ha->ioctl_data ) {                               
+      ha->ioctl_data = ha->save_ioctl_data;                           
+      ha->ioctl_order = ha->save_ioctl_order;                          
+      ha->ioctl_datasize = ha->save_ioctl_datasize;                       
+      ips_FlashDataInUse = 0;                                             
+   }
+
    return (0);
 }
 
@@ -1718,6 +1835,9 @@
             device->queue_depth = ha->max_cmds / count - 1;
          else
             device->queue_depth = 2;
+
+         if (device->queue_depth < 2)
+            device->queue_depth = 2;
       }
    }
 }
@@ -1979,10 +2099,11 @@
 
    /* Find our host structure */
    for (i = 0; i < ips_next_controller; i++) {
-      if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
-         ha = (ips_ha_t *) ips_sh[i]->hostdata;
-
-         break;
+      if (ips_sh[i]) {
+         if (ips_sh[i]->host_no == hostno) {
+            ha = (ips_ha_t *) ips_sh[i]->hostdata;
+            break;
+         }
       }
    }
 
@@ -2051,7 +2172,8 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
+ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb, int intr) {
+   IPS_NVRAM_P5    nvram;
    ips_passthru_t *pt;
 
    METHOD_TRACE("ips_make_passthru", 1);
@@ -2128,19 +2250,375 @@
             return (IPS_FAILURE);
          }
 
+         if ((pt->CoppCP.cmd.nvram.op_code == IPS_CMD_RW_NVRAM_PAGE) &&
+             (pt->CoppCP.cmd.nvram.page == 5) &&
+             (pt->CoppCP.cmd.nvram.write == 0)) {
+
+            if (pt->CmdBSize < sizeof(IPS_NVRAM_P5)) {
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            ips_get_bios_version(ha, IPS_INTR_IORL);
+            ips_create_nvrampage5(ha, &nvram);
+
+            /* Copy the result back */
+            memcpy(SC->request_buffer + sizeof(ips_passthru_t), &nvram, sizeof(IPS_NVRAM_P5));
+
+            SC->result = DID_OK << 16;
+            pt->BasicStatus = 0x00;
+            pt->ExtendedStatus = 0x00;
+
+            return (IPS_SUCCESS_IMM);
+         }
+
          if (ips_usrcmd(ha, pt, scb))
             return (IPS_SUCCESS);
          else
             return (IPS_FAILURE);
       } else if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
+         char           *user_area;
+         char           *kern_area;
+         u32             datasize;
+
          if (SC->request_bufflen < (sizeof(ips_passthru_t))) {
             /* wrong size */
             DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
                       ips_name, ha->host_num);
 
+            SC->result = DID_ERROR << 16;
+
             return (IPS_FAILURE);
          }
 
+
+         /* IF it's OK to Use the "CD BOOT" Flash Buffer, then you can     */
+         /* avoid allocating a huge buffer per adapter ( which can fail ). */
+         if ( (ips_FlashData) &&                                            
+              (pt->CmdBSize == IPS_IMAGE_SIZE) &&                                   
+              (ips_FlashDataInUse == 0) ) {                                 
+            ips_FlashDataInUse = 1;                                         
+            ha->save_ioctl_data  = ha->ioctl_data;                          
+            ha->save_ioctl_order = ha->ioctl_order;                         
+            ha->save_ioctl_datasize = ha->ioctl_datasize;                   
+            ha->ioctl_data  = ips_FlashData;                                
+            ha->ioctl_order = 7;                                            
+            ha->ioctl_datasize = IPS_IMAGE_SIZE;                                    
+         }                                                                  
+
+         if ((pt->CoppCP.cmd.nvram.op_code == IPS_CMD_RW_NVRAM_PAGE) &&
+             (pt->CoppCP.cmd.nvram.page == 5) &&
+             (pt->CoppCP.cmd.nvram.write == 0)) {
+
+            datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]);
+
+            if (datasize < sizeof(IPS_NVRAM_P5)) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            ips_get_bios_version(ha, IPS_INTR_IORL);
+            ips_create_nvrampage5(ha, &nvram);
+
+            user_area = *((char **) &scb->scsi_cmd->cmnd[4]);
+            kern_area = (char *) &nvram;
+            datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]);
+
+            if (datasize > sizeof(IPS_NVRAM_P5))
+               datasize = sizeof(IPS_NVRAM_P5);
+
+            /* Copy out the buffer */
+            if (copy_to_user((void *) user_area, (void *) kern_area, datasize) > 0) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            pt->BasicStatus = 0x00;
+            pt->ExtendedStatus = 0x00;
+            SC->result = DID_OK << 16;
+
+            return (IPS_SUCCESS_IMM);
+         }
+
+         /*
+          * IPSSEND flashing BIOS
+          */
+         if ((pt->CoppCP.cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW) &&
+             (pt->CoppCP.cmd.flashfw.type == 1) &&
+             (pt->CoppCP.cmd.flashfw.direction == 2) &&
+             (ha->device_id == IPS_DEVICEID_COPPERHEAD)) {
+            struct tq_struct  task;
+            IPS_FLASH_DATA    flash_data;
+            DECLARE_MUTEX_LOCKED(sem);
+
+            /* We only support one packet */
+            if (pt->CoppCP.cmd.flashfw.total_packets != 1) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            /* copy in the size/buffer ptr from the scsi command */
+            memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4);
+            memcpy(&pt->CmdBSize, &SC->cmnd[8], 4);
+
+            if (pt->CmdBSize > pt->CoppCP.cmd.flashfw.count) {
+               pt->CmdBSize = pt->CoppCP.cmd.flashfw.count;
+            } else {
+               /* ERROR: Command/Buffer mismatch */
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            if ((!ha->func.programbios) ||
+                (!ha->func.erasebios) ||
+                (!ha->func.verifybios)) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            /* must have a buffer */
+            if ((!pt->CmdBSize) || (!pt->CmdBuffer)) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            /* make sure buffer is big enough */
+            if (pt->CmdBSize > ha->ioctl_datasize) {
+               void *bigger_struct;
+               u32   count;
+               u32   order;
+
+               /* try to allocate a bigger struct */
+               for (count = PAGE_SIZE, order = 0;
+                    count < pt->CmdBSize;
+                    order++, count <<= 1);
+
+               bigger_struct = (void *) __get_free_pages(GFP_ATOMIC, order);
+               if (bigger_struct) {
+                  /* free the old memory */
+                  free_pages((unsigned long) ha->ioctl_data, ha->ioctl_order);
+
+                  /* use the new memory */
+                  ha->ioctl_data = (char *) bigger_struct;
+                  ha->ioctl_order = order;
+                  ha->ioctl_datasize = count;
+               } else {
+                  pt->BasicStatus = 0x0B;
+                  pt->ExtendedStatus = 0x00;
+                  SC->result = DID_ERROR << 16;
+
+                  spin_unlock(&ha->ips_lock);
+
+                  return (IPS_FAILURE);
+               }
+            }
+
+            /* copy in the buffer */
+            if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) {
+               DEBUG_VAR(1, "(%s%d) flash bios failed - unable to copy user buffer",
+                         ips_name, ha->host_num);
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            flash_data.userbuffer = pt->CmdBuffer;
+            flash_data.usersize = pt->CmdBSize;
+            flash_data.kernbuffer = ha->ioctl_data;
+            flash_data.kernsize = ha->ioctl_datasize;
+            flash_data.offset = 0;
+            flash_data.SC = (void *) SC;
+            flash_data.pt = (void *) pt;
+            flash_data.ha = (void *) ha;
+            flash_data.sem = &sem;
+
+            task.sync = 0;
+            task.routine = ips_scheduled_flash_bios;
+            task.data = (void *) &flash_data;
+
+            /* Unlock the master lock */
+            spin_unlock_irq(&io_request_lock);
+
+            queue_task(&task, &tq_immediate);
+            mark_bh(IMMEDIATE_BH);
+
+            /* Wait for the flash to complete */
+            down(&sem);
+
+            /* Obtain the master lock */
+            spin_lock_irq(&io_request_lock);
+
+            return (flash_data.retcode);
+         }
+
+         /*
+          * IPSSEND flashing BIOS in sectioned mode
+          */
+         if ((pt->CoppCP.cmd.flashbios.op_code == IPS_CMD_RW_BIOSFW) &&
+             (pt->CoppCP.cmd.flashbios.type == 1) &&
+             (pt->CoppCP.cmd.flashbios.direction == 4) &&
+             (ha->device_id == IPS_DEVICEID_COPPERHEAD)) {
+            struct tq_struct  task;
+            IPS_FLASH_DATA    flash_data;
+            DECLARE_MUTEX_LOCKED(sem);
+
+            /* copy in the size/buffer ptr from the scsi command */
+            memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4);
+            memcpy(&pt->CmdBSize, &SC->cmnd[8], 4);
+
+            if (pt->CmdBSize > pt->CoppCP.cmd.flashbios.count) {
+               pt->CmdBSize = pt->CoppCP.cmd.flashbios.count;
+            } else {
+               /* ERROR: Command/Buffer mismatch */
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            /* Update the Card BIOS */
+            if ((!ha->func.programbios) ||
+                (!ha->func.erasebios) ||
+                (!ha->func.verifybios)) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            /* must have a buffer */
+            if ((!pt->CmdBSize) || (!pt->CmdBuffer)) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            /* make sure buffer is big enough */
+            if (pt->CmdBSize > ha->ioctl_datasize) {
+               void *bigger_struct;
+               u32   count;
+               u32   order;
+
+               /* try to allocate a bigger struct */
+               for (count = PAGE_SIZE, order = 0;
+                    count < pt->CmdBSize;
+                    order++, count <<= 1);
+
+               bigger_struct = (void *) __get_free_pages(GFP_ATOMIC, order);
+               if (bigger_struct) {
+                  /* free the old memory */
+                  free_pages((unsigned long) ha->ioctl_data, ha->ioctl_order);
+
+                  /* use the new memory */
+                  ha->ioctl_data = (char *) bigger_struct;
+                  ha->ioctl_order = order;
+                  ha->ioctl_datasize = count;
+               } else {
+                  pt->BasicStatus = 0x0B;
+                  pt->ExtendedStatus = 0x00;
+                  SC->result = DID_ERROR << 16;
+
+                  spin_unlock(&ha->ips_lock);
+
+                  return (IPS_FAILURE);
+               }
+            }
+
+            /* copy in the buffer */
+            if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) {
+               DEBUG_VAR(1, "(%s%d) flash bios failed - unable to copy user buffer",
+                         ips_name, ha->host_num);
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            flash_data.userbuffer = pt->CmdBuffer;
+            flash_data.usersize = pt->CmdBSize;
+            flash_data.kernbuffer = ha->ioctl_data;
+            flash_data.kernsize = ha->ioctl_datasize;
+            flash_data.offset = pt->CoppCP.cmd.flashbios.offset;
+            flash_data.SC = (void *) SC;
+            flash_data.pt = (void *) pt;
+            flash_data.ha = (void *) ha;
+            flash_data.sem = &sem;
+
+            task.sync = 0;
+            task.routine = ips_flash_bios_section;
+            task.data = (void *) &flash_data;
+
+            /* Unlock the master lock */
+            spin_unlock_irq(&io_request_lock);
+
+            queue_task(&task, &tq_immediate);
+            mark_bh(IMMEDIATE_BH);
+           
+            /* Wait for the flash to complete */
+            down(&sem);
+
+            /* Obtain the master lock */
+            spin_lock_irq(&io_request_lock);
+
+            return (flash_data.retcode);
+         }
+
+         if ((pt->CoppCP.cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW) &&
+             (pt->CoppCP.cmd.flashfw.type == 1) &&
+             (pt->CoppCP.cmd.flashfw.direction == 3) &&
+             (ha->device_id == IPS_DEVICEID_COPPERHEAD)) {
+            /* Erase the Card BIOS */
+            if (!ha->func.erasebios) {
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            if ((*ha->func.erasebios)(ha)) {
+               DEBUG_VAR(1, "(%s%d) flash bios failed - unable to erase flash",
+                         ips_name, ha->host_num);
+               pt->BasicStatus = 0x0B;
+               pt->ExtendedStatus = 0x00;
+               SC->result = DID_ERROR << 16;
+
+               return (IPS_FAILURE);
+            }
+
+            SC->result = DID_OK << 16;
+            pt->BasicStatus = 0x00;
+            pt->ExtendedStatus = 0x00;
+
+            return (IPS_SUCCESS_IMM);
+         }
+
          if (ips_newusrcmd(ha, pt, scb))
             return (IPS_SUCCESS);
          else
@@ -2149,87 +2627,152 @@
 
       break;
 
-   case IPS_FLASHBIOS:
-      /* we must use the new interface */
-      if (SC->cmnd[0] != IPS_IOCTL_NEW_COMMAND)
-         return (IPS_FAILURE);
+   } /* end switch */
 
-      /* don't flash the BIOS on future cards */
-      if ((ha->device_id != IPS_COPPERHEAD_DEVICEID) ||
-          (ha->revision_id > IPS_REVID_TROMBONE64)) {
-         DEBUG_VAR(1, "(%s%d) flash bios failed - unsupported controller",
-                   ips_name, ha->host_num);
+   return (IPS_FAILURE);
+}
 
-         return (IPS_FAILURE);
-      }
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_scheduled_flash_bios                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Flash the BIOS on a Copperhead style controller                        */
+/*   To be called from a task queue                                         */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_scheduled_flash_bios(void *data) {
+   ips_ha_t       *ha;
+   Scsi_Cmnd      *SC;
+   ips_passthru_t *pt;
+   IPS_FLASH_DATA *fd;
 
-      /*
-       * Check to make sure we have functions
-       * to handle the request
-       */
-      if ((!ha->func.programbios) ||
-          (!ha->func.erasebios) ||
-          (!ha->func.verifybios))
-         return (IPS_FAILURE);
+   fd = (IPS_FLASH_DATA *) data;
+   ha = (ips_ha_t *) fd->ha;
+   pt = (ips_passthru_t *) fd->pt;
+   SC = (Scsi_Cmnd *) fd->SC;
 
-      /* copy in the size/buffer ptr from the scsi command */
-      memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4);
-      memcpy(&pt->CmdBSize, &SC->cmnd[8], 4);
+   /*
+    * Set initial return codes
+    */
+   SC->result = DID_OK << 16;
+   pt->BasicStatus = 0x00;
+   pt->ExtendedStatus = 0x00;
+   fd->retcode = IPS_SUCCESS_IMM;
 
-      /* must have a buffer */
-      if ((!pt->CmdBSize) || (!pt->CmdBuffer))
-         return (IPS_FAILURE);
+   /*
+    * Fix the size/ptr to account for the
+    * flash header
+    */
+   fd->kernbuffer += 0xC0;
+   fd->kernsize -= 0xC0;
+   fd->userbuffer += 0xC0;
+   fd->usersize -= 0xC0;
 
-      /* make sure buffer is big enough */
-      if (pt->CmdBSize > ha->ioctl_datasize) {
-         void *bigger_struct;
+   if ((*ha->func.erasebios)(ha)) {
+      DEBUG_VAR(1, "(%s%d) flash bios failed - unable to erase flash",
+                ips_name, ha->host_num);
+      pt->BasicStatus = 0x0B;
+      pt->ExtendedStatus = 0x00;
+      SC->result = DID_ERROR << 16;
+      fd->retcode = IPS_FAILURE;
+      up(fd->sem);
 
-         /* try to allocate a bigger struct */
-         bigger_struct = kmalloc(pt->CmdBSize, GFP_ATOMIC|GFP_DMA);
-         if (bigger_struct) {
-            /* free the old memory */
-            kfree(ha->ioctl_data);
+      return ;
+   }
 
-            /* use the new memory */
-            ha->ioctl_data = bigger_struct;
-            ha->ioctl_datasize = pt->CmdBSize;
-         } else
-            return (IPS_FAILURE);
-      }
+   ips_flash_bios_segment(data);
 
-      /* copy in the buffer */
-      if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) {
-         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to copy user buffer",
-                   ips_name, ha->host_num);
+   if (fd->retcode == IPS_FAILURE)
+      return ;
 
-         return (IPS_FAILURE);
-      }
+   if ((*ha->func.verifybios)(ha, fd->kernbuffer, fd->usersize, fd->offset)) {
+      DEBUG_VAR(1, "(%s%d) flash bios failed - unable to verify flash",
+                ips_name, ha->host_num);
+      pt->BasicStatus = 0x0B;
+      pt->ExtendedStatus = 0x00;
+      SC->result = DID_ERROR << 16;
+      fd->retcode = IPS_FAILURE;
+      up(fd->sem);
 
-      if ((*ha->func.erasebios)(ha)) {
-         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to erase flash",
-                   ips_name, ha->host_num);
+      return ;
+   }
 
-         return (IPS_FAILURE);
-      }
+   /* Tell them we are done */
+   if (fd->retcode != IPS_FAILURE)
+      up(fd->sem);
+}
 
-      if ((*ha->func.programbios)(ha, ha->ioctl_data, pt->CmdBSize)) {
-         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to program flash",
-                   ips_name, ha->host_num);
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_flash_bios_section                                     */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   wrapper for ips_flash_bios_segment that raises the semaphore           */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_flash_bios_section(void *data) {
+   ips_ha_t       *ha;
+   Scsi_Cmnd      *SC;
+   ips_passthru_t *pt;
+   IPS_FLASH_DATA *fd;
 
-         return (IPS_FAILURE);
-      }
+   fd = (IPS_FLASH_DATA *) data;
+   ha = (ips_ha_t *) fd->ha;
+   pt = (ips_passthru_t *) fd->pt;
+   SC = (Scsi_Cmnd *) fd->SC;
 
-      if ((*ha->func.verifybios)(ha, ha->ioctl_data, pt->CmdBSize)) {
-         DEBUG_VAR(1, "(%s%d) flash bios failed - unable to verify flash",
-                   ips_name, ha->host_num);
+   /*
+    * Set initial return codes
+    */
+   SC->result = DID_OK << 16;
+   pt->BasicStatus = 0x00;
+   pt->ExtendedStatus = 0x00;
+   fd->retcode = IPS_SUCCESS_IMM;
 
-         return (IPS_FAILURE);
-      }
+   ips_flash_bios_segment(data);
 
-      return (IPS_SUCCESS_IMM);
-   } /* end switch */
+   if (fd->retcode != IPS_FAILURE)
+      up(fd->sem);
+}
 
-   return (IPS_FAILURE);
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_flash_bios_segment                                     */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Flash a portion of the BIOS on a Copperhead style controller           */
+/*   To be called from a task queue                                         */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_flash_bios_segment(void *data) {
+   ips_ha_t       *ha;
+   Scsi_Cmnd      *SC;
+   ips_passthru_t *pt;
+   IPS_FLASH_DATA *fd;
+
+   fd = (IPS_FLASH_DATA *) data;
+   ha = (ips_ha_t *) fd->ha;
+   pt = (ips_passthru_t *) fd->pt;
+   SC = (Scsi_Cmnd *) fd->SC;
+
+   if ((*ha->func.programbios)(ha, fd->kernbuffer, fd->usersize, fd->offset)) {
+      DEBUG_VAR(1, "(%s%d) flash bios failed - unable to program flash",
+                ips_name, ha->host_num);
+      pt->BasicStatus = 0x0B;
+      pt->ExtendedStatus = 0x00;
+      SC->result = DID_ERROR << 16;
+      fd->retcode = IPS_FAILURE;
+      up(fd->sem);
+
+      return ;
+   }
 }
 
 /****************************************************************************/
@@ -2363,16 +2906,23 @@
    if (pt->CmdBSize) {
       if (pt->CmdBSize > ha->ioctl_datasize) {
          void *bigger_struct;
+         u32   count;
+         u32   order;
 
          /* try to allocate a bigger struct */
-         bigger_struct = kmalloc(pt->CmdBSize, GFP_ATOMIC|GFP_DMA);
+         for (count = PAGE_SIZE, order = 0;
+              count < pt->CmdBSize;
+              order++, count <<= 1);
+
+         bigger_struct = (void *) __get_free_pages(GFP_ATOMIC, order);
          if (bigger_struct) {
             /* free the old memory */
-            kfree(ha->ioctl_data);
+            free_pages((unsigned long) ha->ioctl_data, ha->ioctl_order);
 
             /* use the new memory */
-            ha->ioctl_data = bigger_struct;
-            ha->ioctl_datasize = pt->CmdBSize;
+            ha->ioctl_data = (char *) bigger_struct;
+            ha->ioctl_order = order;
+            ha->ioctl_datasize = count;
          } else
             return (0);
 
@@ -2450,6 +3000,10 @@
    pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer;
 
    /* Copy data back to the user */
+   if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) {       /* Copy DCDB Back to Caller's Area */
+      memcpy(&pt->CoppCP.dcdb, &scb->dcdb, sizeof(IPS_DCDB_TABLE));
+   }
+
    if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_COMMAND) {
       /* Copy data back to the user */
       pt->BasicStatus = scb->basic_status;
@@ -2606,6 +3160,253 @@
 
 /****************************************************************************/
 /*                                                                          */
+/* Routine Name: ips_identify_controller                                    */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Identify this controller                                               */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_identify_controller(ips_ha_t *ha) {
+   METHOD_TRACE("ips_identify_controller", 1);
+
+   switch (ha->device_id) {
+   case IPS_DEVICEID_COPPERHEAD:
+      if (ha->revision_id <= IPS_REVID_SERVERAID) {
+         ha->ad_type = IPS_ADTYPE_SERVERAID;
+      } else if (ha->revision_id == IPS_REVID_SERVERAID2) {
+         ha->ad_type = IPS_ADTYPE_SERVERAID2;
+      } else if (ha->revision_id == IPS_REVID_NAVAJO) {
+         ha->ad_type = IPS_ADTYPE_NAVAJO;
+      } else if ((ha->revision_id == IPS_REVID_SERVERAID2) && (ha->slot_num == 0)) {
+         ha->ad_type = IPS_ADTYPE_KIOWA;
+      } else if ((ha->revision_id >= IPS_REVID_CLARINETP1) &&
+                 (ha->revision_id <= IPS_REVID_CLARINETP3)) {
+         if (ha->enq->ucMaxPhysicalDevices == 15)
+            ha->ad_type = IPS_ADTYPE_SERVERAID3L;
+         else
+            ha->ad_type = IPS_ADTYPE_SERVERAID3;
+      } else if ((ha->revision_id >= IPS_REVID_TROMBONE32) &&
+                 (ha->revision_id <= IPS_REVID_TROMBONE64)) {
+         ha->ad_type = IPS_ADTYPE_SERVERAID4H;
+      }
+      break;
+
+   case IPS_DEVICEID_MORPHEUS:
+      switch (ha->subdevice_id) {
+      case IPS_SUBDEVICEID_4L:
+         ha->ad_type = IPS_ADTYPE_SERVERAID4L;
+         break;
+
+      case IPS_SUBDEVICEID_4M:
+         ha->ad_type = IPS_ADTYPE_SERVERAID4M;
+         break;
+
+      case IPS_SUBDEVICEID_4MX:
+         ha->ad_type = IPS_ADTYPE_SERVERAID4MX;
+         break;
+
+      case IPS_SUBDEVICEID_4LX:
+         ha->ad_type = IPS_ADTYPE_SERVERAID4LX;
+         break;
+      }
+
+      break;
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_create_nvrampage5                                      */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Create a pseudo nvram page 5                                           */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_create_nvrampage5(ips_ha_t *ha, IPS_NVRAM_P5 *nvram) {
+   METHOD_TRACE("ips_create_nvrampage5", 1);
+
+   memset(nvram, 0, sizeof(IPS_NVRAM_P5));
+
+   nvram->signature = IPS_NVRAM_P5_SIG;
+   nvram->adapter_slot = ha->slot_num;
+   nvram->adapter_type = ha->ad_type;
+   nvram->operating_system = IPS_OS_LINUX;
+   strncpy((char *) nvram->driver_high, IPS_VERSION_HIGH, 4);
+   strncpy((char *) nvram->driver_low, IPS_VERSION_LOW, 4);
+   strncpy((char *) nvram->bios_high, ha->bios_version, 4);
+   strncpy((char *) nvram->bios_low, ha->bios_version + 4, 4);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_get_bios_version                                       */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Get the BIOS revision number                                           */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_get_bios_version(ips_ha_t *ha, int intr) {
+   ips_scb_t *scb;
+   int        ret;
+   u8         major;
+   u8         minor;
+   u8         subminor; 
+   u8        *buffer;
+   char       hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+   METHOD_TRACE("ips_get_bios_version", 1);
+
+   major = 0;
+   minor = 0;
+
+   strncpy(ha->bios_version, "       ?", 8);
+
+   if (ha->device_id == IPS_DEVICEID_COPPERHEAD) {
+      if (IPS_USE_MEMIO(ha)) {
+         /* Memory Mapped I/O */
+
+         /* test 1st byte */
+         writel(0, ha->mem_ptr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
+            return;
+
+         writel(1, ha->mem_ptr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
+            return;
+
+         /* Get Major version */
+         writel(0x1FF, ha->mem_ptr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         major = readb(ha->mem_ptr + IPS_REG_FLDP);
+
+         /* Get Minor version */
+         writel(0x1FE, ha->mem_ptr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         minor = readb(ha->mem_ptr + IPS_REG_FLDP);
+
+         /* Get Sub Minor version */
+         writel(0x1FD, ha->mem_ptr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5);/* 5 us */
+
+         subminor = readb(ha->mem_ptr + IPS_REG_FLDP);
+
+
+      } else {
+         /* Programmed I/O */
+
+         /* test 1st byte */
+         outl(0, ha->io_addr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
+            return ;
+
+         outl(1, ha->io_addr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
+            return ;
+
+         /* Get Major version */
+         outl(0x1FF, ha->io_addr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         major = inb(ha->io_addr + IPS_REG_FLDP);
+
+         /* Get Minor version */
+         outl(0x1FE, ha->io_addr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         minor = inb(ha->io_addr + IPS_REG_FLDP);
+         
+         /* Get SubMinor version */
+         outl(0x1FD, ha->io_addr + IPS_REG_FLAP);
+         if (ha->revision_id == IPS_REVID_TROMBONE64)
+            udelay(5); /* 5 us */
+
+         subminor = inb(ha->io_addr + IPS_REG_FLDP);
+
+      }
+   } else {
+      /* Morpheus Family - Send Command to the card */
+
+      buffer = kmalloc(0x1000, GFP_ATOMIC);
+      if (!buffer)
+         return;
+
+      memset(buffer, 0, 0x1000);
+
+      scb = &ha->scbs[ha->max_cmds-1];
+
+      ips_init_scb(ha, scb);
+
+      scb->timeout = ips_cmd_timeout;
+      scb->cdb[0] = IPS_CMD_RW_BIOSFW;
+
+      scb->cmd.flashfw.op_code = IPS_CMD_RW_BIOSFW;
+      scb->cmd.flashfw.command_id = IPS_COMMAND_ID(ha, scb);
+      scb->cmd.flashfw.type = 1;
+      scb->cmd.flashfw.direction = 0;
+      scb->cmd.flashfw.count = 0x800;
+      scb->cmd.flashfw.buffer_addr = VIRT_TO_BUS(buffer);
+      scb->cmd.flashfw.total_packets = 1;
+      scb->cmd.flashfw.packet_num = 0;
+
+      /* issue the command */
+      if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) ||
+          (ret == IPS_SUCCESS_IMM) ||
+          ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
+         /* Error occurred */
+         kfree(buffer);
+
+         return;
+      }
+
+      if ((buffer[0xC0] == 0x55) && (buffer[0xC1] == 0xAA)) {
+         major = buffer[0x1ff + 0xC0]; /* Offset 0x1ff after the header (0xc0) */
+         minor = buffer[0x1fe + 0xC0]; /* Offset 0x1fe after the header (0xc0) */
+         subminor = buffer[0x1fd + 0xC0]; /* Offset 0x1fe after the header (0xc0) */
+
+      } else {
+         return;
+      }
+
+      kfree(buffer);
+   }
+
+   ha->bios_version[0] = hexDigits[(major & 0xF0) >> 4];
+   ha->bios_version[1] = '.';
+   ha->bios_version[2] = hexDigits[major & 0x0F];
+   ha->bios_version[3] = hexDigits[subminor];
+   ha->bios_version[4] = '.';
+   ha->bios_version[5] = hexDigits[(minor & 0xF0) >> 4];
+   ha->bios_version[6] = hexDigits[minor & 0x0F];
+   ha->bios_version[7] = 0;
+}
+
+/****************************************************************************/
+/*                                                                          */
 /* Routine Name: ips_hainit                                                 */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -2651,6 +3452,9 @@
       return (0);
    }
 
+   /* Identify this controller */
+   ips_identify_controller(ha);
+
    if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) {
       printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n",
              ips_name, ha->host_num);
@@ -2799,30 +3603,47 @@
           (scb = ips_getscb(ha))) {
 
       IPS_QUEUE_UNLOCK(&ha->copp_waitlist);
-      IPS_HA_UNLOCK(cpu_flags);
       item = ips_removeq_copp_head(&ha->copp_waitlist);
+      IPS_HA_UNLOCK(cpu_flags);
       scb->scsi_cmd = item->scsi_cmd;
       scb->sem = item->sem;
       kfree(item);
 
-      ret = ips_make_passthru(ha, scb->scsi_cmd, scb);
+      ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
 
       switch (ret) {
       case IPS_FAILURE:
          if (scb->scsi_cmd) {
+            scb->scsi_cmd->result = DID_ERROR << 16;
+
             /* raise the semaphore */
-            if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
-               up(scb->sem);
+            if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
+               u32 datasize;
 
-            scb->scsi_cmd->result = DID_ERROR << 16;
+               datasize = 0;
+               memcpy(&scb->scsi_cmd->cmnd[8], &datasize, 4);
+               up(scb->sem);
+            } else {
+               scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+            }
          }
+
          ips_freescb(ha, scb);
          break;
       case IPS_SUCCESS_IMM:
          if (scb->scsi_cmd) {
+            scb->scsi_cmd->result = DID_OK << 16;
+
             /* raise the semaphore */
-            if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND)
+            if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) {
+               u32 datasize;
+
+               datasize = 0;
+               memcpy(&scb->scsi_cmd->cmnd[8], &datasize, 4);
                up(scb->sem);
+            } else {
+               scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+            }
          }
 
          ips_freescb(ha, scb);
@@ -2891,10 +3712,12 @@
          continue;
       }
 
-      IPS_HA_UNLOCK(cpu_flags);
-
       q = p;
       SC = ips_removeq_wait(&ha->scb_waitlist, q);
+      if (SC == NULL)                    /* Should never happen, but good to check anyway */
+         continue;
+      
+      IPS_HA_UNLOCK(cpu_flags);          /* Unlock HA after command is taken off queue */
 
       SC->result = DID_OK;
       SC->host_scribble = NULL;
@@ -2932,27 +3755,37 @@
             scb->data_busaddr = VIRT_TO_BUS(sg[0].address);
             scb->sg_len = 0;
          } else {
+            /* Check for the first Element being bigger than MAX_XFER */
+            if (sg[0].length > ha->max_xfer) {
+               scb->sg_list[0].address = VIRT_TO_BUS(sg[0].address);
+               scb->sg_list[0].length = ha->max_xfer;
+               scb->data_len = ha->max_xfer;
+               scb->breakup = 0; 
+	            scb->sg_break=1;  
+               scb->sg_len = 1;
+	         }
+            else {
+               for (i = 0; i < SC->use_sg; i++) {
+                  scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
+                  scb->sg_list[i].length = sg[i].length;
+            
+                  if (scb->data_len + sg[i].length > ha->max_xfer) {
+                     /*
+                      * Data Breakup required
+                      */
+                     scb->breakup = i;
+                     break;
+                  }
 
-            for (i = 0; i < SC->use_sg; i++) {
-               scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
-               scb->sg_list[i].length = sg[i].length;
-
-               if (scb->data_len + sg[i].length > ha->max_xfer) {
-                  /*
-                   * Data Breakup required
-                   */
-                  scb->breakup = i;
-                  break;
+                  scb->data_len += sg[i].length;
                }
 
-               scb->data_len += sg[i].length;
+               if (!scb->breakup)
+                  scb->sg_len = SC->use_sg;
+               else
+                  scb->sg_len = scb->breakup;
             }
 
-            if (!scb->breakup)
-               scb->sg_len = SC->use_sg;
-            else
-               scb->sg_len = scb->breakup;
-
             scb->dcdb.transfer_length = scb->data_len;
             scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
          }
@@ -3590,9 +4423,9 @@
        * data and had to be broke up.  If so, queue
        * the rest of the data and continue.
        */
-      if (scb->breakup) {
-         /* we had a data breakup */
-         u16 bk_save;
+      if (scb->breakup || scb->sg_break) { 
+         /* We had a data breakup */
+         u8 bk_save;
 
          bk_save = scb->breakup;
          scb->breakup = 0;
@@ -3618,34 +4451,68 @@
                scb->dcdb.transfer_length = scb->data_len;
                scb->sg_len = 0;
             } else {
-               scb->data_len = 0;
-
-               for (i = bk_save; i < scb->scsi_cmd->use_sg; i++) {
-                  scb->sg_list[i - bk_save].address = VIRT_TO_BUS(sg[i].address);
-                  scb->sg_list[i - bk_save].length = sg[i].length;
-
-                  if (scb->data_len + sg[i].length > ha->max_xfer) {
-                     /*
-                      * Data Breakup required
-                      */
-                     scb->breakup = i;
-                     break;
+               /* We're here because there was MORE than one s/g unit. */
+	            /* bk_save points to which sg unit to look at           */
+	            /* sg_break points to how far through this unit we are  */
+	            /* NOTE: We will not move from one sg to another here,  */
+               /*    just finish the one we are in.  Not the most      */
+               /*    efficient, but it keeps it from getting too hacky */
+
+		         /* IF sg_break is non-zero, then just work on this current sg piece, */
+               /* pointed to by bk_save                                             */
+               if (scb->sg_break) {
+                  scb->sg_len = 1;
+        			   scb->sg_list[0].address = VIRT_TO_BUS(sg[bk_save].address+ha->max_xfer*scb->sg_break);
+                  if (ha->max_xfer > sg[bk_save].length-ha->max_xfer * scb->sg_break) 
+                     scb->sg_list[0].length = sg[bk_save].length-ha->max_xfer * scb->sg_break;
+                  else 
+                     scb->sg_list[0].length = ha->max_xfer;
+                  scb->sg_break++;              /* MUST GO HERE for math below to work */
+			         scb->data_len = scb->sg_list[0].length;;
+
+		            if (sg[bk_save].length <= ha->max_xfer * scb->sg_break ) {
+                     scb->sg_break = 0;         /* No more work in this unit */
+                     if (( bk_save + 1 ) >= scb->scsi_cmd->use_sg) 
+                        scb->breakup = 0;
+                     else 
+                        scb->breakup = bk_save + 1;
                   }
+               } else {
+			         /* ( sg_break == 0 ), so this is our first look at a new sg piece */
+                  if (sg[bk_save].length > ha->max_xfer) {
+			            scb->sg_list[0].address = VIRT_TO_BUS(sg[bk_save].address);
+				         scb->sg_list[0].length = ha->max_xfer;
+				         scb->breakup = bk_save;
+				         scb->sg_break = 1;
+				         scb->data_len = ha->max_xfer;
+				         scb->sg_len = 1;
+ 	        		   } else {
+				         /* OK, the next sg is a short one, so loop until full */
+			            scb->data_len = 0;
+		     	         scb->sg_len = 0;
+      			      scb->sg_break = 0;
+                     /*   We're only doing full units here */
+				         for (i = bk_save; i < scb->scsi_cmd->use_sg; i++) {
+					         scb->sg_list[i - bk_save].address = VIRT_TO_BUS(sg[i].address);
+				            scb->sg_list[i - bk_save].length = sg[i].length;
+                        if (scb->data_len + sg[i].length > ha->max_xfer) {
+					            scb->breakup = i;  /* sneaky, if not more work, than breakup is 0 */
+					            break;
+					         }
+					         scb->data_len += sg[i].length;
+					         scb->sg_len++;           /* only if we didn't get too big */
+		  		         }
+			         }
+		         }
 
-                  scb->data_len += sg[i].length;
-               }
-
-               if (!scb->breakup)
-                  scb->sg_len = scb->scsi_cmd->use_sg - bk_save;
-               else
-                  scb->sg_len = scb->breakup - bk_save;
-
+               /* Also, we need to be sure we don't queue work ( breakup != 0 )
+                  if no more sg units for next time */
                scb->dcdb.transfer_length = scb->data_len;
                scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
-           }
-        } else {
+            }
+         } else {
             /* Non S/G Request */
-            if (scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer)) {
+            if ((scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer)) > ha->max_xfer) {
                /* Further breakup required */
                scb->data_len = ha->max_xfer;
                scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
@@ -3882,7 +4749,9 @@
 static int
 ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
    int       ret;
-
+   char     *sp;
+   int       device_error;
+  
    METHOD_TRACE("ips_send_cmd", 1);
 
    ret = IPS_SUCCESS;
@@ -4068,7 +4937,20 @@
          break;
 
       default:
-         scb->scsi_cmd->result = DID_ERROR << 16;
+         /* Set the Return Info to appear like the Command was */
+         /* attempted, a Check Condition occurred, and Sense   */
+         /* Data indicating an Invalid CDB OpCode is returned. */
+         sp = (char *) scb->scsi_cmd->sense_buffer;
+         memset(sp, 0, sizeof(scb->scsi_cmd->sense_buffer));
+  
+         sp[0] = 0x70;             /* Error Code               */ 
+         sp[2] = ILLEGAL_REQUEST;  /* Sense Key 5 Illegal Req. */
+         sp[7] = 0x0A;             /* Additional Sense Length  */
+         sp[12] = 0x20;            /* ASC = Invalid OpCode     */
+         sp[13] = 0x00;            /* ASCQ                     */
+   
+         device_error = 2;         /* Indicate Check Condition */
+         scb->scsi_cmd->result = device_error | (DID_OK << 16);
          break;
       } /* end switch */
    } /* end if */
@@ -4083,6 +4965,13 @@
       else
          scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG;
 
+      /* If we already know the Device is Not there, no need to attempt a Command   */
+      /* This also protects an NT FailOver Controller from getting CDB's sent to it */
+      if ( ha->conf->dev[scb->bus-1][scb->target_id].ucState == 0 ) {
+         scb->scsi_cmd->result = DID_NO_CONNECT << 16;
+         return (IPS_SUCCESS_IMM); 
+      }
+
       ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id);
       scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
       scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
@@ -4289,8 +5178,7 @@
       return (0);
    }
 
-   if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive &&
-       ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE &&
+   if (ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE &&
        ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_FREE &&
        ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_CRS &&
        ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_SYS)
@@ -4510,9 +5398,10 @@
       }
 
       if (ha->ioctl_data) {
-         kfree(ha->ioctl_data);
+         free_pages((unsigned long) ha->ioctl_data, ha->ioctl_order);
          ha->ioctl_data = NULL;
          ha->ioctl_datasize = 0;
+         ha->ioctl_order = 0;
       }
 
       if (ha->scbs) {
@@ -4552,9 +5441,10 @@
    METHOD_TRACE("ips_allocatescbs", 1);
 
    /* Allocate memory for the CCBs */
-   ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_ATOMIC|GFP_DMA);
-   if(ha->scbs == NULL)
-   	return 0;
+   ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_ATOMIC);
+   if (ha->scbs == NULL)
+    	return 0;
+
 
    memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t));
 
@@ -4562,7 +5452,7 @@
       scb_p = &ha->scbs[i];
 
       /* allocate S/G list */
-      scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC|GFP_DMA);
+      scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_ATOMIC);
 
       if (! scb_p->sg_list)
          return (0);
@@ -4713,7 +5603,7 @@
 /****************************************************************************/
 static int
 ips_isinit_copperhead_memio(ips_ha_t *ha) {
-   u8 isr;
+   u8 isr=0;
    u8 scpr;
 
    METHOD_TRACE("ips_is_init_copperhead_memio", 1);
@@ -4903,7 +5793,7 @@
 /****************************************************************************/
 static int
 ips_init_copperhead_memio(ips_ha_t *ha) {
-   u8  Isr;
+   u8  Isr=0;
    u8  Cbsp;
    u8  PostByte[IPS_MAX_POST_BYTES];
    u8  ConfigByte[IPS_MAX_CONFIG_BYTES];
@@ -5372,7 +6262,7 @@
    TimeOut = 0;
 
    while ((val = inw(ha->io_addr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
-      UDELAY(1000);
+      udelay(1000);
 
       if (++TimeOut >= IPS_SEM_TIMEOUT) {
          if (!(val & IPS_BIT_START_STOP))
@@ -5435,7 +6325,7 @@
    TimeOut = 0;
 
    while ((val = readl(ha->mem_ptr + IPS_REG_CCCR)) & IPS_BIT_SEM) {
-      UDELAY(1000);
+      udelay(1000);
 
       if (++TimeOut >= IPS_SEM_TIMEOUT) {
          if (!(val & IPS_BIT_START_STOP))
@@ -5674,7 +6564,7 @@
           */
 
          while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
-            UDELAY(1000);
+            udelay(1000);
 
          (*ha->func.intr)(ha);
 
@@ -5700,7 +6590,7 @@
          spin_lock(&io_request_lock);
 
          while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
-            UDELAY(1000);
+            udelay(1000);
 
          (*ha->func.intr)(ha);
 
@@ -5709,7 +6599,7 @@
          spin_unlock(&io_request_lock);
       }
 
-      UDELAY(1000); /* 1 milisecond */
+      udelay(1000); /* 1 milisecond */
       time--;
    }
 
@@ -5752,9 +6642,6 @@
              ha->nvram->bios_low[0], ha->nvram->bios_low[1],
              ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
 
-   /* save controller type */
-   ha->ad_type = ha->nvram->adapter_type;
-
    /* change values (as needed) */
    ha->nvram->operating_system = IPS_OS_LINUX;
    strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
@@ -5768,6 +6655,9 @@
       return (0);
    }
 
+   /* IF NVRAM Page 5 is OK, Use it for Slot Number Info Because Linux Doesn't Do Slots */
+   ha->slot_num = ha->nvram->adapter_slot;
+
    return (1);
 }
 
@@ -6154,40 +7044,40 @@
 static int
 ips_erase_bios(ips_ha_t *ha) {
    int   timeout;
-   u8    status;
+   u8    status=0;
 
    METHOD_TRACE("ips_erase_bios", 1);
 
    /* Clear the status register */
    outl(0, ha->io_addr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    outb(0x50, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* Erase Setup */
    outb(0x20, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* Erase Confirm */
    outb(0xD0, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* Erase Status */
    outb(0x70, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    timeout = 80000; /* 80 seconds */
 
    while (timeout > 0) {
       if (ha->revision_id == IPS_REVID_TROMBONE64) {
          outl(0, ha->io_addr + IPS_REG_FLAP);
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
       }
 
       status = inb(ha->io_addr + IPS_REG_FLDP);
@@ -6206,14 +7096,14 @@
       /* try to suspend the erase */
       outb(0xB0, ha->io_addr + IPS_REG_FLDP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       /* wait for 10 seconds */
       timeout = 10000;
       while (timeout > 0) {
          if (ha->revision_id == IPS_REVID_TROMBONE64) {
             outl(0, ha->io_addr + IPS_REG_FLAP);
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
          }
 
          status = inb(ha->io_addr + IPS_REG_FLDP);
@@ -6242,12 +7132,12 @@
    /* clear status */
    outb(0x50, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* enable reads */
    outb(0xFF, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    return (0);
 }
@@ -6270,33 +7160,33 @@
    /* Clear the status register */
    writel(0, ha->mem_ptr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* Erase Setup */
    writeb(0x20, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* Erase Confirm */
    writeb(0xD0, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* Erase Status */
    writeb(0x70, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    timeout = 80000; /* 80 seconds */
 
    while (timeout > 0) {
       if (ha->revision_id == IPS_REVID_TROMBONE64) {
          writel(0, ha->mem_ptr + IPS_REG_FLAP);
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
       }
 
       status = readb(ha->mem_ptr + IPS_REG_FLDP);
@@ -6315,14 +7205,14 @@
       /* try to suspend the erase */
       writeb(0xB0, ha->mem_ptr + IPS_REG_FLDP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       /* wait for 10 seconds */
       timeout = 10000;
       while (timeout > 0) {
          if (ha->revision_id == IPS_REVID_TROMBONE64) {
             writel(0, ha->mem_ptr + IPS_REG_FLAP);
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
          }
 
          status = readb(ha->mem_ptr + IPS_REG_FLDP);
@@ -6351,12 +7241,12 @@
    /* clear status */
    writeb(0x50, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    /* enable reads */
    writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    return (0);
 }
@@ -6370,33 +7260,33 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_program_bios(ips_ha_t *ha, char *buffer, int buffersize) {
+ips_program_bios(ips_ha_t *ha, char *buffer, u32 buffersize, u32 offset) {
    int   i;
    int   timeout;
-   u8    status;
+   u8    status=0;
 
    METHOD_TRACE("ips_program_bios", 1);
 
    for (i = 0; i < buffersize; i++) {
       /* write a byte */
-      outl(i, ha->io_addr + IPS_REG_FLAP);
+      outl(i + offset, ha->io_addr + IPS_REG_FLAP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       outb(0x40, ha->io_addr + IPS_REG_FLDP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       outb(buffer[i], ha->io_addr + IPS_REG_FLDP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       /* wait up to one second */
       timeout = 1000;
       while (timeout > 0) {
          if (ha->revision_id == IPS_REVID_TROMBONE64) {
             outl(0, ha->io_addr + IPS_REG_FLAP);
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
          }
 
          status = inb(ha->io_addr + IPS_REG_FLDP);
@@ -6412,11 +7302,11 @@
          /* timeout error */
          outl(0, ha->io_addr + IPS_REG_FLAP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          outb(0xFF, ha->io_addr + IPS_REG_FLDP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          return (1);
       }
@@ -6426,11 +7316,11 @@
          /* programming error */
          outl(0, ha->io_addr + IPS_REG_FLAP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          outb(0xFF, ha->io_addr + IPS_REG_FLDP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          return (1);
       }
@@ -6439,11 +7329,11 @@
    /* Enable reading */
    outl(0, ha->io_addr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    outb(0xFF, ha->io_addr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    return (0);
 }
@@ -6457,33 +7347,33 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_program_bios_memio(ips_ha_t *ha, char *buffer, int buffersize) {
+ips_program_bios_memio(ips_ha_t *ha, char *buffer, u32 buffersize, u32 offset) {
    int   i;
    int   timeout;
-   u8    status;
+   u8    status=0;
 
    METHOD_TRACE("ips_program_bios_memio", 1);
 
    for (i = 0; i < buffersize; i++) {
       /* write a byte */
-      writel(i, ha->mem_ptr + IPS_REG_FLAP);
+      writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       writeb(0x40, ha->mem_ptr + IPS_REG_FLDP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       writeb(buffer[i], ha->mem_ptr + IPS_REG_FLDP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       /* wait up to one second */
       timeout = 1000;
       while (timeout > 0) {
          if (ha->revision_id == IPS_REVID_TROMBONE64) {
             writel(0, ha->mem_ptr + IPS_REG_FLAP);
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
          }
 
          status = readb(ha->mem_ptr + IPS_REG_FLDP);
@@ -6499,11 +7389,11 @@
          /* timeout error */
          writel(0, ha->mem_ptr + IPS_REG_FLAP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          return (1);
       }
@@ -6513,11 +7403,11 @@
          /* programming error */
          writel(0, ha->mem_ptr + IPS_REG_FLAP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
          if (ha->revision_id == IPS_REVID_TROMBONE64)
-            UDELAY(5); /* 5 us */
+            udelay(5); /* 5 us */
 
          return (1);
       }
@@ -6526,11 +7416,11 @@
    /* Enable reading */
    writel(0, ha->mem_ptr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    writeb(0xFF, ha->mem_ptr + IPS_REG_FLDP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    return (0);
 }
@@ -6544,7 +7434,7 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_verify_bios(ips_ha_t *ha, char *buffer, int buffersize) {
+ips_verify_bios(ips_ha_t *ha, char *buffer, u32 buffersize, u32 offset) {
    u8    checksum;
    int   i;
 
@@ -6553,23 +7443,23 @@
    /* test 1st byte */
    outl(0, ha->io_addr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
       return (1);
 
    outl(1, ha->io_addr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
    if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
       return (1);
 
    checksum = 0xff;
    for (i = 2; i < buffersize; i++) {
 
-      outl(i, ha->io_addr + IPS_REG_FLAP);
+      outl(i + offset, ha->io_addr + IPS_REG_FLAP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       checksum = (u8) checksum + inb(ha->io_addr + IPS_REG_FLDP);
    }
@@ -6591,7 +7481,7 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_verify_bios_memio(ips_ha_t *ha, char *buffer, int buffersize) {
+ips_verify_bios_memio(ips_ha_t *ha, char *buffer, u32 buffersize, u32 offset) {
    u8    checksum;
    int   i;
 
@@ -6600,23 +7490,23 @@
    /* test 1st byte */
    writel(0, ha->mem_ptr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
 
    if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0x55)
       return (1);
 
    writel(1, ha->mem_ptr + IPS_REG_FLAP);
    if (ha->revision_id == IPS_REVID_TROMBONE64)
-      UDELAY(5); /* 5 us */
+      udelay(5); /* 5 us */
    if (readb(ha->mem_ptr + IPS_REG_FLDP) != 0xAA)
       return (1);
 
    checksum = 0xff;
    for (i = 2; i < buffersize; i++) {
 
-      writel(i, ha->mem_ptr + IPS_REG_FLAP);
+      writel(i + offset, ha->mem_ptr + IPS_REG_FLAP);
       if (ha->revision_id == IPS_REVID_TROMBONE64)
-         UDELAY(5); /* 5 us */
+         udelay(5); /* 5 us */
 
       checksum = (u8) checksum + readb(ha->mem_ptr + IPS_REG_FLDP);
    }
@@ -6631,7 +7521,6 @@
 
 static Scsi_Host_Template driver_template = IPS;
 #include "scsi_module.c"
-
 
 
 /*
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/ips.h linux/drivers/scsi/ips.h
--- v2.4.4/linux/drivers/scsi/ips.h	Mon Dec 11 13:38:29 2000
+++ linux/drivers/scsi/ips.h	Sat May 19 17:43:06 2001
@@ -69,13 +69,13 @@
 
    #define IPS_HA(x)                   ((ips_ha_t *) x->hostdata)
    #define IPS_COMMAND_ID(ha, scb)     (int) (scb - ha->scbs)
-   #define IPS_IS_TROMBONE(ha)         (((ha->device_id == IPS_COPPERHEAD_DEVICEID) && \
+   #define IPS_IS_TROMBONE(ha)         (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \
                                          (ha->revision_id >= IPS_REVID_TROMBONE32) && \
                                          (ha->revision_id <= IPS_REVID_TROMBONE64)) ? 1 : 0)
-   #define IPS_IS_CLARINET(ha)         (((ha->device_id == IPS_COPPERHEAD_DEVICEID) && \
+   #define IPS_IS_CLARINET(ha)         (((ha->device_id == IPS_DEVICEID_COPPERHEAD) && \
                                          (ha->revision_id >= IPS_REVID_CLARINETP1) && \
                                          (ha->revision_id <= IPS_REVID_CLARINETP3)) ? 1 : 0)
-   #define IPS_IS_MORPHEUS(ha)         (ha->device_id == IPS_MORPHEUS_DEVICEID)
+   #define IPS_IS_MORPHEUS(ha)         (ha->device_id == IPS_DEVICEID_MORPHEUS)
    #define IPS_USE_I2O_DELIVER(ha)     ((IPS_IS_MORPHEUS(ha) || \
                                          (IPS_IS_TROMBONE(ha) && \
                                           (ips_force_i2o))) ? 1 : 0)
@@ -99,23 +99,11 @@
    #ifndef verify_area_20
       #define verify_area_20(t,a,sz)   (0) /* success */
    #endif
-
-   #ifndef PUT_USER
-      #define PUT_USER                 put_user
-   #endif
-
-   #ifndef __PUT_USER
-      #define __PUT_USER               __put_user
-   #endif
-
-   #ifndef GET_USER
-      #define GET_USER                 get_user
-   #endif
    
-   #ifndef __GET_USER
-      #define __GET_USER               __get_user
+   #ifndef DECLARE_MUTEX_LOCKED
+      #define DECLARE_MUTEX_LOCKED(sem) struct semaphore sem = MUTEX_LOCKED;
    #endif
-   
+
    /*
     * Lock macros
     */
@@ -186,6 +174,7 @@
    #define IPS_CMD_DCDB_SG              0x84
    #define IPS_CMD_CONFIG_SYNC          0x58
    #define IPS_CMD_ERROR_TABLE          0x17
+   #define IPS_CMD_RW_BIOSFW            0x22
 
    /*
     * Adapter Equates
@@ -217,11 +206,16 @@
    #define IPS_INTR_HAL                 2
    #define IPS_ADAPTER_ID               0xF
    #define IPS_VENDORID                 0x1014
-   #define IPS_COPPERHEAD_DEVICEID      0x002E
-   #define IPS_MORPHEUS_DEVICEID        0x01BD
+   #define IPS_DEVICEID_COPPERHEAD      0x002E
+   #define IPS_DEVICEID_MORPHEUS        0x01BD
+   #define IPS_SUBDEVICEID_4M           0x01BE
+   #define IPS_SUBDEVICEID_4L           0x01BF
+   #define IPS_SUBDEVICEID_4MX          0x0208
+   #define IPS_SUBDEVICEID_4LX          0x020E
    #define IPS_IOCTL_SIZE               8192
    #define IPS_STATUS_SIZE              4
    #define IPS_STATUS_Q_SIZE            (IPS_MAX_CMDS+1) * IPS_STATUS_SIZE
+   #define IPS_IMAGE_SIZE               500 * 1024
    #define IPS_MEMMAP_SIZE              128
    #define IPS_ONE_MSEC                 1
    #define IPS_ONE_SEC                  1000
@@ -285,6 +279,21 @@
    #define IPS_REVID_TROMBONE64         0x10
 
    /*
+    * NVRAM Page 5 Adapter Defines
+    */
+   #define IPS_ADTYPE_SERVERAID         0x01
+   #define IPS_ADTYPE_SERVERAID2        0x02
+   #define IPS_ADTYPE_NAVAJO            0x03
+   #define IPS_ADTYPE_KIOWA             0x04
+   #define IPS_ADTYPE_SERVERAID3        0x05
+   #define IPS_ADTYPE_SERVERAID3L       0x06
+   #define IPS_ADTYPE_SERVERAID4H       0x07
+   #define IPS_ADTYPE_SERVERAID4M       0x08
+   #define IPS_ADTYPE_SERVERAID4L       0x09
+   #define IPS_ADTYPE_SERVERAID4MX      0x0A
+   #define IPS_ADTYPE_SERVERAID4LX      0x0B
+
+   /*
     * Adapter Command/Status Packet Definitions
     */
    #define IPS_SUCCESS                  0x01 /* Successfully completed       */
@@ -538,17 +547,41 @@
    u8     reserved2;
 } IPS_FFDC_CMD, *PIPS_FFDC_CMD;
 
+typedef struct {
+   u8     op_code;
+   u8     command_id;
+   u8     type;
+   u8     direction;
+   u32    count;
+   u32    buffer_addr;
+   u8     total_packets;
+   u8     packet_num;
+   u16    reserved;
+} IPS_FLASHFW_CMD, *PIPS_FLASHFW_CMD;
+
+typedef struct {
+   u8     op_code;
+   u8     command_id;
+   u8     type;
+   u8     direction;
+   u32    count;
+   u32    buffer_addr;
+   u32    offset;
+} IPS_FLASHBIOS_CMD, *PIPS_FLASHBIOS_CMD;
+
 typedef union {
-   IPS_IO_CMD        basic_io;
-   IPS_LD_CMD        logical_info;
-   IPS_IOCTL_CMD     ioctl_info;
-   IPS_DCDB_CMD      dcdb;
-   IPS_CS_CMD        config_sync;
-   IPS_US_CMD        unlock_stripe;
-   IPS_FC_CMD        flush_cache;
-   IPS_STATUS_CMD    status;
-   IPS_NVRAM_CMD     nvram;
-   IPS_FFDC_CMD      ffdc;
+   IPS_IO_CMD         basic_io;
+   IPS_LD_CMD         logical_info;
+   IPS_IOCTL_CMD      ioctl_info;
+   IPS_DCDB_CMD       dcdb;
+   IPS_CS_CMD         config_sync;
+   IPS_US_CMD         unlock_stripe;
+   IPS_FC_CMD         flush_cache;
+   IPS_STATUS_CMD     status;
+   IPS_NVRAM_CMD      nvram;
+   IPS_FFDC_CMD       ffdc;
+   IPS_FLASHFW_CMD    flashfw;
+   IPS_FLASHBIOS_CMD  flashbios;
 } IPS_HOST_COMMAND, *PIPS_HOST_COMMAND;
 
 typedef struct {
@@ -839,6 +872,19 @@
    int   option_value;
 } IPS_OPTION;
 
+typedef struct {
+   void             *userbuffer;
+   u32               usersize;
+   void             *kernbuffer;
+   u32               kernsize;
+   void             *ha;
+   void             *SC;
+   void             *pt;
+   struct semaphore *sem;
+   u32               offset;
+   u32               retcode;
+} IPS_FLASH_DATA;
+
 /*
  * Status Info
  */
@@ -893,8 +939,8 @@
    int  (*isintr)(struct ips_ha *);
    int  (*init)(struct ips_ha *);
    int  (*erasebios)(struct ips_ha *);
-   int  (*programbios)(struct ips_ha *, char *, int);
-   int  (*verifybios)(struct ips_ha *, char *, int);
+   int  (*programbios)(struct ips_ha *, char *, u32, u32);
+   int  (*verifybios)(struct ips_ha *, char *, u32, u32);
    u32  (*statupd)(struct ips_ha *);
    void (*statinit)(struct ips_ha *);
    void (*intr)(struct ips_ha *);
@@ -936,7 +982,11 @@
    u32                last_ffdc;          /* last time we sent ffdc info*/
    u8                 revision_id;        /* Revision level             */
    u16                device_id;          /* PCI device ID              */
-   u8                 reserved;
+   u8                 slot_num;           /* PCI Slot Number            */
+   u16                subdevice_id;       /* Subsystem device ID        */
+   u8                 ioctl_order;        /* Number of pages in ioctl   */
+   u8                 reserved2;          /* Empty                      */
+   u8                 bios_version[8];    /* BIOS Revision              */
    u32                mem_addr;           /* Memory mapped address      */
    u32                io_len;             /* Size of IO Address         */
    u32                mem_len;            /* Size of memory address     */
@@ -947,6 +997,9 @@
    spinlock_t         scb_lock;
    spinlock_t         copp_lock;
    spinlock_t         ips_lock;
+   char              *save_ioctl_data;    /* Save Area for ioctl_data   */
+   u8                 save_ioctl_order;   /* Save Area for ioctl_order  */
+   u32                save_ioctl_datasize;/* Save Area for ioctl_datasize */
 } ips_ha_t;
 
 typedef void (*ips_scb_callback) (ips_ha_t *, struct ips_scb *);
@@ -966,7 +1019,8 @@
    u32               timeout;
    u8                basic_status;
    u8                extended_status;
-   u16               breakup;
+   u8                breakup;
+   u8                sg_break;
    u32               data_len;
    u32               sg_len;
    u32               flags;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- v2.4.4/linux/drivers/scsi/pci2220i.c	Fri Apr 27 13:59:19 2001
+++ linux/drivers/scsi/pci2220i.c	Mon Apr 30 17:13:07 2001
@@ -2657,7 +2657,7 @@
 		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
 			DiskMirror[z].status = inb_p (padapter->regScratchPad + BIGD_RAID_0_STATUS + z);		
 
-		scsi_set_pci_info(pshost, pcidev);
+		scsi_set_pci_device(pshost, pcidev);
 		pshost->max_id = padapter->numberOfDrives;
 		padapter->failRegister = inb_p (padapter->regScratchPad + BIGD_ALARM_IMAGE);
 		for ( z = 0;  z < padapter->numberOfDrives;  z++ )
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/qlogicfas.c linux/drivers/scsi/qlogicfas.c
--- v2.4.4/linux/drivers/scsi/qlogicfas.c	Wed Apr 11 19:02:37 2001
+++ linux/drivers/scsi/qlogicfas.c	Tue May 22 10:23:16 2001
@@ -563,6 +563,7 @@
 			if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
 			  && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
 				break;
+			release_region(qbase, 0x10 );
 		}
 		if (qbase == 0x430)
 			return 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.4.4/linux/drivers/scsi/scsi.c	Wed Apr 25 16:18:54 2001
+++ linux/drivers/scsi/scsi.c	Thu May 24 15:34:14 2001
@@ -104,7 +104,7 @@
 const unsigned char scsi_command_size[8] =
 {
 	6, 10, 10, 12,
-	16, 12, 10, 10
+	12, 12, 10, 10
 };
 static unsigned long serial_number;
 static Scsi_Cmnd *scsi_bh_queue_head;
@@ -843,7 +843,7 @@
 	 */
 	scsi_insert_special_req(SRpnt, 0);
 
-	SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_cmd()\n"));
+	SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_req()\n"));
 }
  
 /*
@@ -929,7 +929,7 @@
 	SCpnt->abort_reason = 0;
 	SCpnt->result = 0;
 
-	SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_do_cmd()\n"));
+	SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n"));
 }
 
 /*
@@ -1572,6 +1572,11 @@
 	copy_from_user(buffer, buf, length);
 
 	err = -EINVAL;
+	if (length < PAGE_SIZE)
+		buffer[length] ='\0';
+	else if (buffer[length])
+		goto out;
+
 	if (length < 11 || strncmp("scsi", buffer, 4))
 		goto out;
 
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.4.4/linux/drivers/scsi/scsi_lib.c	Fri Mar  2 18:38:39 2001
+++ linux/drivers/scsi/scsi_lib.c	Fri May  4 15:16:28 2001
@@ -1108,9 +1108,13 @@
  */
 void scsi_unblock_requests(struct Scsi_Host * SHpnt)
 {
+	Scsi_Device *SDloop;
+
 	SHpnt->host_self_blocked = FALSE;
+	/* Now that we are unblocked, try to start the queues. */
+	for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next)
+		scsi_queue_next_request(&SDloop->request_queue, NULL);
 }
-
 
 /*
  * Function:    scsi_report_bus_reset()
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v2.4.4/linux/drivers/scsi/scsi_proc.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/scsi/scsi_proc.c	Sat May 19 17:43:06 2001
@@ -104,7 +104,11 @@
 
 	if (!(page = (char *) __get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
-	copy_from_user(page, buf, count);
+	if(copy_from_user(page, buf, count))
+	{
+		free_page((ulong) page);
+		return -EFAULT;
+	}
 
 	if (hpnt->hostt->proc_info == NULL)
 		ret = -ENOSYS;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.4.4/linux/drivers/scsi/sd.c	Sat Feb  3 11:45:55 2001
+++ linux/drivers/scsi/sd.c	Sat Apr 28 11:28:08 2001
@@ -993,8 +993,7 @@
 		the_result = SRpnt->sr_result;
 
 		if (the_result) {
-			printk("%s: test WP failed, assume Write Protected\n", nbuff);
-			rscsi_disks[i].write_prot = 1;
+			printk("%s: test WP failed, assume Write Enabled\n", nbuff);
 		} else {
 			rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0);
 			printk("%s: Write Protect is %s\n", nbuff,
@@ -1261,12 +1260,7 @@
 
 	for (i = max_p - 1; i >= 0; i--) {
 		int index = start + i;
-		kdev_t devi = MKDEV_SD_PARTITION(index);
-		struct super_block *sb = get_super(devi);
-		sync_dev(devi);
-		if (sb)
-			invalidate_inodes(sb);
-		invalidate_buffers(devi);
+		invalidate_device(MKDEV_SD_PARTITION(index), 1);
 		sd_gendisks->part[index].start_sect = 0;
 		sd_gendisks->part[index].nr_sects = 0;
 		/*
@@ -1314,12 +1308,7 @@
 
 			for (j = max_p - 1; j >= 0; j--) {
 				int index = start + j;
-				kdev_t devi = MKDEV_SD_PARTITION(index);
-				struct super_block *sb = get_super(devi);
-				sync_dev(devi);
-				if (sb)
-					invalidate_inodes(sb);
-				invalidate_buffers(devi);
+				invalidate_device(MKDEV_SD_PARTITION(index), 1);
 				sd_gendisks->part[index].start_sect = 0;
 				sd_gendisks->part[index].nr_sects = 0;
 				sd_sizes[index] = 0;
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.4.4/linux/drivers/scsi/sr.c	Mon Feb 19 10:25:17 2001
+++ linux/drivers/scsi/sr.c	Sat Apr 28 11:28:08 2001
@@ -496,13 +496,6 @@
 	return 0;
 }
 
-/*
- * do_sr_request() is the request handler function for the sr driver.
- * Its function in life is to take block device requests, and
- * translate them to SCSI commands.
- */
-
-
 static int sr_detect(Scsi_Device * SDp)
 {
 
@@ -869,16 +862,11 @@
 
 	for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++)
 		if (cpnt->device == SDp) {
-			kdev_t devi = MKDEV(MAJOR_NR, i);
-			struct super_block *sb = get_super(devi);
-
 			/*
 			 * Since the cdrom is read-only, no need to sync the device.
 			 * We should be kind to our buffer cache, however.
 			 */
-			if (sb)
-				invalidate_inodes(sb);
-			invalidate_buffers(devi);
+			invalidate_device(MKDEV(MAJOR_NR, i), 0);
 
 			/*
 			 * Reset things back to a sane state so that one can re-load a new
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.4.4/linux/drivers/scsi/u14-34f.c	Sun Feb  4 10:05:30 2001
+++ linux/drivers/scsi/u14-34f.c	Sat May 19 17:43:06 2001
@@ -1,6 +1,9 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *       1 May 2001 Rev. 6.05 for linux 2.4.4
+ *        + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d)
+ *
  *      25 Jan 2001 Rev. 6.03 for linux 2.4.0
  *        + "check_region" call replaced by "request_region".
  *
@@ -1005,7 +1008,7 @@
    static const unsigned char data_out_cmds[] = {
       0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
       0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
-      0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
+      0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b, 0x5d
       };
 
    static const unsigned char data_none_cmds[] = {
diff -u --recursive --new-file v2.4.4/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v2.4.4/linux/drivers/scsi/u14-34f.h	Sun Feb  4 10:05:30 2001
+++ linux/drivers/scsi/u14-34f.h	Sat May 19 17:43:06 2001
@@ -13,7 +13,7 @@
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "6.03.00"
+#define U14_34F_VERSION "6.05.00"
 
 #define ULTRASTOR_14_34F {                                                   \
                 name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/cs4281/cs4281m.c linux/drivers/sound/cs4281/cs4281m.c
--- v2.4.4/linux/drivers/sound/cs4281/cs4281m.c	Wed Apr 18 11:49:11 2001
+++ linux/drivers/sound/cs4281/cs4281m.c	Tue May  1 16:05:00 2001
@@ -194,9 +194,6 @@
         }                                         \
 })
 
-#define list_for_each(pos, head) \
-        for (pos = (head)->next; pos != (head); pos = pos->next)
-
 //LIST_HEAD(cs4281_devs);
 struct list_head cs4281_devs = { &cs4281_devs, &cs4281_devs };
 
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c
--- v2.4.4/linux/drivers/sound/cs46xx.c	Thu Apr 12 12:16:36 2001
+++ linux/drivers/sound/cs46xx.c	Thu May 24 15:14:08 2001
@@ -47,6 +47,9 @@
  *	20010117-tw	2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0
  *	20010118-tw	basic PM support for 2.2.16+ and 2.4.0/2.4.2.
  *	20010228-dh	patch from David Huggins - cs_update_ptr recursion.
+ *	20010409-tw	add hercules game theatre XP amp code.
+ *	20010420-tw	cleanup powerdown/up code.
+ *	20010521-tw	eliminate pops, and fixes for powerdown.
  *
  *	Status:
  *	Playback/Capture supported from 8k-48k.
@@ -56,9 +59,9 @@
  *	be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro
  *	definition.
  *
- *      Hercules Game Pro XP - the EGPIO2 pin controls the external Amp,
- *	but the static image can not modify the EGPIO pins, so we can not
- *	turn on the external amp.
+ *      Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp,
+ *	so, use the drain/polarity to enable.  
+ *	hercules_egpio_disable set to 1, will force a 0 to EGPIODR.
  *
  *	VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control
  *	the external amplifier for the "back" speakers, since we do not
@@ -109,6 +112,11 @@
 #define CS_TRUE 	1
 #define CS_FALSE 	0
 
+#define CS_INC_USE_COUNT(m) (atomic_inc(m))
+#define CS_DEC_USE_COUNT(m) (atomic_dec(m))
+#define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m))
+#define CS_IN_USE(m) (atomic_read(m) != 0)
+
 #define CS_DBGBREAKPOINT {__asm__("INT $3");}
 /*
  *	CS461x definitions
@@ -167,6 +175,8 @@
 static unsigned long cs_debugmask=CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */
 MODULE_PARM(cs_debugmask, "i");
 #endif
+static unsigned long hercules_egpio_disable=0;  /* if non-zero set all EGPIO to 0 */
+MODULE_PARM(hercules_egpio_disable, "i");
 static unsigned long initdelay=700;  /* PM delay in millisecs */
 MODULE_PARM(initdelay, "i");
 static unsigned long powerdown=1;  /* turn on/off powerdown processing in driver */
@@ -189,7 +199,7 @@
 };
 
 #define CS46XX_MAJOR_VERSION "1"
-#define CS46XX_MINOR_VERSION "22"
+#define CS46XX_MINOR_VERSION "27"
 
 #ifdef __ia64__
 #define CS46XX_ARCH	     	"64"	//architecture key
@@ -287,6 +297,9 @@
 	   so we use a single per card lock */
 	spinlock_t lock;
 
+	/* mixer use count */
+	atomic_t mixer_use_cnt;
+
 	/* PCI device stuff */
 	struct pci_dev * pci_dev;
 	struct list_head list;
@@ -358,6 +371,7 @@
 static int cs_hardware_init(struct cs_card *card);
 static int cs46xx_powerup(struct cs_card *card, unsigned int type);
 static int cs461x_powerdown(struct cs_card *card, unsigned int type);
+static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
 
 static inline unsigned ld2(unsigned int x)
 {
@@ -667,6 +681,45 @@
 			dmabuf->divisor) );
 }
 
+/*
+* mute some of the more prevalent registers to avoid popping.
+*/
+static void cs_mute(struct cs_card *card, int state) 
+{
+	struct ac97_codec *dev=card->ac97_codec[0];
+
+	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()+ %s\n",
+		(state == CS_TRUE) ? "Muting" : "UnMuting") );
+
+	if(state == CS_TRUE)
+	{
+	/*
+	* fix pops when powering up on thinkpads
+	*/
+		card->pm.u32AC97_master_volume = (u32)cs_ac97_get( dev, 
+				(u8)BA0_AC97_MASTER_VOLUME); 
+		card->pm.u32AC97_headphone_volume = (u32)cs_ac97_get(dev, 
+				(u8)BA0_AC97_HEADPHONE_VOLUME); 
+		card->pm.u32AC97_master_volume_mono = (u32)cs_ac97_get(dev, 
+				(u8)BA0_AC97_MASTER_VOLUME_MONO); 
+		card->pm.u32AC97_pcm_out_volume = (u32)cs_ac97_get(dev, 
+				(u8)BA0_AC97_PCM_OUT_VOLUME);
+			
+		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, 0x8000);
+		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
+		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
+		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
+	}
+	else
+	{
+		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume);
+		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume);
+		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono);
+		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, card->pm.u32AC97_pcm_out_volume);
+	}
+	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mute()-\n"));
+}
+
 /* set playback sample rate */
 static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate)
 {	
@@ -1386,12 +1439,17 @@
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct dmabuf *dmabuf = &state->dmabuf;
+	struct cs_card *card=state->card;
 	unsigned long flags;
 	unsigned long tmo;
 	int count;
 
+	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()+ \n"));
 	if (dmabuf->mapped || !dmabuf->ready)
+	{
+		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0, not ready\n"));
 		return 0;
+	}
 
 	add_wait_queue(&dmabuf->wait, &wait);
 	for (;;) {
@@ -1427,8 +1485,16 @@
 	remove_wait_queue(&dmabuf->wait, &wait);
 	current->state = TASK_RUNNING;
 	if (signal_pending(current))
+	{
+		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n"));
+		/*
+		* set to silence and let that clear the fifos.
+		*/
+		cs461x_clear_serial_FIFOs(card, CS_TYPE_DAC);
 		return -ERESTARTSYS;
+	}
 
+	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- 0\n"));
 	return 0;
 }
 
@@ -1524,7 +1590,7 @@
 				}
 
 				if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
-					CS_DBGOUT(CS_ERROR, 2, printk(
+					CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
 					  "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",
 					  	dmabuf->count));
 					/* 
@@ -1584,7 +1650,7 @@
 	struct cs_state *playstate = card->channel[1].state;
 	u32 status;
 
-	CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()+ \n"));
+	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n"));
 
 	spin_lock(&card->lock);
 
@@ -1614,7 +1680,7 @@
  	/* clear 'em */
 	cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
 	spin_unlock(&card->lock);
-	CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()- \n"));
+	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n"));
 }
 
 
@@ -2298,7 +2364,7 @@
 		if(state)
 		{
 			CS_DBGOUT(CS_OPEN, 2, printk(
-			  "cs46xx: cs_mmap() VM_WRITE - state CS_TRUE prog_dmabuf DAC\n") );
+			  "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
 			if ((ret = prog_dmabuf(state)) != 0)
 				return ret;
 		}
@@ -2307,7 +2373,7 @@
 		if(state)
 		{
 			CS_DBGOUT(CS_OPEN, 2, printk(
-			  "cs46xx: cs_mmap() VM_READ - state CS_TRUE prog_dmabuf ADC\n") );
+			  "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
 			if ((ret = prog_dmabuf(state)) != 0)
 				return ret;
 		}
@@ -2955,31 +3021,36 @@
 	}
 }
 
+		       
 /*
- *	For the VTB Santa Cruz card, the Secondary Codec must have the 
- *	GPIO pins 7 and 8 manipulated, not the Primary codec.
- *	Currently, only the primary codec is supported, so the following
- *	code will not function.  Additionally, slot 12 must be setup
- *	to allow proper output for 7 and 8 to occur (trw).
+ *	Game Theatre XP card - EGPIO[2] is used to enable the external amp.
  */
  
-static void amp_voyetra_4294(struct cs_card *card, int change)
+static void amp_hercules(struct cs_card *card, int change)
 {
-	struct ac97_codec *c=card->ac97_codec[0];
-	
+	int old=card->amplifier;
+	if(!card)
+	{
+		CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO 
+			"cs46xx: amp_hercules() called before initialized.\n"));
+		return;
+	}
 	card->amplifier+=change;
-
-	if(card->amplifier)
+	if( (card->amplifier && !old) && !(hercules_egpio_disable))
 	{
-		/* Switch the GPIO pins 7 and 8 to open drain */
-		cs_ac97_set(c, 0x4C, cs_ac97_get(c, 0x4C) & 0xFE7F);
-		cs_ac97_set(c, 0x4E, cs_ac97_get(c, 0x4E) | 0x0180);
-		/* Now wake the AMP (this might be backwards) */
-		cs_ac97_set(c, 0x54, cs_ac97_get(c, 0x54) & ~0x0180);
+		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
+			"cs46xx: amp_hercules() external amp enabled\n"));
+		cs461x_pokeBA0(card, BA0_EGPIODR, 
+			EGPIODR_GPOE2);     /* enable EGPIO2 output */
+		cs461x_pokeBA0(card, BA0_EGPIOPTR, 
+			EGPIOPTR_GPPT2);   /* open-drain on output */
 	}
-	else
+	else if(old && !card->amplifier)
 	{
-		cs_ac97_set(c, 0x54, cs_ac97_get(c, 0x54) | 0x0180);
+		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
+			"cs46xx: amp_hercules() external amp disabled\n"));
+		cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */
+		cs461x_pokeBA0(card, BA0_EGPIOPTR, 0); /* disable */
 	}
 }
 
@@ -3016,7 +3087,7 @@
 	/* Flip CLKRUN off while running */
 	if(!card->active && old)
 	{
-		CS_DBGOUT(CS_PARMS , 9, printk(
+		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
 			"cs46xx: clkrun() enable clkrun - change=%d active=%d\n",
 				change,card->active));
 		outw(control|0x2000, port+0x10);
@@ -3026,7 +3097,7 @@
 	/*
 	* sometimes on a resume the bit is set, so always reset the bit.
 	*/
-		CS_DBGOUT(CS_PARMS , 9, printk(
+		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
 			"cs46xx: clkrun() disable clkrun - change=%d active=%d\n",
 				change,card->active));
 		outw(control&~0x2000, port+0x10);
@@ -3404,7 +3475,7 @@
 			"cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp) );
 	}
 
-	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs46xx_ac97_suspend()-\n"));
+	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n"));
 }
 
 /****************************************************************************
@@ -3417,7 +3488,7 @@
 	int Count,i;
 	struct ac97_codec *dev=card->ac97_codec[0];
 
-	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs46xx_ac97_resume()+\n"));
+	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()+\n"));
 
 /*
 * First, we restore the state of the general purpose register.  This
@@ -3458,7 +3529,7 @@
 	if(card->amp_init)
 		card->amp_init(card);
         
-	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs46xx_ac97_resume()-\n"));
+	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n"));
 }
 
 
@@ -3521,7 +3592,7 @@
 {
 	unsigned int tmp;
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk("cs46xx: cs46xx_suspend()+ flags=%d s=0x%x\n",
+		printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=0x%x\n",
 			(unsigned)card->pm.flags,(unsigned)card));
 /*
 * check the current state, only suspend if IDLE
@@ -3604,7 +3675,7 @@
 	printpm(card);
 
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk("cs46xx: cs46xx_suspend()- flags=%d\n",
+		printk("cs46xx: cs46xx_suspend()- flags=0x%x\n",
 			(unsigned)card->pm.flags));
 	return 0;
 }
@@ -3614,7 +3685,7 @@
 	int i;
 
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
-		printk( "cs46xx: cs46xx_resume()+ flags=%d\n",
+		printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n",
 			(unsigned)card->pm.flags));
 	if(!(card->pm.flags & CS46XX_PM_SUSPENDED))
 	{
@@ -3654,7 +3725,7 @@
 
 	card->active_ctrl(card, -1);
 
-	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=%d\n",
+	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, printk("cs46xx: cs46xx_resume()- flags=0x%x\n",
 		(unsigned)card->pm.flags));
 	return 0;
 }
@@ -3919,12 +3990,17 @@
 	file->private_data = card->ac97_codec[i];
 
 	card->active_ctrl(card,1);
-	if( (tmp = cs46xx_powerup(card, CS_POWER_MIXVON )) )
+	if(!CS_IN_USE(&card->mixer_use_cnt))
 	{
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs_open_mixdev() powerup failure (0x%x)\n",tmp) );
-		return -EIO;
+		if( (tmp = cs46xx_powerup(card, CS_POWER_MIXVON )) )
+		{
+			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
+				"cs46xx: cs_open_mixdev() powerup failure (0x%x)\n",tmp) );
+			return -EIO;
+		}
 	}
+	card->amplifier_ctrl(card, 1);
+	CS_INC_USE_COUNT(&card->mixer_use_cnt);
 	MOD_INC_USE_COUNT;
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
 		  printk(KERN_INFO "cs46xx: cs_open_mixdev()- 0\n"));
@@ -3938,8 +4014,9 @@
 	struct list_head *entry;
 	int i;
 	unsigned int tmp;
-	
-	
+
+	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
+		  printk(KERN_INFO "cs46xx: cs_release_mixdev()+\n"));
 	list_for_each(entry, &cs46xx_devs)
 	{
 		card = list_entry(entry, struct cs_card, list);
@@ -3955,14 +4032,26 @@
 		return -ENODEV;
 	}
 match:
+	card->active_ctrl(card, -1);
+	card->amplifier_ctrl(card, -1);
+	MOD_DEC_USE_COUNT;
+	if(!CS_DEC_AND_TEST(&card->mixer_use_cnt))
+	{
+		CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
+			  printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n"));
+		return 0;
+	}
+/*
+* ok, no outstanding mixer opens, so powerdown.
+*/
 	if( (tmp = cs461x_powerdown(card, CS_POWER_MIXVON )) )
 	{
 		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
 			"cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n",tmp) );
 		return -EIO;
 	}
-	card->active_ctrl(card, -1);
-	MOD_DEC_USE_COUNT;
+	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
+		  printk(KERN_INFO "cs46xx: cs_release_mixdev()- 0\n"));
 	return 0;
 }
 
@@ -4027,7 +4116,7 @@
 			else
 			{
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
-				    "cs4281: mixer_ioctl(): invalid APM cmd (%d)\n",
+				    "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n",
 					val));
 			}
 			return 0;
@@ -4181,9 +4270,9 @@
 	cs461x_poke(card, BA1_FRMT, 0xadf);
 }
 
-static void cs461x_clear_serial_FIFOs(struct cs_card *card)
+static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type)
 {
-	int idx, loop, powerdown = 0;
+	int idx, loop, startfifo=0, endfifo=0, powerdown1 = 0;
 	unsigned int tmp;
 
 	/*
@@ -4192,7 +4281,7 @@
 	 */
 	if (!((tmp = cs461x_peekBA0(card, BA0_CLKCR1)) & CLKCR1_SWCE)) {
 		cs461x_pokeBA0(card, BA0_CLKCR1, tmp | CLKCR1_SWCE);
-		powerdown = 1;
+		powerdown1 = 1;
 	}
 
 	/*
@@ -4203,9 +4292,25 @@
 	cs461x_pokeBA0(card, BA0_SERBWP, 0);
 
 	/*
-	 *  Fill all 256 sample FIFO locations.
+	* Check for which FIFO locations to clear, if we are currently
+	* playing or capturing then we don't want to put in 128 bytes of
+	* "noise".
+	 */
+	if(type & CS_TYPE_DAC)
+	{
+		startfifo = 128;
+		endfifo = 256;
+	}
+	if(type & CS_TYPE_ADC)
+	{
+		startfifo = 0;
+		if(!endfifo)
+			endfifo = 128;
+	}
+	/*
+	 *  Fill sample FIFO locations (256 locations total).
 	 */
-	for (idx = 0; idx < 256; idx++) {
+	for (idx = startfifo; idx < endfifo; idx++) {
 		/*
 		 *  Make sure the previous FIFO write operation has completed.
 		 */
@@ -4215,7 +4320,7 @@
 				break;
 		}
 		if (cs461x_peekBA0(card, BA0_SERBST) & SERBST_WBSY) {
-			if (powerdown)
+			if (powerdown1)
 				cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
 		}
 		/*
@@ -4231,7 +4336,7 @@
 	 *  Now, if we powered up the devices, then power them back down again.
 	 *  This is kinda ugly, but should never happen.
 	 */
-	if (powerdown)
+	if (powerdown1)
 		cs461x_pokeBA0(card, BA0_CLKCR1, tmp);
 }
 
@@ -4268,6 +4373,15 @@
 			"cs46xx: cs461x_powerdown()- 0  unable to powerdown. tmp=0x%x\n",tmp));
 		return 0;
 	}
+/*
+* for now, always keep power to the mixer block.
+* not sure why it's a problem but it seems to be if we power off.
+*/
+	type &= ~CS_POWER_MIXVON;
+	type &= ~CS_POWER_MIXVOFF;
+
+	cs_mute(card, CS_TRUE);
+
 	/*
 	 *  Power down indicated areas.
 	 */
@@ -4443,6 +4557,7 @@
 		}
 	}
 	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
+	cs_mute(card, CS_FALSE);
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
 		"cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp));
 	return 0;
@@ -4462,6 +4577,8 @@
 		type |= CS_POWER_MIXVOFF;
 	if(type & (CS_POWER_DAC | CS_POWER_ADC))
 		type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF;
+
+	cs_mute(card, CS_TRUE);
 	/*
 	 *  Power up indicated areas.
 	 */
@@ -4637,6 +4754,7 @@
 		}
 	}
 	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
+	cs_mute(card, CS_FALSE);
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
 		"cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp));
 	return 0;
@@ -4741,7 +4859,6 @@
 	*/
 	if(!(card->pm.flags & CS46XX_PM_IDLE))
 		mdelay(initdelay);
-
 	/*
 	 *  Write the selected clock control setup to the hardware.  Do not turn on
 	 *  SWCE yet (if requested), so that the devices clocked by the output of
@@ -4770,7 +4887,7 @@
 	/*
 	 *  Fill the serial port FIFOs with silence.
 	 */
-	cs461x_clear_serial_FIFOs(card);
+	cs461x_clear_serial_FIFOs(card,CS_TYPE_DAC | CS_TYPE_ADC);
 
 	/*
 	 *  Set the serial port FIFO pointer to the first sample in the FIFO.
@@ -4951,12 +5068,25 @@
 	 */
 	if(card->pm.flags & CS46XX_PM_IDLE)
 	{
-		if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-				CS_POWER_MIXVON )) )
+		if(!powerdown)
 		{
-			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
-			return -EIO;
+			if( (tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
+					CS_POWER_MIXVON )) )
+			{
+				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
+					"cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) );
+				return -EIO;
+			}
+		}
+		else
+		{
+			if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
+					CS_POWER_MIXVON )) )
+			{
+				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
+					"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
+				return -EIO;
+			}
 		}
 	}
 	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
@@ -4964,11 +5094,9 @@
 	return 0;
 }
 
-
 /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
    until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
    
-   
 /*
  *	Card subid table
  */
@@ -4987,8 +5115,12 @@
 	{0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL, NULL},
 	{0x5053, 0x3357, "Voyetra", amp_voyetra, NULL, NULL},
 	{0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL, NULL},
-	{0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL},
-	{0x1681, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL},
+	{0x14AF, 0x0050, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+	{0x1681, 0x0050, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+	{0x1681, 0x0051, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+	{0x1681, 0x0052, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+	{0x1681, 0x0053, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+	{0x1681, 0x0054, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
 	/* Not sure if the 570 needs the clkrun hack */
 	{PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", amp_none, NULL, clkrun_hack},
 	{PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack},
@@ -5016,6 +5148,11 @@
 	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
 		  printk(KERN_INFO "cs46xx: probe()+\n"));
 
+	if (pci_enable_device(pci_dev)) {
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
+			 "cs46xx: pci_enable_device() failed\n"));
+		return -1;
+	}
 	if (!RSRCISMEMORYREGION(pci_dev, 0) ||
 	    !RSRCISMEMORYREGION(pci_dev, 1)) {
 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
@@ -5042,12 +5179,6 @@
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(*card));
-
-	if (pci_enable_device(pci_dev)) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
-			 "cs46xx: pci_enable_device() failed\n"));
-		goto fail2;
-	}
 	card->ba0_addr = RSRCADDRESS(pci_dev, 0);
 	card->ba1_addr = RSRCADDRESS(pci_dev, 1);
 	card->pci_dev = pci_dev;
@@ -5096,7 +5227,7 @@
 		card->amplifier_ctrl = amp_none;
 		card->active_ctrl = clkrun_hack;
 	}		
-		       
+
 	if (external_amp == 1)
 	{
 		printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n");
@@ -5120,7 +5251,7 @@
 	card->ba1.name.reg = ioremap_nocache(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE);
 	
 	CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO 
-		"cs46xx: card->ba0=0x%.08x\n",(unsigned)card->ba0) );
+		"cs46xx: card=0x%x card->ba0=0x%.08x\n",(unsigned)card,(unsigned)card->ba0) );
 	CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO 
 		"cs46xx: card->ba1=0x%.08x 0x%.08x 0x%.08x 0x%.08x\n",
 			(unsigned)card->ba1.name.data0,
@@ -5319,9 +5450,9 @@
 	unregister_sound_dsp(card->dev_audio);
         if(card->dev_midi)
                 unregister_sound_midi(card->dev_midi);
+	list_del(&card->list);
 	kfree(card);
 	PCI_SET_DRIVER_DATA(pci_dev,NULL);
-	list_del(&card->list);
 
 	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
 		 "cs46xx: cs46xx_remove()-: remove successful\n"));
@@ -5329,8 +5460,8 @@
 
 enum {
 	CS46XX_4610 = 0,
-	CS46XX_4612,  	/* same as 4624 */
-	CS46XX_4615,  	/* same as 4630 */
+	CS46XX_4612,  	/* same as 4630 */
+	CS46XX_4615,  	/* same as 4624 */
 };
 
 static struct pci_device_id cs46xx_pci_tbl[] __devinitdata = {
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/emu10k1/cardwo.c linux/drivers/sound/emu10k1/cardwo.c
--- v2.4.4/linux/drivers/sound/emu10k1/cardwo.c	Mon Aug 14 08:32:48 2000
+++ linux/drivers/sound/emu10k1/cardwo.c	Sat May 19 17:43:07 2001
@@ -87,7 +87,8 @@
 
 			pageindex = buffer->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
 
-			((u32 *) card->virtualpagetable.addr)[pageindex] = (busaddx * 2) | pageindex;
+			((u32 *) card->virtualpagetable.addr)[pageindex] =
+            cpu_to_le32((busaddx * 2) | pageindex);
 		}
 	}
 
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
--- v2.4.4/linux/drivers/sound/emu10k1/main.c	Tue Mar 20 12:04:59 2001
+++ linux/drivers/sound/emu10k1/main.c	Sat May 19 17:43:07 2001
@@ -475,7 +475,8 @@
 	}
 
 	for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
-		((u32 *) card->virtualpagetable.addr)[pagecount] = (card->silentpage.dma_handle * 2) | pagecount;
+		((u32 *) card->virtualpagetable.addr)[pagecount] =
+         cpu_to_le32((card->silentpage.dma_handle * 2) | pagecount);
 
 	/* Init page table & tank memory base register */
 	sblive_writeptr_tag(card, 0,
@@ -612,6 +613,10 @@
 {
 	struct emu10k1_card *card;
 	u32 subsysvid;
+	int ret;
+
+	if ((ret=pci_enable_device(pci_dev)))
+		return ret;
 
 	if ((card = kmalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "emu10k1: out of memory\n");
@@ -621,11 +626,6 @@
 
 	if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) {
 		printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n");
-		kfree(card);
-		return -ENODEV;
-	}
-
-	if (pci_enable_device(pci_dev)) {
 		kfree(card);
 		return -ENODEV;
 	}
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/emu10k1/midi.c linux/drivers/sound/emu10k1/midi.c
--- v2.4.4/linux/drivers/sound/emu10k1/midi.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/sound/emu10k1/midi.c	Sat May 19 17:43:07 2001
@@ -56,7 +56,7 @@
 {
 	struct midi_hdr *midihdr;
 
-	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr *), GFP_KERNEL)) == NULL) {
+	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL) {
 		ERROR();
 		return -EINVAL;
 	}
@@ -328,7 +328,7 @@
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 
-	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr *), GFP_KERNEL)) == NULL)
+	if ((midihdr = (struct midi_hdr *) kmalloc(sizeof(struct midi_hdr), GFP_KERNEL)) == NULL)
 		return -EINVAL;
 
 	midihdr->bufferlength = count;
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.4.4/linux/drivers/sound/es1370.c	Thu Apr 12 12:16:36 2001
+++ linux/drivers/sound/es1370.c	Tue May 22 10:23:16 2001
@@ -2560,19 +2560,21 @@
 	{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
 };
 
-#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
-				 pci_resource_flags((dev), (num)) & IORESOURCE_IO)
-
 static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1370_state *s;
 	mm_segment_t fs;
-	int i, val;
+	int i, val, ret;
+
+	if ((ret=pci_enable_device(pcidev)))
+		return ret;
 
-	if (!RSRCISIOREGION(pcidev, 0))
-		return -1;
+	if ( !(pci_resource_flags(pcidev, 0) & IORESOURCE_IO) ||
+	     !pci_resource_start(pcidev, 0)
+	)
+		return -ENODEV;
 	if (pcidev->irq == 0) 
-		return -1;
+		return -ENODEV;
 	i = pci_set_dma_mask(pcidev, 0xffffffff);
 	if (i) {
 		printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n");
@@ -2580,7 +2582,7 @@
 	}
 	if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
 		printk(KERN_WARNING "es1370: out of memory\n");
-		return -1;
+		return -ENOMEM;
 	}
 	memset(s, 0, sizeof(struct es1370_state));
 	init_waitqueue_head(&s->dma_adc.wait);
@@ -2597,14 +2599,14 @@
 	s->irq = pcidev->irq;
 	if (!request_region(s->io, ES1370_EXTENT, "es1370")) {
 		printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
+		ret = -EBUSY;
 		goto err_region;
 	}
-	if (pci_enable_device(pcidev))
-		goto err_irq;
-	if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
+	if ((ret=request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370",s))) {
 		printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
 		goto err_irq;
 	}
+
 	/* initialize codec registers */
 	/* note: setting CTRL_SERR_DIS is reported to break
 	 * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
@@ -2631,14 +2633,22 @@
 	       (s->ctrl & CTRL_XCTL0) ? "out" : "in",
 		       (s->ctrl & CTRL_XCTL1) ? "1" : "0");
 	/* register devices */
-	if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
+	if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) {
+		ret = s->dev_audio;
 		goto err_dev1;
-	if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
+	}
+	if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0) {
+		ret = s->dev_mixer;
 		goto err_dev2;
-	if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
+	}
+	if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0) {
+		ret = s->dev_dac;
 		goto err_dev3;
-	if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
+	}
+	if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0) {
+		ret = s->dev_midi;
 		goto err_dev4;
+	}
 	/* initialize the chips */
 	outl(s->ctrl, s->io+ES1370_REG_CONTROL);
 	outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
@@ -2688,7 +2698,7 @@
 	release_region(s->io, ES1370_EXTENT);
  err_region:
 	kfree(s);
-	return -1;
+	return ret;
 }
 
 static void __devinit es1370_remove(struct pci_dev *dev)
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.4.4/linux/drivers/sound/es1371.c	Thu Apr 12 12:16:36 2001
+++ linux/drivers/sound/es1371.c	Tue May 22 10:23:16 2001
@@ -2771,22 +2771,22 @@
 	{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
 };
 
-#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
-				 (pci_resource_flags((dev), (num)) & IORESOURCE_IO))
-
 static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1371_state *s;
 	mm_segment_t fs;
-	int i, val;
+	int i, val, res = -1;
 	unsigned long tmo;
 	signed long tmo2;
 	unsigned int cssr;
 
-	if (!RSRCISIOREGION(pcidev, 0))
-		return -1;
+	if ((res=pci_enable_device(pcidev)))
+		return res;
+
+	if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO))
+		return -ENODEV;
 	if (pcidev->irq == 0) 
-		return -1;
+		return -ENODEV;
 	i = pci_set_dma_mask(pcidev, 0xffffffff);
 	if (i) {
 		printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
@@ -2794,7 +2794,7 @@
 	}
 	if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
 		printk(KERN_WARNING PFX "out of memory\n");
-		return -1;
+		return -ENOMEM;
 	}
 	memset(s, 0, sizeof(struct es1371_state));
 	init_waitqueue_head(&s->dma_adc.wait);
@@ -2820,24 +2820,23 @@
 	       s->vendor, s->device, s->rev);
 	if (!request_region(s->io, ES1371_EXTENT, "es1371")) {
 		printk(KERN_ERR PFX "io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+		res = -EBUSY;
 		goto err_region;
 	}
-	if (pci_enable_device(pcidev))
-		goto err_irq;
-	if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+	if ((res=request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371",s))) {
 		printk(KERN_ERR PFX "irq %u in use\n", s->irq);
 		goto err_irq;
 	}
 	printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n"
 	       KERN_INFO PFX "features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[devindex]);
 	/* register devices */
-	if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+	if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1))<0))
 		goto err_dev1;
-	if ((s->codec.dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+	if ((res=(s->codec.dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0))
 		goto err_dev2;
-	if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+	if ((res=(s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0))
 		goto err_dev3;
-	if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+	if ((res=(s->dev_midi = register_sound_midi(&es1371_midi_fops, -1))<0 ))
 		goto err_dev4;
 #ifdef ES1371_DEBUG
 	/* intialize the debug proc device */
@@ -2916,8 +2915,10 @@
 	/* init the sample rate converter */
 	src_init(s);
 	/* codec init */
-	if (!ac97_probe_codec(&s->codec))
+	if (!ac97_probe_codec(&s->codec)) {
+		res = -ENODEV;
 		goto err_gp;
+	}
 	/* set default values */
 
 	fs = get_fs();
@@ -2964,7 +2965,7 @@
 	release_region(s->io, ES1371_EXTENT);
  err_region:
 	kfree(s);
-	return -1;
+	return res;
 }
 
 static void __devinit es1371_remove(struct pci_dev *dev)
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.4.4/linux/drivers/sound/esssolo1.c	Thu Apr 12 12:16:36 2001
+++ linux/drivers/sound/esssolo1.c	Tue May 22 10:23:16 2001
@@ -77,6 +77,8 @@
  *                       Fix SETTRIGGER non OSS API conformity
  *    10.03.2001         provide abs function, prevent picking up a bogus kernel macro
  *                       for abs. Bug report by Andrew Morton <andrewm@uow.edu.au>
+ *    15.05.2001         pci_enable_device moved, return values in probe cleaned
+ *                       up. Marcus Meissner <mm@caldera.de>
  */
 
 /*****************************************************************************/
@@ -128,17 +130,6 @@
 
 /* --------------------------------------------------------------------- */
 
-/* prevent picking up a bogus abs macro */
-#undef abs
-extern inline int abs(int x)
-{
-	if (x < 0)
-		return -x;
-	return x;
-}
-
-/* --------------------------------------------------------------------- */
-
 #ifndef PCI_VENDOR_ID_ESS
 #define PCI_VENDOR_ID_ESS         0x125d
 #endif
@@ -2288,22 +2279,21 @@
 	return 0;
 }
 
-
-#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
-				 (pci_resource_flags((dev), (num)) & IORESOURCE_IO))
-
 static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct solo1_state *s;
 	struct pm_dev *pmdev;
+	int ret;
 
-	if (!RSRCISIOREGION(pcidev, 0) ||
-	    !RSRCISIOREGION(pcidev, 1) ||
-	    !RSRCISIOREGION(pcidev, 2) ||
-	    !RSRCISIOREGION(pcidev, 3))
-		return -1;
+ 	if ((ret=pci_enable_device(pcidev)))
+		return ret;
+	if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_IO) ||
+	    !(pci_resource_flags(pcidev, 1) & IORESOURCE_IO) ||
+	    !(pci_resource_flags(pcidev, 2) & IORESOURCE_IO) ||
+	    !(pci_resource_flags(pcidev, 3) & IORESOURCE_IO))
+		return -ENODEV;
 	if (pcidev->irq == 0)
-		return -1;
+		return -ENODEV;
 
 	/* Recording requires 24-bit DMA, so attempt to set dma mask
 	 * to 24 bits first, then 32 bits (playback only) if that fails.
@@ -2311,12 +2301,12 @@
 	if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
 	    pci_set_dma_mask(pcidev, 0xffffffff)) {
 		printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
-		return -1;
+		return -ENODEV;
 	}
 
 	if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) {
 		printk(KERN_WARNING "solo1: out of memory\n");
-		return -1;
+		return -ENOMEM;
 	}
 	memset(s, 0, sizeof(struct solo1_state));
 	init_waitqueue_head(&s->dma_adc.wait);
@@ -2336,6 +2326,7 @@
 	s->gameport.io = pci_resource_start(pcidev, 4);
 	s->gameport.size = pci_resource_len(pcidev,4);
 	s->irq = pcidev->irq;
+	ret = -EBUSY;
 	if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
 		printk(KERN_ERR "solo1: io ports in use\n");
 		goto err_region1;
@@ -2358,24 +2349,32 @@
 		printk(KERN_ERR "solo1: gameport io ports in use\n");
 		s->gameport.io = s->gameport.size = 0;
 	}
-	if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
+	if ((ret=request_irq(s->irq,solo1_interrupt,SA_SHIRQ,"ESS Solo1",s))) {
 		printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
 		goto err_irq;
 	}
- 	if (pci_enable_device(pcidev))
-		goto err_irq;
 	printk(KERN_INFO "solo1: joystick port at %#x\n", s->gameport.io+1);
 	/* register devices */
-	if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0)
+	if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) {
+		ret = s->dev_audio;
 		goto err_dev1;
-	if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0)
+	}
+	if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0) {
+		ret = s->dev_mixer;
 		goto err_dev2;
-	if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0)
+	}
+	if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0) {
+		ret = s->dev_midi;
 		goto err_dev3;
-	if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0)
+	}
+	if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0) {
+		ret = s->dev_dmfm;
 		goto err_dev4;
-	if (setup_solo1(s))
+	}
+	if (setup_solo1(s)) {
+		ret = -EIO;
 		goto err;
+	}
 	/* register gameport */
 	gameport_register_port(&s->gameport);
 	/* store it in the driver field */
@@ -2412,7 +2411,7 @@
 	release_region(s->mpubase, MPUBASE_EXTENT);
  err_region1:
 	kfree(s);
-	return -1;
+	return ret;
 }
 
 static void __devinit solo1_remove(struct pci_dev *dev)
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c
--- v2.4.4/linux/drivers/sound/i810_audio.c	Wed Apr 18 11:49:12 2001
+++ linux/drivers/sound/i810_audio.c	Sat May 19 17:43:07 2001
@@ -96,6 +96,9 @@
 #ifndef PCI_DEVICE_ID_INTEL_ICH2
 #define PCI_DEVICE_ID_INTEL_ICH2	0x2445
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH3
+#define PCI_DEVICE_ID_INTEL_ICH3	0x2485
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_440MX
 #define PCI_DEVICE_ID_INTEL_440MX	0x7195
 #endif
@@ -210,13 +213,15 @@
 	ICH82901AB,
 	INTEL440MX,
 	INTELICH2,
+	INTELICH3
 };
 
 static char * card_names[] = {
 	"Intel ICH 82801AA",
 	"Intel ICH 82901AB",
 	"Intel 440MX",
-	"Intel ICH2"
+	"Intel ICH2",
+	"Intel ICH3"
 };
 
 static struct pci_device_id i810_pci_tbl [] __initdata = {
@@ -228,6 +233,8 @@
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH2,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH3,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
 	{0,}
 };
 
@@ -1520,7 +1527,9 @@
 			val = 16384;
 		if (val > 65536)
 			val = 65536;
-		dmabuf->ossfragsize = val/dmabuf->ossmaxfrags;
+		dmabuf->ossmaxfrags = val/dmabuf->ossfragsize;
+		if(dmabuf->ossmaxfrags<4)
+			dmabuf->ossfragsize = val/4;
 		dmabuf->ready = 0;
 #ifdef DEBUG
 		printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val,
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c
--- v2.4.4/linux/drivers/sound/nm256_audio.c	Sat Nov 11 18:33:14 2000
+++ linux/drivers/sound/nm256_audio.c	Tue May  1 16:05:00 2001
@@ -15,6 +15,8 @@
  * Changes:
  * 11-10-2000	Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  *		Added some __init
+ * 19-04-2001	Marcus Meissner <mm@caldera.de>
+ *		Ported to 2.4 PCI API.
  */
 
 #define __NO_VERSION__
@@ -49,8 +51,6 @@
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 
-#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
-
 /* List of cards.  */
 static struct nm256_info *nmcard_list;
 
@@ -1042,6 +1042,9 @@
     struct pm_dev *pmdev;
     int x;
 
+    if (pci_enable_device(pcidev))
+	    return 0;
+
     card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
     if (card == NULL) {
 	printk (KERN_ERR "NM256: out of memory!\n");
@@ -1055,7 +1058,7 @@
 
     /* Init the memory port info.  */
     for (x = 0; x < 2; x++) {
-	card->port[x].physaddr = RSRCADDRESS (pcidev, x);
+	card->port[x].physaddr = pci_resource_start (pcidev, x);
 	card->port[x].ptr = NULL;
 	card->port[x].start_offset = 0;
 	card->port[x].end_offset = 0;
@@ -1201,6 +1204,8 @@
 	}
     }
 
+    pci_set_drvdata(pcidev,card);
+
     /* Insert the card in the list.  */
     card->next_card = nmcard_list;
     nmcard_list = card;
@@ -1251,37 +1256,38 @@
     return 0;
 }
 
-/*
- * 	This loop walks the PCI configuration database and finds where
- *	the sound cards are.
- */
- 
-int __init
-init_nm256(void)
+static int __devinit
+nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid)
 {
-    struct pci_dev *pcidev = NULL;
-    int count = 0;
-
-    if(! pci_present())
-	return -ENODEV;
-
-    while((pcidev = pci_find_device(PCI_VENDOR_ID_NEOMAGIC,
-				    PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO,
-				    pcidev)) != NULL) {
-	count += nm256_install(pcidev, REV_NM256AV, "256AV");
-    }
-
-    while((pcidev = pci_find_device(PCI_VENDOR_ID_NEOMAGIC,
-				    PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO,
-				    pcidev)) != NULL) {
-	count += nm256_install(pcidev, REV_NM256ZX, "256ZX");
+    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO)
+	return nm256_install(pcidev, REV_NM256AV, "256AV");
+    if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO)
+	return nm256_install(pcidev, REV_NM256ZX, "256ZX");
+    return -1; /* should not come here ... */
+}
+
+static void __devinit
+nm256_remove(struct pci_dev *pcidev) {
+    struct nm256_info *xcard = pci_get_drvdata(pcidev);
+    struct nm256_info *card,*next_card = NULL;
+
+    for (card = nmcard_list; card != NULL; card = next_card) {
+	next_card = card->next_card;
+	if (card == xcard) {
+	    stopPlay (card);
+	    stopRecord (card);
+	    if (card->has_irq)
+		free_irq (card->irq, card);
+	    nm256_release_ports (card);
+	    sound_unload_mixerdev (card->mixer_oss_dev);
+	    sound_unload_audiodev (card->dev[0]);
+	    sound_unload_audiodev (card->dev[1]);
+	    kfree (card);
+	    break;
+	}
     }
-
-    if (count == 0)
-	return -ENODEV;
-
-    printk (KERN_INFO "Done installing NM256 audio driver.\n");
-    return 0;
+    if (nmcard_list == card)
+    	nmcard_list = next_card;
 }
 
 /*
@@ -1639,9 +1645,21 @@
     local_qlen:		nm256_audio_local_qlen,
 };
 
-EXPORT_SYMBOL(init_nm256);
+static struct pci_device_id nm256_pci_tbl[] __devinitdata = {
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO,
+	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO,
+	PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+	{0,}
+};
+MODULE_DEVICE_TABLE(pci, nm256_pci_tbl);
 
-static int loaded = 0;
+struct pci_driver nm256_pci_driver = {
+	name:"nm256_audio",
+	id_table:nm256_pci_tbl,
+	probe:nm256_probe,
+	remove:nm256_remove,
+};
 
 MODULE_PARM (usecache, "i");
 MODULE_PARM (buffertop, "i");
@@ -1650,37 +1668,13 @@
 
 static int __init do_init_nm256(void)
 {
-    nmcard_list = NULL;
-    printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1\n");
-
-    if (init_nm256 () == 0) {
-	loaded = 1;
-	return 0;
-    }
-    else
-	return -ENODEV;
+    printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1p\n");
+    return pci_module_init(&nm256_pci_driver);
 }
 
 static void __exit cleanup_nm256 (void)
 {
-    if (loaded) {
-	struct nm256_info *card;
-	struct nm256_info *next_card;
-
-	for (card = nmcard_list; card != NULL; card = next_card) {
-	    stopPlay (card);
-	    stopRecord (card);
-	    if (card->has_irq)
-		free_irq (card->irq, card);
-	    nm256_release_ports (card);
-	    sound_unload_mixerdev (card->mixer_oss_dev);
-	    sound_unload_audiodev (card->dev[0]);
-	    sound_unload_audiodev (card->dev[1]);
-	    next_card = card->next_card;
-	    kfree (card);
-	}
-	nmcard_list = NULL;
-    }
+    pci_unregister_driver(&nm256_pci_driver);
     pm_unregister_all (&handle_pm_event);
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.4.4/linux/drivers/sound/sb_card.c	Sun Feb  4 10:05:29 2001
+++ linux/drivers/sound/sb_card.c	Tue May 22 10:23:16 2001
@@ -338,6 +338,16 @@
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 		0,0,0,0,
 		0,1,1,-1},
+        {"Sound Blaster AWE 32",
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
+		0,0,0,0,
+		0,1,1,-1},
+	{"Sound Blaster AWE 32",
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
+		0,0,0,0,
+		0,1,1,-1},
 	{"Sound Blaster AWE 32",
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
@@ -531,6 +541,9 @@
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 
 	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
 
 	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
--- v2.4.4/linux/drivers/sound/trident.c	Fri Apr  6 10:51:19 2001
+++ linux/drivers/sound/trident.c	Sat May 19 17:43:10 2001
@@ -732,7 +732,7 @@
 	struct dmabuf *dmabuf = &state->dmabuf;
 	struct trident_channel *channel = dmabuf->channel;
 
-	channel->lba = virt_to_bus(dmabuf->rawbuf);
+	channel->lba = dmabuf->dma_handle;
 	channel->delta = compute_rate_play(dmabuf->rate);
 
 	channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
@@ -808,7 +808,7 @@
 		return;
 	}
 
-	channel->lba = virt_to_bus(dmabuf->rawbuf);
+	channel->lba = dmabuf->dma_handle;
 	channel->delta = compute_rate_rec(dmabuf->rate);
 	if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && (channel->num == ALI_SPDIF_IN_CHANNEL)) {
 		rate = ali_get_spdif_in_rate(card);
@@ -1074,14 +1074,21 @@
 				}
 			}
 			else {
-				if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER)
-					dmabuf->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
+				if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) {
+					dmabuf->rawbuf = pci_alloc_consistent(state->card->pci_dev,
+									      PAGE_SIZE << order,
+									      &dmabuf->dma_handle);
+				}
 				if (!dmabuf->rawbuf) {
 					free_pages((unsigned long)state->dmabuf.rawbuf, state->dmabuf.buforder);
 					state->dmabuf.rawbuf = NULL;
 					i-=2;
-					for (; i >= 0; i--)
-						free_pages((unsigned long)state->other_states[i]->dmabuf.rawbuf, state->other_states[i]->dmabuf.buforder);
+					for (; i >= 0; i--) {
+						pci_free_consistent(state->card->pci_dev,
+								    PAGE_SIZE << state->other_states[i]->dmabuf.buforder,
+								    state->other_states[i]->dmabuf.rawbuf,
+								    state->other_states[i]->dmabuf.dma_handle);
+					}
 					unlock_set_fmt(state);
 					return -ENOMEM;
 				}
@@ -1967,9 +1974,9 @@
 
 	case SNDCTL_DSP_GETTRIGGER:
 		val = 0;
-		if (file->f_mode & FMODE_READ && dmabuf->enable)
+		if ((file->f_mode & FMODE_READ) && dmabuf->enable)
 			val |= PCM_ENABLE_INPUT;
-		if (file->f_mode & FMODE_WRITE && dmabuf->enable)
+		if ((file->f_mode & FMODE_WRITE) && dmabuf->enable)
 			val |= PCM_ENABLE_OUTPUT;
 		return put_user(val, (int *)arg);
 
@@ -3157,20 +3164,34 @@
 {
 	struct trident_card *card = (struct trident_card *)data;
 	unsigned long flags;
+	char c;
+
+	if (count<0)
+		return -EINVAL;
+	if (count == 0)
+		return 0;
+	if (get_user(c, buffer))
+		return -EFAULT;
 	
 	spin_lock_irqsave(&card->lock, flags);
-	if (*buffer == '0') {	//default
+	switch (c) {
+	    case '0':
 		ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
 		ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
-	}	
-	else if (*buffer == '1')
+		break;
+	    case '1':
 		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT|ALI_SPDIF_OUT_PCM);
-	else if (*buffer == '2')	//AC3 data
+		break;
+	    case '2':
 		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT|ALI_SPDIF_OUT_NON_PCM);
-	else if (*buffer == '3') 
+		break;
+	    case '3':
 		ali_disable_spdif_in(card);	//default
-	else if (*buffer == '4')
+		break;
+	    case '4':
 		ali_setup_spdif_in(card);
+		break;
+	}
 	spin_unlock_irqrestore(&card->lock, flags);
 
 	return count;
@@ -3307,11 +3328,23 @@
 {
 	unsigned long iobase;
 	struct trident_card *card;
+	dma_addr_t mask;
+	int bits;
 	u8 revision;
 
-	if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) {
+	if (pci_enable_device(pci_dev))
+	    return -ENODEV;
+
+	if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) {
+		mask = 0xffffffff;
+		bits = 32;
+	} else {
+		mask = TRIDENT_DMA_MASK;
+		bits = 30;
+	}
+	if (pci_set_dma_mask(pci_dev, mask)) {
 		printk(KERN_ERR "trident: architecture does not support"
-		       " 30bit PCI busmaster DMA\n");
+		       " %dbit PCI busmaster DMA\n", bits);
 		return -ENODEV;
 	}
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
@@ -3322,9 +3355,6 @@
 		       iobase);
 		return -ENODEV;
 	}
-
-	if (pci_enable_device(pci_dev))
-	    return -ENODEV;
 
 	if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "trident: out of memory\n");
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- v2.4.4/linux/drivers/sound/via82cxxx_audio.c	Fri Mar  2 11:02:15 2001
+++ linux/drivers/sound/via82cxxx_audio.c	Tue May  1 16:05:00 2001
@@ -3020,6 +3020,11 @@
 	if (printed_version++ == 0)
 		printk (KERN_INFO "Via 686a audio driver " VIA_VERSION "\n");
 
+	if (pci_enable_device (pdev)) {
+		rc = -EIO;
+		goto err_out_none;
+	}
+
 	if (!request_region (pci_resource_start (pdev, 0),
 	    		     pci_resource_len (pdev, 0),
 			     VIA_MODULE_NAME)) {
@@ -3028,10 +3033,6 @@
 		goto err_out;
 	}
 
-	if (pci_enable_device (pdev)) {
-		rc = -EIO;
-		goto err_out_none;
-	}
 
 	card = kmalloc (sizeof (*card), GFP_KERNEL);
 	if (!card) {
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.4.4/linux/drivers/sound/wavfront.c	Fri Mar  2 11:12:11 2001
+++ linux/drivers/sound/wavfront.c	Thu May 24 15:14:08 2001
@@ -131,7 +131,7 @@
 #if    OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
 static int (*midi_load_patch) (int devno, int format, const char *addr,
 			       int offs, int count, int pmgr_flag) = NULL;
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */
 
 /* if WF_DEBUG not defined, no run-time debugging messages will
    be available via the debug flag setting. Given the current
@@ -279,7 +279,7 @@
         int fx_mididev;                    /* devno for FX MIDI interface */
 #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
 	int oss_dev;                      /* devno for OSS sequencer synth */
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */
 
 	char fw_version[2];                /* major = [0], minor = [1] */
 	char hw_version[2];                /* major = [0], minor = [1] */
@@ -2139,7 +2139,7 @@
 	bender:		midi_synth_bender,
 	setup_voice:	midi_synth_setup_voice
 };
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */
 
 #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_STATIC_INSTALL
 
@@ -2158,7 +2158,7 @@
     (void) uninstall_wavefront ();
 }
 
-#endif OSS_SUPPORT_STATIC_INSTALL
+#endif /* OSS_SUPPORT_STATIC_INSTALL */
 
 /***********************************************************************/
 /* WaveFront: Linux modular sound kernel installation interface        */
@@ -2674,7 +2674,7 @@
 		    &wavefront_oss_load_patch;
 	}
 
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */
 	
 	/* Turn on Virtual MIDI, but first *always* turn it off,
 	   since otherwise consectutive reloads of the driver will
@@ -2852,14 +2852,14 @@
 	} else {
 		synth_devs[dev.oss_dev] = &wavefront_operations;
 	}
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */
 
 	if (wavefront_init (1) < 0) {
 		printk (KERN_WARNING LOGNAME "initialization failed.\n");
 
 #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
 		sound_unload_synthdev (dev.oss_dev);
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */ 
 
 		return -1;
 	}
@@ -2890,7 +2890,7 @@
 
 #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
 	sound_unload_synthdev (dev.oss_dev);
-#endif OSS_SUPPORT_SEQ
+#endif /* OSS_SUPPORT_SEQ */ 
 	uninstall_wf_mpu ();
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- v2.4.4/linux/drivers/sound/ymfpci.c	Thu Apr 26 22:17:27 2001
+++ linux/drivers/sound/ymfpci.c	Sat May 19 17:47:55 2001
@@ -989,11 +989,6 @@
 
 	status = ymfpci_readl(codec, YDSXGR_STATUS);
 	if (status & 0x80000000) {
-		spin_lock(&codec->reg_lock);
-		ymfpci_writel(codec, YDSXGR_STATUS, 0x80000000);
-		mode = ymfpci_readl(codec, YDSXGR_MODE) | 2;
-		ymfpci_writel(codec, YDSXGR_MODE, mode);
-		spin_unlock(&codec->reg_lock);
 		codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1;
 		spin_lock(&codec->voice_lock);
 		for (nvoice = 0; nvoice < 64; nvoice++) {
@@ -1007,6 +1002,11 @@
 				ymf_cap_interrupt(codec, cap);
 		}
 		spin_unlock(&codec->voice_lock);
+		spin_lock(&codec->reg_lock);
+		ymfpci_writel(codec, YDSXGR_STATUS, 0x80000000);
+		mode = ymfpci_readl(codec, YDSXGR_MODE) | 2;
+		ymfpci_writel(codec, YDSXGR_MODE, mode);
+		spin_unlock(&codec->reg_lock);
 	}
 
 	status = ymfpci_readl(codec, YDSXGR_INTFLAG);
@@ -2059,9 +2059,10 @@
 	}
 
 	if (mpuio >= 0 || oplio >= 0) {
-		v = 0x003e;
+		/* 0x0020: 1 - 10 bits of I/O address decoded, 0 - 16 bits. */
+		v = 0x001e;
 		pci_write_config_word(pcidev, PCIR_LEGCTRL, v);
-	
+
 		switch (pcidev->device) {
 		case PCI_DEVICE_ID_YAMAHA_724:
 		case PCI_DEVICE_ID_YAMAHA_740:
@@ -2106,6 +2107,8 @@
 		pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd | 0x03);
 		pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc);
 	}
+	pci_write_config_word(pci, PCIR_DSXPWRCTRL1, 0);
+	pci_write_config_word(pci, PCIR_DSXPWRCTRL2, 0);
 }
 
 static void ymfpci_enable_dsp(ymfpci_t *codec)
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/ymfpci.h linux/drivers/sound/ymfpci.h
--- v2.4.4/linux/drivers/sound/ymfpci.h	Fri Jan 26 23:31:16 2001
+++ linux/drivers/sound/ymfpci.h	Tue May 15 11:16:26 2001
@@ -135,6 +135,8 @@
 #define PCIR_LEGCTRL			0x40
 #define PCIR_ELEGCTRL			0x42
 #define PCIR_DSXGCTRL			0x48
+#define PCIR_DSXPWRCTRL1		0x4a
+#define PCIR_DSXPWRCTRL2		0x4e
 #define PCIR_OPLADR			0x60
 #define PCIR_SBADR			0x62
 #define PCIR_MPUADR			0x64
diff -u --recursive --new-file v2.4.4/linux/drivers/sound/yss225.h linux/drivers/sound/yss225.h
--- v2.4.4/linux/drivers/sound/yss225.h	Sat Jul 18 14:11:41 1998
+++ linux/drivers/sound/yss225.h	Thu May 24 15:14:08 2001
@@ -20,5 +20,5 @@
 extern unsigned char coefficients3[404];
 
 
-#endif __ys225_h__
+#endif /* __ys225_h__ */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- v2.4.4/linux/drivers/telephony/ixj.c	Fri Mar  2 18:38:39 2001
+++ linux/drivers/telephony/ixj.c	Sat May 19 17:47:55 2001
@@ -4434,7 +4434,8 @@
 	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
-	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)))
+	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)) ||
+	    (unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE) )
 	{
 		kfree(lcp);
 		return -EFAULT;
@@ -4475,7 +4476,7 @@
 {
 	IXJ_FILTER_CADENCE *lcp;
 
-	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
+	lcp = kmalloc(sizeof(IXJ_FILTER_CADENCE), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
 	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE)))
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.4.4/linux/drivers/usb/Config.in	Mon Nov 27 18:10:35 2000
+++ linux/drivers/usb/Config.in	Tue May 22 10:25:36 2001
@@ -32,6 +32,7 @@
    if [ "$CONFIG_USB_STORAGE" != "n" ]; then
       bool '    USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG
       bool '    Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM
+      bool '    Microtech CompactFlash/SmartMedia reader' CONFIG_USB_STORAGE_DPCM
    fi
    dep_tristate '  USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
    dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
@@ -57,6 +58,7 @@
    comment 'USB Multimedia devices'
    dep_tristate '  USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
+   dep_tristate '  USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.4.4/linux/drivers/usb/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/drivers/usb/Makefile	Tue May 22 10:25:36 2001
@@ -17,6 +17,21 @@
 list-multi		:= usbcore.o
 usbcore-objs		:= usb.o usb-debug.o hub.o
 
+ifneq ($(CONFIG_USB_PWC),n)
+	# By default we use the C colour conversion functions unless we
+	# detect an Intel CPU, for which there is assembly available
+	ccvt-objs		:= ccvt_c.o vcvt_c.o
+	ifeq ($(CONFIG_X86),y)
+		ccvt-objs		:= ccvt_i386.o vcvt_i386.o
+	endif
+
+	export-objs		+= pwc-uncompress.o
+	list-multi		+= pwc.o
+endif
+
+pwc-objs		:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o $(ccvt-objs)
+
+
 # Optional parts of multipart objects.
 
 ifeq ($(CONFIG_USB_DEVICEFS),y)
@@ -47,6 +62,7 @@
 obj-$(CONFIG_USB_PRINTER)	+= printer.o
 obj-$(CONFIG_USB_AUDIO)		+= audio.o
 obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o
+obj-$(CONFIG_USB_PWC)		+= pwc.o
 obj-$(CONFIG_USB_DC2XX)		+= dc2xx.o
 obj-$(CONFIG_USB_MDC800)	+= mdc800.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
@@ -79,4 +95,7 @@
 
 usbcore.o: $(usbcore-objs)
 	$(LD) -r -o $@ $(usbcore-objs)
+
+pwc.o:		$(pwc-objs)
+	$(LD) -r -o $@ $(pwc-objs)
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.4.4/linux/drivers/usb/acm.c	Fri Feb 16 16:06:17 2001
+++ linux/drivers/usb/acm.c	Mon May 21 15:02:06 2001
@@ -55,6 +55,13 @@
 #include <linux/usb.h>
 
 /*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.18"
+#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
+#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
+
+/*
  * CMSPAR, some architectures can't have space and mark parity.
  */
 
@@ -233,8 +240,14 @@
 		dbg("nonzero read bulk status received: %d", urb->status);
 
 	if (!urb->status & !acm->throttle)  {
-		for (i = 0; i < urb->actual_length && !acm->throttle; i++)
+		for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
+			/* if we insert more than TTY_FLIPBUF_SIZE characters,
+			 * we drop them. */
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+			}
 			tty_insert_flip_char(tty, data[i], 0);
+		}
 		tty_flip_buffer_push(tty);
 	}
 
@@ -304,6 +317,10 @@
 
 	acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
 
+	/* force low_latency on so that our tty_push actually forces the data through, 
+	   otherwise it is scheduled, and with high data rates data can get lost. */
+	tty->low_latency = 1;
+
 	return 0;
 }
 
@@ -692,6 +709,9 @@
 		return -1;
 	}
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -704,5 +724,6 @@
 module_init(acm_init);
 module_exit(acm_exit);
 
-MODULE_AUTHOR("Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik");
-MODULE_DESCRIPTION("USB Abstract Control Model driver for USB modems and ISDN adapters");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.4.4/linux/drivers/usb/audio.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/audio.c	Mon May 21 15:02:06 2001
@@ -92,6 +92,8 @@
  * 2000-11-26:  Thomas Sailer
  *              Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for
  *              its 8 bit modes, but expects signed data (and should therefore have used PCM).
+ * 2001-04-08:  gb
+ *              Identify version on module load.
  *
  */
 
@@ -190,6 +192,13 @@
 
 #include "audio.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)"
+#define DRIVER_DESC "USB Audio Class driver"
+
 #define AUDIO_DEBUG 1
 
 #define SND_DEV_DSP16   5 
@@ -3746,6 +3755,8 @@
 static int __init usb_audio_init(void)
 {
 	usb_register(&usb_audio_driver);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -3758,6 +3769,6 @@
 module_init(usb_audio_init);
 module_exit(usb_audio_cleanup);
 
-MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)");
-MODULE_DESCRIPTION("USB Audio Class driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c
--- v2.4.4/linux/drivers/usb/bluetooth.c	Mon Mar 19 17:21:54 2001
+++ linux/drivers/usb/bluetooth.c	Mon May 21 15:02:06 2001
@@ -5,6 +5,9 @@
  * Copyright (c) 2000 Mark Douglas Corner	<mcorner@umich.edu>
  *
  * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
+ * 
+ * (08/04/2001) gb
+ *	Identify version on module load.
  *
  * (2001/03/10) Version 0.8 gkh
  *	Fixed problem with not unlinking interrupt urb on device close
@@ -91,9 +94,12 @@
 #define DEBUG
 #include <linux/usb.h>
 
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, Mark Douglas Corner");
-MODULE_DESCRIPTION("USB Bluetooth driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.8"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
+#define DRIVER_DESC "USB Bluetooth driver"
 
 /* define this if you have hardware that is not good */
 /*#define	BTBUGGYHARDWARE */
@@ -1280,6 +1286,9 @@
 		return -1;
 	}
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -1294,4 +1303,7 @@
 module_init(usb_bluetooth_init);
 module_exit(usb_bluetooth_exit);
 
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/ccvt.h linux/drivers/usb/ccvt.h
--- v2.4.4/linux/drivers/usb/ccvt.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ccvt.h	Tue May 22 10:25:36 2001
@@ -0,0 +1,87 @@
+/* 
+   (C) 2000 Nemosoft Unv.    nemosoft@smcc.demon.nl
+   
+   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
+
+*/
+
+#ifndef CCVT_H
+#define CCVT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Colour ConVerT: going from one colour space to another
+
+   Format descriptions:
+   420i = "4:2:0 interlaced"
+           YYYY UU YYYY UU   even lines
+           YYYY VV YYYY VV   odd lines
+           U/V data is subsampled by 2 both in horizontal 
+           and vertical directions, and intermixed with the Y values.
+   
+   420p = "4:2:0 planar"
+           YYYYYYYY      N lines
+           UUUU          N/2 lines
+           VVVV          N/2 lines
+           U/V is again subsampled, but all the Ys, Us and Vs are placed 
+           together in separate buffers. The buffers may be placed in
+           one piece of contiguous memory though, with Y buffer first,
+           followed by U, followed by V.
+
+   yuyv = "4:2:2 interlaced"
+           YUYV YUYV YUYV ...   N lines
+           The U/V data is subsampled by 2 in horizontal direction only.
+
+   bgr24 = 3 bytes per pixel, in the order Blue Green Red (whoever came up
+           with that idea...)
+   rgb24 = 3 bytes per pixel, in the order Red Green Blue (which is sensible)
+   rgb32 = 4 bytes per pixel, in the order Red Green Blue Alpha, with 
+           Alpha really being a filler byte (0)
+   bgr32 = last but not least, 4 bytes per pixel, in the order Blue Green Red
+           Alpha, Alpha again a filler byte (0)
+ */
+
+/* Functions in ccvt_i386.S/ccvt_c.c */
+/* 4:2:0 YUV interlaced to RGB/BGR */
+void ccvt_420i_bgr24(int width, int height, void *src, void *dst);
+void ccvt_420i_rgb24(int width, int height, void *src, void *dst);
+void ccvt_420i_bgr32(int width, int height, void *src, void *dst);
+void ccvt_420i_rgb32(int width, int height, void *src, void *dst);
+
+/* 4:2:2 YUYV interlaced to RGB/BGR */
+void ccvt_yuyv_rgb32(int width, int height, void *src, void *dst);
+void ccvt_yuyv_bgr32(int width, int height, void *src, void *dst);
+
+/* 4:2:0 YUV planar to RGB/BGR     */
+void ccvt_420p_rgb32(int width, int height, void *srcy, void *srcu, void *srcv, void *dst);
+void ccvt_420p_bgr32(int width, int height, void *srcy, void *srcu, void *srcv, void *dst);
+
+/* RGB/BGR to 4:2:0 YUV interlaced */
+
+/* RGB/BGR to 4:2:0 YUV planar     */
+void ccvt_rgb24_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv);
+void ccvt_bgr24_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv);
+
+/* Go from 420i to other yuv formats */
+void ccvt_420i_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv);
+void ccvt_420i_yuyv(int width, int height, void *src, void *dst);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/ccvt_c.c linux/drivers/usb/ccvt_c.c
--- v2.4.4/linux/drivers/usb/ccvt_c.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ccvt_c.c	Tue May 22 10:25:36 2001
@@ -0,0 +1,59 @@
+/*
+   Colour conversion routines (RGB <-> YUV) in plain C
+   (C) 2000-2001 Nemosoft Unv.    nemosoft@smcc.demon.nl
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include "ccvt.h"
+#include "vcvt.h"
+
+/* We use the viewport routines, with a viewport width that is exactly
+   the same as the image width. The overhead for computing the view/image
+   offsets is very small anyway.
+   
+   The assembly routines are still different, since they are quite optimized.
+ */
+void ccvt_420i_rgb24(int width, int height, void *src, void *dst)
+{
+	vcvt_420i_rgb24(width, height, width, src, dst);
+}
+
+void ccvt_420i_bgr24(int width, int height, void *src, void *dst)
+{
+	vcvt_420i_bgr24(width, height, width, src, dst);
+}
+
+void ccvt_420i_rgb32(int width, int height, void *src, void *dst)
+{
+	vcvt_420i_rgb32(width, height, width, src, dst);
+}
+
+void ccvt_420i_bgr32(int width, int height, void *src, void *dst)
+{
+	vcvt_420i_bgr32(width, height, width, src, dst);
+}
+
+
+void ccvt_420i_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv)
+{
+	vcvt_420i_420p(width, height, width, src, dsty, dstu, dstv);
+}
+
+void ccvt_420i_yuyv(int width, int height, void *src, void *dst)
+{
+	vcvt_420i_yuyv(width, height, width, src, dst);
+}
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/ccvt_i386.S linux/drivers/usb/ccvt_i386.S
--- v2.4.4/linux/drivers/usb/ccvt_i386.S	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ccvt_i386.S	Tue May 22 10:25:36 2001
@@ -0,0 +1,1144 @@
+/*
+Colour conversion routines (RGB <-> YUV) in x86 assembly
+ 
+(C) 2000 Nemosoft Unv.    nemosoft@smcc.demon.nl
+   
+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.   
+
+*/
+
+
+/* The ccvt_* functions always start with width and height, so these
+   parameters are in 8(%ebp) and 12 (%ebp). The other parameters can be
+   2 to 4 pointers, and one of these combinations:
+   *src, *dst
+   *srcy, *srcu, *srv, *dst
+   *src, *dsty, *dstu, *dstv
+ */   
+
+#define __ASSEMBLY__
+#include <linux/linkage.h>
+
+#define Width   8(%ebp)
+#define Height 12(%ebp)
+
+/* 2 parameters, 1 in, 1 out */
+#define Src2 16(%ebp)
+#define Dst2 20(%ebp)
+
+/* 4 parameters, 3 in, 1 out */
+#define SrcY 16(%ebp)
+#define SrcU 20(%ebp)
+#define SrcV 24(%ebp)
+#define Dst4 28(%ebp)
+
+/* 4 parameters, 1 in, 3 out */
+#define Src4 16(%ebp)
+#define DstY 20(%ebp)
+#define DstU 24(%ebp)
+#define DstV 28(%ebp)
+
+/* This buffer space used to be staticly allocted, but this is going to
+   give problems with multiple cams (though I have yet to see it).
+   Therefor, we reserve at least 64 + 8 = 72 bytes on the stack with 
+   `enter'.
+ */
+
+#define PixelBuffer -64(%ebp)
+#define Uptr        -68(%ebp)
+#define Vptr        -72(%ebp)
+
+	.text
+
+/* This function will load the src and destination pointers, including
+   Uptr/Vptr when necessary, and test the width/height parameters.
+   - %esi will be set to Src or SrcY
+   - %edi will be set to Dst or DstY
+   the carry flag will be set if any of these tests fail. 
+   It assumes %ebp has been set.
+ */
+/* 2 parameters, src & dst */
+test_param_2:
+	mov Src2, %esi
+	mov Dst2, %edi
+	
+	cmp $0, %esi		# NULL pointers?
+	je param_fail
+	cmp $0, %edi
+	je param_fail
+
+	jmp test_width_height
+
+/* 3 inputs, 1 output */
+test_param_31:
+	mov Dst4, %edi		# NULL pointers
+	cmp $0, %edi
+	je param_fail
+	
+	mov SrcV, %esi
+	cmp $0, %esi
+	je param_fail
+	mov %esi, Vptr
+
+	mov SrcU, %esi
+	cmp $0, %esi
+	je param_fail
+	mov %esi, Uptr
+	
+	mov SrcY, %esi
+	cmp $0, %esi
+	je param_fail
+	
+	jmp test_width_height
+
+/* 1 input, 3 output */	
+test_param_13:
+	mov Src4, %esi		# NULL pointers
+	cmp $0, %esi
+	je param_fail
+	
+	mov DstV, %edi
+	cmp $0, %edi
+	je param_fail
+	mov %edi, Vptr
+	
+	mov DstU, %edi
+	cmp $0, %edi
+	je param_fail
+	mov %edi, Uptr
+	
+	mov DstY, %edi
+	cmp $0, %edi
+	je param_fail
+	
+	jmp test_width_height
+	
+	nop
+
+test_width_height:
+	cmpl $0, Width
+	jbe param_fail
+	testl $3, Width		# multiple of 4?
+	jnz param_fail		# Nope...
+
+	cmp $0, Height		# check illegal height
+	jbe param_fail
+	testl $1, Height	# Odd no. of lines?
+	jnz param_fail		# Aye
+
+	/* fall through */
+
+/* exit points */
+param_ok:
+	clc			# Success: clear carry
+	ret
+
+param_fail:
+	stc			# Fail: set carry
+	ret
+
+
+
+# This will fill PixelBuffer with 4 grey scale pixels (Y)
+# In: 		%eax = Value (Y3Y2Y1Y0)
+# Out:
+# Modifies:	%ecx (-4)
+# Destroys: 	%edx
+expand_4_y:
+	mov %eax, %edx		# Keep in edx (we need eax)
+	lea PixelBuffer, %edi	
+	
+0:	# This code is executed 4 times
+	movzbl %dl, %eax	# move, zero extending byte-to-long
+	shl $8, %eax		# 8 digit precision
+	
+	stosl			# Expand into PixelBuffer
+	stosl
+	stosl
+	add $4, %edi		# Skip alpha
+
+	shr $8, %edx		# next Y
+
+	dec %ecx
+	test $3, %ecx
+	jnz 0b
+
+	ret			# from expand_4_y
+	
+# This will add the color factors to the (grey) values in PixelBuffer
+# In:		%ebx (U1U0V1V0)
+# Out:
+# Modifies:
+# Destroys:	%edi, %ebx, %eax, %edx
+expand_4_uv:
+	lea PixelBuffer, %edi	# reset pointer
+
+	# V0
+	sub $128, %bl
+	movsbl %bl, %eax
+	mov $359, %edx		# Vr
+	mul %edx
+	add %eax, 0x00(%edi)
+	add %eax, 0x10(%edi)
+	
+	movsbl %bl, %eax
+	mov $183, %edx		# Vg
+	mul %edx
+	sub %eax, 0x04(%edi)
+	sub %eax, 0x14(%edi)
+	
+	# V1
+	sub $128, %bh
+	movsbl %bh, %eax
+	mov $359, %edx		# Vr
+	mul %edx
+	add %eax, 0x20(%edi)
+	add %eax, 0x30(%edi)
+	
+	movsbl %bh, %eax
+	mov $183, %edx		# Vg
+	mul %edx
+	sub %eax, 0x24(%edi)
+	sub %eax, 0x34(%edi)
+	
+	# U0
+	bswap %ebx		# Get U values in lower half
+	sub $128, %bh
+	movsbl %bh, %eax
+	mov $88, %edx		# Ug
+	mul %edx
+	sub %eax, 0x04(%edi)
+	sub %eax, 0x14(%edi)
+
+	movsbl %bh, %eax
+	mov $454, %edx		# Ub
+	mul %edx
+	add %eax, 0x08(%edi)
+	add %eax, 0x18(%edi)
+	
+	# U1
+	sub $128, %bl
+	movsbl %bl, %eax
+	mov $88, %edx		# Ug
+	mul %edx
+	sub %eax, 0x24(%edi)
+	sub %eax, 0x34(%edi)
+	
+	movsbl %bl, %eax
+	mov $454, %edx		# Ub
+	mul %edx
+	add %eax, 0x28(%edi)
+	add %eax, 0x38(%edi)
+	ret			# expand_4_uv
+
+
+/* This function expands 4 420i pixels into PixelBuffer */
+do_four_yuvi:
+	push %edi
+
+	lodsl			# 4 bytes at a time
+	
+	call expand_4_y
+	
+	# now do UV values. on even lines, Y is followed by U values; on 
+	# odd lines V values follow. The U and V values are always pushed
+	# on the stack in this order:
+	# U V
+	
+	# First, calculate offset per line (1.5 * width)
+	mov Width, %ebx	# width
+	shl %ebx		# 2 *
+	add Width, %ebx	# 3 * 
+	shr %ebx		# 1.5 *
+
+	# even or odd lines	
+	testl $1, Height
+	jz 2f
+
+	# odd line; we are at V data, but do U data first
+	neg %ebx		# make ebx offset negative
+	mov (%esi,%ebx),%ax	# U
+	push %ax
+	lodsw			# V
+	push %ax
+	jmp 3f	
+	
+2:	# even line
+	lodsw			# U
+	push %ax
+	sub $2, %ebx
+	mov (%esi,%ebx), %ax	# V
+	push %ax
+
+3:	# Okay, so we now have the U and V values... expand into PixelBuffer
+
+	pop %ebx
+	call expand_4_uv
+
+	pop %edi
+	ret			# from do_four_yuvi
+
+
+# Do four pixels, in planar format
+do_four_yuvp:
+	push %edi
+
+	# The first part is the same as for interlaced (4 bytes Y)
+	lodsl			# 4 bytes at a time
+	call expand_4_y
+	
+	# now gather U and V values... 
+	mov Uptr, %ebx		# Use Uptr/Vptr
+	mov (%ebx), %ax
+	push %ax
+	add $2, %ebx
+	mov %ebx, Uptr
+
+	mov Vptr, %ebx
+	mov (%ebx), %ax
+	push %ax
+	add $2, %ebx
+	mov %ebx, Vptr
+	
+	pop %ebx
+	call expand_4_uv
+	
+	pop %edi
+	ret
+
+
+# Do four pixels, in yuyv interlaced format
+do_four_yuyv:
+	push %edi
+
+	lodsl			# v0y1u0y0
+	mov %eax, %ebx
+	bswap %ebx		# y0u0y1v0
+	mov %bh, %ah		# v0y1y1y0
+	and $0x00ff00ff, %ebx	# __u0__v0
+	push %ax		# y1y0
+
+	lodsl			# v1y3u1y2	# mix register instructions
+	mov %eax, %edx				# so CPU pipeline doesnt stall
+	rol $16, %eax		# u1y2v1y3	
+	mov %dl, %dh		# v1y3y2y2
+	and $0xff00ff00, %eax	# u1__v1__
+	mov $0, %dl		# v1y3y2__
+	or %eax, %ebx		# u1u0v1v0
+	shl $8, %edx		# y3y2____
+	pop %dx			# y3y2y1y0
+	mov %edx, %eax
+	call expand_4_y
+	call expand_4_uv
+	
+	pop %edi
+	ret
+
+limit_pixels:
+	# Limit all values in PixelBuffer
+	push %esi
+	push %edi
+	push %ecx
+	lea PixelBuffer, %esi
+	mov %esi, %edi
+	mov $16, %ecx
+0:	lodsl
+	cmp $0, %eax		# this would have been a perfect spot for CMOVxx instructions...
+	jl 2f			#  except they only work on Pentium Pro processors,
+	cmp $0xff00, %eax	#  and not even all of them
+	jg 3f
+	add $4, %edi		# no use for stosl here
+	loop 0b
+	jmp 9f
+2:	mov $0, %eax
+	stosl
+	loop 0b
+	jmp 9f
+3:	mov $0xff00, %eax
+	stosl
+	loop 0b
+	jmp 9f
+
+9:	pop %ecx
+	pop %edi
+	pop %esi
+	ret			# from limit_pixels
+
+/* Copy RGB values from PixelBuffer into destination buffer, 4 bytes
+   with alpha 
+ */
+
+/* Push 3 pixel (12 bytes), in correct order */
+push_rgb24:
+	push %ecx
+	push %esi
+	lea PixelBuffer, %esi
+	mov $4, %ecx
+0:	lodsl
+	shr $8, %eax
+	mov %al, (%edi)  	# Red
+	lodsl
+	shr $8, %eax
+	mov %al, 1(%edi)	# Green
+	lodsl
+	shr $8, %eax
+	mov %al, 2(%edi)	# Blue
+	add $3, %edi
+	lodsl			# dummy
+	loop 0b
+	pop %esi
+	pop %ecx
+	ret
+
+/* Push 3 pixels (12 bytes), in wrong order */
+push_bgr24:
+	push %ecx
+	push %esi
+	lea PixelBuffer, %esi
+	mov $4, %ecx
+0:	lodsl
+	shr $8, %eax
+	mov %al, 2(%edi)	# Red
+	lodsl
+	shr $8, %eax
+	mov %al, 1(%edi)	# Green
+	lodsl
+	shr $8, %eax
+	mov %al, (%edi)		# Blue
+	add $3, %edi
+	lodsl			# dummy
+	loop 0b
+	pop %esi
+	pop %ecx
+	ret
+
+/* The simplest format: push 4 bytes, RGBa */
+push_rgb32:
+	push %ecx
+	push %esi
+	mov $16, %ecx
+	lea PixelBuffer, %esi
+0:	lodsl			# red
+	shr $8, %eax		# 8 bit precision
+	stosb
+	loop 0b
+	pop %esi
+	pop %ecx
+	ret
+
+
+/* Gosh. Would you believe it. They even made this format... (Qt 2.*) */
+push_bgr32:
+	# copy all 4 values to output buffer
+	push %ecx
+	push %esi
+	mov $4, %ecx
+	lea PixelBuffer, %esi
+0:	lodsl			# red
+	shr $8, %eax		# 8 bit precision
+	mov %al, 2(%edi)
+	lodsl			# green
+	shr $8, %eax
+	mov %al, 1(%edi)
+	lodsl			# blue
+	shr $8, %eax
+	mov %al, (%edi)
+	add $4, %edi
+	lodsl			# dummy
+	loop 0b	
+	pop %esi
+	pop %ecx
+	ret
+
+/*************************************/
+
+/* Functions to go from YUV interlaced formats to RGB */
+
+/* Go from interlaced to RGB, red first */
+
+ENTRY(ccvt_420i_rgb24)
+	enter $72, $0		# no extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+	
+0:	mov Width, %ecx		# width
+1:	call do_four_yuvi
+	call limit_pixels
+	call push_rgb24
+			
+	cmp $0, %ecx
+	jnz 1b			# end of line?
+	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+/* Go from interlaced to BGR, blue first */
+
+ENTRY(ccvt_420i_bgr24)
+	enter $72, $0		# no extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+	
+0:	mov Width, %ecx	# width
+1:	call do_four_yuvi
+	call limit_pixels
+	call push_bgr24
+			
+	cmp $0, %ecx
+	jnz 1b			# end of line?
+	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+/* From interlaced to RGBa */
+
+ENTRY(ccvt_420i_rgb32)
+	enter $72, $0		# no extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+
+0:	mov Width, %ecx		# width
+1:	call do_four_yuvi
+	call limit_pixels
+	call push_rgb32
+		
+	cmp $0, %ecx		# end of line?
+	jnz 1b
+	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+/* Guess what? Go from interlaced to BGRa */
+
+ENTRY(ccvt_420i_bgr32)
+	enter $72, $0		# no extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+
+0:	mov Width, %ecx		# width
+1:	call do_four_yuvi
+	call limit_pixels
+	call push_bgr32
+		
+	cmp $0, %ecx		# end of line?
+	jnz 1b
+	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+
+
+/* From YUYV to RGBa */
+
+ENTRY(ccvt_yuyv_rgb32)
+	enter $72, $0		# no extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+	
+0:	mov Width, %ecx		# width
+1:	call do_four_yuyv
+	call limit_pixels
+	call push_rgb32
+		
+	cmp $0, %ecx		# end of line?
+	jnz 1b
+
+8:	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+/* From YUYV to BGRa */
+ENTRY(ccvt_yuyv_bgr32)
+	enter $72, $0		# no extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+	
+	# YUYV -> RGBa RGBa
+
+0:	mov Width, %ecx		# width
+1:	call do_four_yuyv
+	call limit_pixels
+	call push_bgr32
+		
+	cmp $0, %ecx		# end of line?
+	jnz 1b
+
+8:	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+
+
+/* Planar to RGBa */
+
+ENTRY(ccvt_420p_rgb32)
+	enter $72, $0
+	push %ebx
+	push %esi
+	push %edi
+	
+	call test_param_31
+	jc 9f
+
+	mov Width, %eax		# width
+	mull Height		# * height
+	mov SrcU, %eax		# Copy U/V pointers
+	mov %eax, Uptr
+	mov SrcV, %eax
+	mov %eax, Vptr
+
+0:	mov Width, %ecx		# width
+1:	call do_four_yuvp
+	call limit_pixels
+	call push_rgb32	
+		
+	cmp $0, %ecx		# end of line?
+	jnz 1b
+
+	testl $1, Height	# odd/even line
+	jnz 8f
+	
+	mov Width, %eax		# Even: rewind U/V pointers
+	shr %eax
+	sub %eax, Uptr
+	sub %eax, Vptr
+
+8:	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+/* Okay... eventually, you end up with a very complete set of conversion
+   routines. I just wished things were a bit simpler. */
+
+ENTRY(ccvt_420p_bgr32)
+	enter $72, $0
+	push %ebx
+	push %esi
+	push %edi
+	
+	call test_param_31
+	jc 9f
+	
+	mov Width, %eax		# width
+	mull Height		# * height
+	mov SrcU, %eax		# Copy U/V pointers
+	mov %eax, Uptr
+	mov SrcV, %eax
+	mov %eax, Vptr
+
+0:	mov Width, %ecx		# width
+1:	call do_four_yuvp
+	call limit_pixels
+	call push_bgr32
+		
+	cmp $0, %ecx		# end of line?
+	jnz 1b
+
+	testl $1, Height	# odd/even line
+	jnz 8f
+	
+	mov Width, %eax		# Even: rewind U/V pointers
+	shr %eax
+	sub %eax, Uptr
+	sub %eax, Vptr
+
+8:	decl Height		# yes; decrement line counter
+	jnz 0b
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+
+
+/* Go from RGB (red first) to 4:2:0 planar.
+ * Note: this requires decimation of the U/V space by 2 in both directions 
+ * Also, a matrix multiply would be QUITE convenient...
+
+   This is the matrix:
+     (Y )   ( 77  150   29)   (R)
+     (Cb) = (-43  -85  128) * (G)
+     (Cr)   (128 -107  -21)   (B)
+ */
+
+ENTRY(ccvt_rgb24_420p)
+	enter $96, $0		# 24 bytes extra stack, no stackframes
+	push %ebx		#  -76: line width in bytes
+	push %esi		#  -80: height (copy)
+	push %edi		#  -84: width (copy)
+				#  -88: red factor
+				#  -92: green factor
+				#  -96: blue factor
+	call test_param_13
+	jc 9f
+
+	mov Width, %eax
+	shl %eax
+	add Width, %eax		# 3 * width = line increment
+	mov %eax, -76(%ebp)
+
+	mov Height, %eax
+	mov %eax, -80(%ebp)	# copy height into stackframe
+	
+	/*
+	  This is a bit complicated... since U/V decimation is taking 
+	  place both in horizontal and vertical direction, we have to
+	  process 2 lines in parallel. Also, 2 adjacent pixels are
+	  considered. We average the U/V values over these 4 pixels
+	  (of course, we could have just taken the U/V value of the first
+	  pixel and be done with it, but that's not how we do things around
+	  here)
+	 */
+	
+	# 1st pass: Y values. Set factors	
+	movl $77 , -88(%ebp)	# 0.299
+	movl $150, -92(%ebp)	# 0.587
+	movl $29 , -96(%ebp)	# 0.114
+
+0:	mov Width, %ecx		# width
+1:	xor %ebx, %ebx		# 0
+	call rgb_multiply
+	shr $8, %ebx		# divide by 256 (no need for limitor, since 77 + 150 + 29 = 256)
+	mov %bl, %al
+	stosb			# store it into Y buffer
+	
+	dec %ecx		# end of line?
+	jnz 1b
+	decl -80(%ebp)		# end of image?
+	jnz 0b
+
+	# Okay, now the U/V pointers... 
+	# The following code is passed twice, with different factors
+	# Note that the %esi pointer jumps around quite a bit
+
+	# factors for U
+	movl $-43, -88(%ebp)	# -0.1687
+	movl $-85, -92(%ebp)	# -0.3313
+	movl $128, -96(%ebp)	# 0.5
+	mov DstU, %edi		# Set %edi register now
+		
+7:	mov Src4, %esi		# Rewind source pointer
+
+	mov Height, %eax	# height
+	shr %eax		#  / 2
+	mov %eax, -80(%ebp)	#   copy
+
+2:	mov Width, %eax		# width
+	shr %eax		#  / 2
+	mov %eax, -84(%ebp)	#   copy
+
+3:	xor %ebx, %ebx		# 0
+	mov $4, %ecx		# average over 4 pixels
+
+4:	call rgb_multiply
+
+	dec %ecx
+	jz 5f			# done?
+	cmp $2, %ecx		# 3rd pixel.. move %esi to next line, with offset
+	jne 4b
+	sub $6, %esi		# backup to where we started
+	add -76(%ebp), %esi	# add line increment
+	jmp 4b
+
+5:	# okay, 4 pixels done... 
+	sub -76(%ebp), %esi	# Get %esi back to its proper place
+
+	add $0x20000, %ebx	# add 0.5 factor
+	shr $10, %ebx		# Divide by 4 * 256
+	mov %bl, %al
+	stosb			# store it!
+
+	decl -84(%ebp)		# end of line?
+	jnz 3b
+	add -76(%ebp), %esi	# %esi to next line (actually, 2 lines further)
+	decl -80(%ebp)		# end of image?
+	jnz 2b
+
+	# check if 3rd pass has been done
+	cmpl $128, -88(%ebp)
+	je 9f			# Done!
+	# Set factors for V pass
+	movl $128 , -88(%ebp)	# 0.5
+	movl $-107, -92(%ebp)	# -0.4187
+	movl $-21 , -96(%ebp)	# -0.0813
+	mov DstV, %edi		# %edi to V buffer
+	jmp 7b			# "Do it to me one more time..."
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+
+
+ENTRY(ccvt_bgr24_420p)
+	enter $96, $0		# 24 bytes extra stack, no stackframes
+	push %ebx		#   -4: line width in bytes
+	push %esi		#   -8: height (copy)
+	push %edi		#  -12: width (copy)
+				#  -16: red factor
+				#  -20: green factor
+				#  -24: blue factor
+	call test_param_13
+	jc 9f
+
+	/* No surprise, this code looks just like rgb24_420p, but with swapped factors */
+	 
+	mov Width, %eax
+	shl %eax
+	add Width, %eax		# 3 * width = line increment
+	mov %eax, -76(%ebp)
+
+	mov Height, %eax
+	mov %eax, -80(%ebp)	# copy height into stackframe
+	
+	# 1st pass: Y values. Set factors	
+	movl $29 , -88(%ebp)	# 0.114
+	movl $150, -92(%ebp)	# 0.587
+	movl $77 , -96(%ebp)	# 0.299
+
+0:	mov Width, %ecx		# width
+1:	xor %ebx, %ebx		# 0
+	call rgb_multiply
+	shr $8, %ebx		# divide by 256 (no need for limitor, since 77 + 150 + 29 = 256)
+	mov %bl, %al
+	stosb			# store it into Y buffer
+	
+	dec %ecx		# end of line?
+	jnz 1b
+	decl -80(%ebp)		# end of image?
+	jnz 0b
+
+	# Okay, now the U/V pointers... 
+	# The following code is passed twice, with different factors
+	# Note that the %esi pointer jumps around quite a bit
+
+	# factors for U
+	movl $123, -88(%ebp)	#  0.5
+	movl $-85, -92(%ebp)	# -0.3313
+	movl $-43, -96(%ebp)	# -0.1687
+	mov DstU, %edi		# Set %edi register now
+		
+7:	mov Src4, %esi		# Rewind source pointer
+
+	mov Height, %eax	# height
+	shr %eax		#  / 2
+	mov %eax, -80(%ebp)	#   copy
+
+2:	mov Width, %eax		# width
+	shr %eax		#  / 2
+	mov %eax, -84(%ebp)	#   copy
+
+3:	xor %ebx, %ebx		# 0
+	mov $4, %ecx		# average over 4 pixels
+
+4:	call rgb_multiply
+
+	dec %ecx
+	jz 5f			# done?
+	cmp $2, %ecx		# 3rd pixel.. move %esi to next line, with offset
+	jne 4b
+	sub $6, %esi		# backup to where we started
+	add -76(%ebp), %esi	# add line increment
+	jmp 4b
+
+5:	# okay, 4 pixels done... 
+	sub -76(%ebp), %esi	# Get %esi back to its proper place
+
+	add $0x20000, %ebx	# add 0.5 factor
+	shr $10, %ebx		# Divide by 4 * 256
+	mov %bl, %al
+	stosb			# store it!
+
+	decl -84(%ebp)		# end of line?
+	jnz 3b
+	add -76(%ebp), %esi	# %esi to next line (actually, 2 lines further)
+	decl -80(%ebp)		# end of image?
+	jnz 2b
+
+	# check if 3rd pass has been done
+	cmpl $-21, -88(%ebp)
+	je 9f			# Done!
+	# Set factors for V pass
+	movl $-21 , -88(%ebp)	# -0.0813
+	movl $-107, -92(%ebp)	# -0.4187
+	movl $128 , -96(%ebp)	#  0.5
+	mov DstV, %edi		# %edi to V buffer
+	jmp 7b			# "Do it to me one more time..."
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+/* RGB-to-YUV helper functions */
+
+rgb_multiply:
+	# do one RGB vector multiplication; its assumed the RGB factors
+	# are set on the stack. The data is accumulated in ebx.
+	lodsb			# red byte
+	and $0xff, %eax
+	mov -88(%ebp), %edx	# red factor
+	mul %edx
+	add %eax, %ebx
+	lodsb			# green byte
+	and $0xff, %eax
+	mov -92(%ebp), %edx	# green factor
+	mul %edx
+	add %eax, %ebx
+	lodsb			# blue byte
+	and $0xff, %eax
+	mov -96(%ebp), %edx	# blue factor
+	mul %edx
+	add %eax, %ebx		# ebx now contains sum
+	ret
+
+
+
+/**************************************************************************/
+
+
+/* Go from 'interlaced' (YYYY UU/VV) format to planar */
+
+ENTRY(ccvt_420i_420p)
+	enter $76, $0		# 4 bytes extra space, no stackframes
+	push %ebx		# -4: width / 4
+	push %esi
+	push %edi
+
+	call test_param_13
+	jc 9f
+
+	# Okay, this is fairly easy... we first grab the Y values (4 bytes
+	#  at a time), then rewind and do the U values, and repeat for V.
+	#  This leaves us with a nice planar format
+
+	mov Width, %eax
+	shr %eax
+	shr %eax		# width / 4
+	mov %eax, -76(%ebp)	# Store
+
+	# Y
+	mov Height, %edx	# line counter
+0:	mov -76(%ebp), %ecx
+1:	lodsl			# get 4 bytes...
+	stosl			# ...push 4 bytes
+	add $2, %esi		# Skip U or V
+	loop 1b
+	dec %edx
+	jnz 0b
+
+	# U
+	mov Src4, %esi		# rewind source pointer
+	mov DstU, %edi
+	add $4, %esi		# set to U 
+	mov Height, %edx
+	shr %edx		# height / 2
+	mov Width, %ebx
+	shl %ebx
+	add Width, %ebx
+	shr %ebx		# Width * 1.5 (line offset)
+
+2:	mov -76(%ebp), %ecx	# width / 4
+3:	lodsw			# 2 bytes at a time
+	stosw
+	add $4, %esi		# skip Y
+	loop 3b
+	add %ebx, %esi		# Skip line (U is on even lines)
+	dec %edx
+	jnz 2b
+	
+	# V
+	mov Src4, %esi		# rewind, set to V in first odd line
+	add $4, %esi
+	add %ebx, %esi		# register re-use; no compiler can beat that :)
+	mov DstV, %edi		# V ptr
+	mov Height, %edx
+	shr %edx		# height / 2
+	
+4:	mov -76(%ebp), %ecx	# Get width/4
+5:	lodsw
+	stosw
+	add $4, %esi		# Skip Y
+	loop 5b
+	add %ebx, %esi		# Skip line (V is on odd lines)
+	dec %edx
+	jnz 4b
+	
+	/* That's it! */
+	
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
+
+
+/* Go from 4:2:0 interlaced to 'normal' YUYV */
+
+ENTRY(ccvt_420i_yuyv)
+	enter $80, $0		# 8 bytes extra space, no stackframes
+	push %ebx
+	push %esi
+	push %edi
+
+	call test_param_2
+	jc 9f
+	
+	mov Width, %ecx		# -4: width / 4 = no. loops per line
+	shr %ecx
+	shr %ecx
+	mov %ecx, -76(%ebp)
+
+	mov Width, %ebx		# -8: width * 1.5 = line offset
+	shl %ebx
+	add Width, %ebx
+	shr %ebx
+	mov %ebx, -80(%ebp)
+	
+	# Okay, this requires a bit of byte shuffling... we go from
+	#  YYYY UU
+	#  YYYY VV
+	# to
+	#  YUYV YUYV
+	#  YUYV YUYV
+	# which indeed takes up more space
+
+	# 
+	
+0:	mov -76(%ebp), %ecx
+
+1:	lodsl			# 4 Y in eax
+	testl $1, Height	# even or odd line?
+	jnz 2f
+	
+	# Even
+	mov -80(%ebp), %ebx
+	mov (%ebx, %esi), %dx	# 16 bits V 
+	shl $16, %edx		# store in high word
+	mov (%esi), %dx		# 16 bits U 
+	add $2, %esi
+	jmp 3f
+	
+2:	# Odd
+	mov -80(%ebp), %ebx
+	neg %ebx		# negative offset
+	mov (%esi), %dx		# 16 bits V
+	shl $16, %edx		# store in high word
+	mov (%ebx, %esi), %dx	# 16 bits U
+	add $2, %esi
+
+3:	# eax = Y3Y2Y1Y0, edx = V1V0U1U0, ebx is free
+	push %eax
+
+	movzbl %al, %ebx	# ______y0
+	and $0xFF00, %eax	# ____y1__
+	shl $8, %eax		# __y1____
+	or %ebx, %eax		# __y1__y0
+	mov %edx, %ebx		# v1v0u1u0
+	shl $8, %ebx		# v0u1u0__
+	and $0xff00ff00, %ebx	# v0__u0__
+	or %ebx, %eax		# v0y1u0y0
+	stosl	
+
+	pop %eax		# y3y2y1y0
+	# Second half
+	shr $8, %eax		# __y3y2y1
+	shr $8, %ax		# __y3__y2
+	and $0xff00ff00, %edx	# v1__u1__
+	or %edx, %eax		# v1y3u1y2
+	stosl
+	
+	loop 1b
+
+
+	decl Height		# height--
+	jnz 0b
+	# Done
+
+9:	pop %edi
+	pop %esi
+	pop %ebx
+	leave
+	ret
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- v2.4.4/linux/drivers/usb/dabusb.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/dabusb.c	Mon May 21 15:02:06 2001
@@ -43,6 +43,13 @@
 #include "dabusb.h"
 #include "dabfirmware.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.54"
+#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
+#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999"
+
 /* --------------------------------------------------------------------- */
 
 #define NRDABUSB 4
@@ -829,6 +836,10 @@
 		return -1;
 
 	dbg("dabusb_init: driver registered");
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -841,8 +852,9 @@
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
-MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
 MODULE_PARM (buffers, "i");
 MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- v2.4.4/linux/drivers/usb/dc2xx.c	Wed Apr 18 11:49:12 2001
+++ linux/drivers/usb/dc2xx.c	Thu May 24 14:55:51 2001
@@ -46,6 +46,7 @@
  * 12 Aug, 2000 .. add some real locking, remove an Oops
  * 10 Oct, 2000 .. usb_device_id table created. 
  * 01 Nov, 2000 .. usb_device_id support added by Adam J. Richter
+ * 08 Apr, 2001 .. Identify version on module load. gb
  *
  * Thanks to:  the folk who've provided USB product IDs, sent in
  * patches, and shared their successes!
@@ -71,6 +72,13 @@
 #include <linux/usb.h>
 
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "David Brownell, <dbrownell@users.sourceforge.net>"
+#define DRIVER_DESC "USB Camera Driver for Kodak DC-2xx series cameras"
+
 
 /* current USB framework handles max of 16 USB devices per driver */
 #define	MAX_CAMERAS		16
@@ -328,8 +336,9 @@
 	if (!camera->dev) {
 		minor_data [subminor] = NULL;
 		kfree (camera);
-	}
-	up (&camera->sem);
+	} else
+		up (&camera->sem);
+	
 	up (&state_table_mutex);
 
 	dbg ("close #%d", subminor); 
@@ -389,7 +398,6 @@
 	}
 	if (i >= MAX_CAMERAS) {
 		info ("Ignoring additional USB Camera");
-		up (&state_table_mutex);
 		goto bye;
 	}
 
@@ -397,7 +405,6 @@
 	camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
 	if (!camera) {
 		err ("no memory!");
-		up (&state_table_mutex);
 		goto bye;
 	}
 
@@ -464,13 +471,15 @@
 	if (!camera->buf) {
 		minor_data [subminor] = NULL;
 		kfree (camera);
+		camera = NULL;
 	} else
 		camera->dev = NULL;
 
 	info ("USB Camera #%d disconnected", subminor);
 	usb_dec_dev_use (dev);
 
-	up (&camera->sem);
+	if (camera != NULL)
+		up (&camera->sem);
 	up (&state_table_mutex);
 }
 
@@ -490,6 +499,8 @@
 {
  	if (usb_register (&camera_driver) < 0)
  		return -1;
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -498,9 +509,9 @@
 	usb_deregister (&camera_driver);
 }
 
-
-MODULE_AUTHOR("David Brownell, <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION("USB Camera Driver for Kodak DC-2xx series cameras");
-
 module_init (usb_dc2xx_init);
 module_exit (usb_dc2xx_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c
--- v2.4.4/linux/drivers/usb/dsbr100.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/dsbr100.c	Mon May 21 15:02:06 2001
@@ -65,6 +65,13 @@
 #include <linux/videodev.h>
 #include <linux/usb.h>
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.24"
+#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
+#define DRIVER_DESC "D-Link DSB-R100 USB radio driver"
+
 #define DSB100_VENDOR 0x04b4
 #define DSB100_PRODUCT 0x1002
 
@@ -100,6 +107,7 @@
 };
 
 static int users = 0;
+static int radio_nr = -1;
 
 static struct usb_device_id usb_dsbr100_table [] = {
 	{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
@@ -330,10 +338,12 @@
 {
 	usb_dsbr100_radio.priv = NULL;
 	usb_register(&usb_dsbr100_driver);
-	if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO)==-1) {	
+	if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO,radio_nr)==-1) {	
 		warn("couldn't register video device");
 		return -EINVAL;
 	}
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -350,8 +360,8 @@
 module_init (dsbr100_init);
 module_exit (dsbr100_exit);
 
-MODULE_AUTHOR("Markus Demleitner <msdemlei@tucana.harvard.edu>");
-MODULE_DESCRIPTION("D-Link DSB-R100 USB radio driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 /*
 vi: ts=8
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
--- v2.4.4/linux/drivers/usb/hid.c	Thu Apr 26 22:17:26 2001
+++ linux/drivers/usb/hid.c	Mon May 21 15:02:06 2001
@@ -54,6 +54,13 @@
 #define hid_dump_device(c)	do { } while (0)
 #endif
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.16"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID support drivers"
+
 #define unk	KEY_UNKNOWN
 
 static unsigned char hid_keyboard[256] = {
@@ -1552,6 +1559,8 @@
 static int __init hid_init(void)
 {
 	usb_register(&hid_driver);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -1563,5 +1572,6 @@
 module_init(hid_init);
 module_exit(hid_exit);
 
-MODULE_AUTHOR("Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB HID support drivers");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c
--- v2.4.4/linux/drivers/usb/ibmcam.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/ibmcam.c	Thu May 24 14:55:51 2001
@@ -43,9 +43,18 @@
 
 #include "ibmcam.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "http://www.linux-usb.org/ibmcam/"
+#define DRIVER_DESC "IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"
+
 #define	ENABLE_HEXDUMP	0	/* Enable if you need it */
 static int debug = 0;
 
+static int video_nr = -1;
+
 /* Completion states of the data parser */
 typedef enum {
 	scan_Continue,		/* Just parse next item */
@@ -159,9 +168,6 @@
 MODULE_PARM(init_model2_yb, "i");
 MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
 
-MODULE_AUTHOR ("module author");
-MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
-
 /* Still mysterious i2c commands */
 static const unsigned short unknown_88 = 0x0088;
 static const unsigned short unknown_89 = 0x0089;
@@ -3032,7 +3038,7 @@
 	usb_ibmcam_configure_video(ibmcam);
 	up (&ibmcam->lock);
 
-	if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER) == -1) {
+	if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
 		printk(KERN_ERR "video_register_device failed\n");
 		ibmcam = NULL; /* Do not free, it's preallocated */
 	}
@@ -3141,6 +3147,8 @@
 		struct usb_ibmcam *ibmcam = &cams[u];
 		memset (ibmcam, 0, sizeof(struct usb_ibmcam));
 	}
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return usb_register(&ibmcam_driver);
 }
 
@@ -3151,5 +3159,8 @@
 
 module_init(usb_ibmcam_init);
 module_exit(usb_ibmcam_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/inode.c linux/drivers/usb/inode.c
--- v2.4.4/linux/drivers/usb/inode.c	Fri Mar  2 13:47:21 2001
+++ linux/drivers/usb/inode.c	Tue May 22 10:25:36 2001
@@ -43,6 +43,11 @@
 
 /* --------------------------------------------------------------------- */
 
+/*
+ * This list of superblocks is still used,
+ * but since usbdevfs became FS_SINGLE
+ * there is only one super_block.
+ */
 static LIST_HEAD(superlist);
 
 struct special {
@@ -159,6 +164,97 @@
 	iput(inode);
 }
 
+static int parse_options(struct super_block *s, char *data)
+{
+	uid_t devuid = 0, busuid = 0, listuid = 0;
+	gid_t devgid = 0, busgid = 0, listgid = 0;
+	umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
+	char *curopt = NULL, *value;
+
+	/* parse options */
+	if (data)
+		curopt = strtok(data, ",");
+	for (; curopt; curopt = strtok(NULL, ",")) {
+		if ((value = strchr(curopt, '=')) != NULL)
+			*value++ = 0;
+		if (!strcmp(curopt, "devuid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			devuid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "devgid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			devgid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "devmode")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "busuid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			busuid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "busgid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			busgid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "busmode")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "listuid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			listuid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "listgid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			listgid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "listmode")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+			if (*value)
+				return -EINVAL;
+		}
+	}
+
+	s->u.usbdevfs_sb.devuid = devuid;
+	s->u.usbdevfs_sb.devgid = devgid;
+	s->u.usbdevfs_sb.devmode = devmode;
+	s->u.usbdevfs_sb.busuid = busuid;
+	s->u.usbdevfs_sb.busgid = busgid;
+	s->u.usbdevfs_sb.busmode = busmode;
+	s->u.usbdevfs_sb.listuid = listuid;
+	s->u.usbdevfs_sb.listgid = listgid;
+	s->u.usbdevfs_sb.listmode = listmode;
+
+	return 0;
+}
+
 static struct usb_bus *usbdevfs_findbus(int busnr)
 {
         struct list_head *list;
@@ -460,10 +556,47 @@
         return 0;
 }
 
+static int usbdevfs_remount(struct super_block *s, int *flags, char *data)
+{
+	struct list_head *ilist = s->u.usbdevfs_sb.ilist.next;
+	struct inode *inode;
+	int ret;
+
+	if ((ret = parse_options(s, data))) {
+		printk(KERN_WARNING "usbdevfs: remount parameter error\n");
+		return ret;
+	}
+
+	for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = ilist->next) {
+		inode = list_entry(ilist, struct inode, u.usbdev_i.slist);
+
+		switch (ITYPE(inode->i_ino)) {
+			case ISPECIAL :
+				inode->i_uid = s->u.usbdevfs_sb.listuid;
+				inode->i_gid = s->u.usbdevfs_sb.listgid;
+				inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
+				break;
+			case IBUS :
+				inode->i_uid = s->u.usbdevfs_sb.busuid;
+				inode->i_gid = s->u.usbdevfs_sb.busgid;
+				inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR;
+				break;
+			case IDEVICE :
+				inode->i_uid = s->u.usbdevfs_sb.devuid;
+				inode->i_gid = s->u.usbdevfs_sb.devgid;
+				inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG;
+				break;
+		}
+	}
+
+	return 0;
+}
+
 static struct super_operations usbdevfs_sops = { 
 	read_inode:	usbdevfs_read_inode,
 	put_super:	usbdevfs_put_super,
 	statfs:		usbdevfs_statfs,
+	remount_fs:	usbdevfs_remount,
 };
 
 struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent)
@@ -472,81 +605,12 @@
 	struct list_head *blist;
 	struct usb_bus *bus;
 	unsigned int i;
-	uid_t devuid = 0, busuid = 0, listuid = 0;
-	gid_t devgid = 0, busgid = 0, listgid = 0;
-	umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
-	char *curopt = NULL, *value;
 
-	/* parse options */
-	if (data)
-		curopt = strtok(data, ",");
-	for (; curopt; curopt = strtok(NULL, ",")) {
-		if ((value = strchr(curopt, '=')) != NULL)
-			*value++ = 0;
-		if (!strcmp(curopt, "devuid")) {
-			if (!value || !value[0])
-				goto opterr;
-			devuid = simple_strtoul(value, &value, 0);
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "devgid")) {
-			if (!value || !value[0])
-				goto opterr;
-			devgid = simple_strtoul(value, &value, 0);
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "devmode")) {
-			if (!value || !value[0])
-				goto opterr;
-			devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "busuid")) {
-			if (!value || !value[0])
-				goto opterr;
-			busuid = simple_strtoul(value, &value, 0);
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "busgid")) {
-			if (!value || !value[0])
-				goto opterr;
-			busgid = simple_strtoul(value, &value, 0);
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "busmode")) {
-			if (!value || !value[0])
-				goto opterr;
-			busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "listuid")) {
-			if (!value || !value[0])
-				goto opterr;
-			listuid = simple_strtoul(value, &value, 0);
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "listgid")) {
-			if (!value || !value[0])
-				goto opterr;
-			listgid = simple_strtoul(value, &value, 0);
-			if (*value)
-				goto opterr;
-		}
-		if (!strcmp(curopt, "listmode")) {
-			if (!value || !value[0])
-				goto opterr;
-			listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
-			if (*value)
-				goto opterr;
-		}
+	if (parse_options(s, data)) {
+		printk(KERN_WARNING "usbdevfs: mount parameter error\n");
+		return NULL;
 	}
+
 	/* fill superblock */
         s->s_blocksize = 1024;
         s->s_blocksize_bits = 10;
@@ -554,12 +618,6 @@
         s->s_op = &usbdevfs_sops;
 	INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
 	INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
-	s->u.usbdevfs_sb.devuid = devuid;
-	s->u.usbdevfs_sb.devgid = devgid;
-	s->u.usbdevfs_sb.devmode = devmode;
-	s->u.usbdevfs_sb.busuid = busuid;
-	s->u.usbdevfs_sb.busgid = busgid;
-	s->u.usbdevfs_sb.busmode = busmode;
 	root_inode = iget(s, IROOT);
         if (!root_inode)
                 goto out_no_root;
@@ -570,9 +628,9 @@
 	for (i = 0; i < NRSPECIAL; i++) {
 		if (!(inode = iget(s, IROOT+1+i)))
 			continue;
-		inode->i_uid = listuid;
-		inode->i_gid = listgid;
-		inode->i_mode = listmode | S_IFREG;
+		inode->i_uid = s->u.usbdevfs_sb.listuid;
+		inode->i_gid = s->u.usbdevfs_sb.listgid;
+		inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
 		special[i].inode = inode;
 		list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
 		list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
@@ -590,10 +648,6 @@
         printk("usbdevfs_read_super: get root inode failed\n");
         iput(root_inode);
         return NULL;
-
- opterr:
-        printk(KERN_WARNING "usbdevfs: mount parameter error\n");
-	return NULL;
 }
 
 static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);
@@ -689,8 +743,10 @@
 	}
 	if ((ret = usb_register(&usbdevfs_driver)))
 		return ret;
-	if ((ret = register_filesystem(&usbdevice_fs_type)))
+	if ((ret = register_filesystem(&usbdevice_fs_type))) {
 		usb_deregister(&usbdevfs_driver);
+		return ret;
+	}
 	kern_mount(&usbdevice_fs_type);
 #ifdef CONFIG_PROC_FS		
 	/* create mount point for usbdevfs */
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/kiara.inc linux/drivers/usb/kiara.inc
--- v2.4.4/linux/drivers/usb/kiara.inc	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/kiara.inc	Tue May 22 10:25:36 2001
@@ -0,0 +1,270 @@
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+         {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+         {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+         {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+         {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 25 fps */
+      {
+         {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+         {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+         {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+         {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+      },
+      /* 30 fps */
+      {
+         {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+         {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+         {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+         {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+         {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+         {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+         {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+         {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+         {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+         {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+         {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+         {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+         {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+         {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+         {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+         {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+         {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+         {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+         {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+         {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+         {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+         {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+         {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c
--- v2.4.4/linux/drivers/usb/mdc800.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/mdc800.c	Mon May 21 15:02:06 2001
@@ -29,6 +29,9 @@
  * mknod /dev/mustek c 180 32
  *
  * The driver supports only one camera.
+ * 
+ * (08/04/2001) gb
+ * Identify version on module load.
  *
  * version 0.7.5
  * Fixed potential SMP races with Spinlocks.
@@ -90,8 +93,12 @@
 
 #include <linux/usb.h>
 
-#define VERSION 	"0.7.5"
-#define RELEASE_DATE 	"(30/10/2000)"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.7.5 (30/10/2000)"
+#define DRIVER_AUTHOR "Henning Zabel <henning@uni-paderborn.de>"
+#define DRIVER_DESC "USB Driver for Mustek MDC800 Digital Camera"
 
 /* Vendor and Product Information */
 #define MDC800_VENDOR_ID 	0x055f
@@ -925,8 +932,8 @@
 	if (usb_register (&mdc800_usb_driver) < 0)
 		goto cleanup_on_fail;
 
-	info ("Mustek Digital Camera Driver " VERSION " (MDC800)");
-	info (RELEASE_DATE " Henning Zabel <henning@uni-paderborn.de>");
+	info (DRIVER_VERSION " " DRIVER_AUTHOR);
+	info (DRIVER_DESC);
 
 	return 0;
 
@@ -969,9 +976,9 @@
 	mdc800=0;
 }
 
-
-MODULE_AUTHOR ("Henning Zabel <henning@uni-paderborn.de>");
-MODULE_DESCRIPTION ("USB Driver for Mustek MDC800 Digital Camera");
-
 module_init (usb_mdc800_init);
 module_exit (usb_mdc800_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c
--- v2.4.4/linux/drivers/usb/microtek.c	Fri Mar 23 11:50:01 2001
+++ linux/drivers/usb/microtek.c	Mon May 21 15:02:06 2001
@@ -115,6 +115,7 @@
  *      20010311 Remove all timeouts and tidy up generally (john)
  *	20010320 check return value of scsi_register()
  *	20010320 Version 0.4.3
+ *	20010408 Identify version on module load.
  */
 
 #include <linux/module.h>
@@ -139,6 +140,13 @@
 
 #include "microtek.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.4.3"
+#define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"
+#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
+
 /* Should we do debugging? */
 
 //#define MTS_DO_DEBUG
@@ -1021,6 +1029,9 @@
 		MTS_DEBUG("driver registered.\n");
 	}
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -1050,5 +1061,6 @@
 module_init(microtek_drv_init);
 module_exit(microtek_drv_exit);
 
-MODULE_AUTHOR("John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>");
-MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/nala.inc linux/drivers/usb/nala.inc
--- v2.4.4/linux/drivers/usb/nala.inc	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/nala.inc	Tue May 22 10:25:36 2001
@@ -0,0 +1,66 @@
+   /* SQCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x03}},
+      {8, 0, {0x05, 0x01, 0x03}},
+      {7, 0, {0x08, 0x01, 0x03}},
+      {7, 0, {0x0A, 0x01, 0x03}},
+      {6, 0, {0x0C, 0x01, 0x03}},
+      {5, 0, {0x0F, 0x01, 0x03}},
+      {4, 0, {0x14, 0x01, 0x03}},
+      {3, 0, {0x18, 0x01, 0x03}},
+   },
+   /* QSIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* QCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x02}},
+      {8, 0, {0x05, 0x01, 0x02}},
+      {7, 0, {0x08, 0x01, 0x02}},
+      {6, 0, {0x0A, 0x01, 0x02}},
+      {5, 0, {0x0C, 0x01, 0x02}},
+      {4, 0, {0x0F, 0x01, 0x02}},
+      {1, 0, {0x14, 0x01, 0x02}},
+      {1, 0, {0x18, 0x01, 0x02}},
+   },
+   /* SIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* CIF */
+   {
+      {4, 0, {0x04, 0x01, 0x01}},
+      {7, 1, {0x05, 0x03, 0x01}},
+      {6, 1, {0x08, 0x03, 0x01}},
+      {4, 1, {0x0A, 0x03, 0x01}},
+      {3, 1, {0x0C, 0x03, 0x01}},
+      {2, 1, {0x0F, 0x03, 0x01}},
+      {0},
+      {0},
+   },
+   /* VGA */
+   {  
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/net1080.c linux/drivers/usb/net1080.c
--- v2.4.4/linux/drivers/usb/net1080.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/net1080.c	Mon May 21 15:02:06 2001
@@ -34,6 +34,9 @@
  * 01-nov-2000
  * usb_device_id table support added by Adam J. Richter <adam@yggdrasil.com>.
  * 
+ * 08-apr-2001 gb
+ * Identify version on module load.
+ * 
  *-------------------------------------------------------------------------*/
 
 #include <linux/config.h>
@@ -55,6 +58,13 @@
 #endif
 #include <linux/usb.h>
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "David Brownell <dbrownell@users.sourceforge.net>"
+#define DRIVER_DESC "NetChip 1080 Driver (USB Host-to-Host Link)"
+
 
 static const struct usb_device_id	products [] = {
 	// reference design
@@ -1101,6 +1111,9 @@
 	get_random_bytes (node_id, sizeof node_id);
 	node_id [0] &= 0x7f;
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 module_init (net1080_init);
@@ -1111,5 +1124,6 @@
 }
 module_exit (net1080_exit);
 
-MODULE_AUTHOR ("David Brownell <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION ("NetChip 1080 Driver (USB Host-to-Host Link)");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- v2.4.4/linux/drivers/usb/ov511.c	Sun Mar 25 18:24:31 2001
+++ linux/drivers/usb/ov511.c	Thu May 24 15:24:37 2001
@@ -30,8 +30,6 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.28";
-
 #define __NO_VERSION__
 
 #include <linux/config.h>
@@ -51,6 +49,13 @@
 
 #include "ov511.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.28"
+#define DRIVER_AUTHOR "Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
+#define DRIVER_DESC "OV511 USB Camera Driver"
+
 #define OV511_I2C_RETRIES 3
 
 /* Video Size 640 x 480 x 3 bytes for RGB */
@@ -62,6 +67,8 @@
 /* PARAMETER VARIABLES: */
 static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
 
+static int video_nr = -1;
+
 /* 0=no debug messages
  * 1=init/detection/unload and other significant messages,
  * 2=some warning messages
@@ -146,8 +153,8 @@
 MODULE_PARM(dumppix, "i");
 MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");
 
-MODULE_AUTHOR("Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
-MODULE_DESCRIPTION("OV511 USB Camera Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 static struct usb_driver ov511_driver;
 
@@ -3139,7 +3146,7 @@
 
 	init_waitqueue_head(&ov511->wq);
 
-	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) < 0) {
+	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
 		err("video_register_device failed");
 		return -EBUSY;
 	}
@@ -3419,7 +3426,8 @@
 	if (usb_register(&ov511_driver) < 0)
 		return -1;
 
-	info("ov511 driver version %s registered", version);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c
--- v2.4.4/linux/drivers/usb/pegasus.c	Sun Mar 18 19:54:52 2001
+++ linux/drivers/usb/pegasus.c	Mon May 21 15:02:06 2001
@@ -50,13 +50,16 @@
 #include <linux/module.h>
 #include "pegasus.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.4.18 2001/03/18 (C) 1999-2000"
+#define DRIVER_AUTHOR "Petko Manolov <petkan@dce.bg>"
+#define DRIVER_DESC "ADMtek AN986 Pegasus USB Ethernet driver"
 
 #define	PEGASUS_USE_INTR
 #define	PEGASUS_WRITE_EEPROM
 
-static const char *version = __FILE__ ": v0.4.18 2001/03/18 (C) 1999-2000 Petko Manolov (petkan@dce.bg)";
-
-
 static int loopback = 0;
 static int mii_mode = 0;
 static int multicast_filter_limit = 32;
@@ -78,8 +81,8 @@
 };
 
 
-MODULE_AUTHOR("Petko Manolov <petkan@dce.bg>");
-MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_PARM(loopback, "i");
 MODULE_PARM(mii_mode, "i");
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
@@ -902,7 +905,8 @@
 
 int __init pegasus_init(void)
 {
-	info( "%s", version );
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return usb_register( &pegasus_driver );
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pegasus.h linux/drivers/usb/pegasus.h
--- v2.4.4/linux/drivers/usb/pegasus.h	Tue Nov 14 12:57:50 2000
+++ linux/drivers/usb/pegasus.h	Mon May 21 17:04:24 2001
@@ -127,7 +127,7 @@
 	__u32	private; /* LSB is gpio reset value */
 };
 
-
+#define	VENDOR_3COM		0x0506
 #define VENDOR_ACCTON           0x083a
 #define VENDOR_ADMTEK           0x07a6
 #define VENDOR_BILLIONTON       0x08dd
@@ -138,13 +138,14 @@
 #define VENDOR_LANEED           0x056e
 #define VENDOR_LINKSYS          0x066b
 #define VENDOR_MELCO            0x0411
+#define VENDOR_SMARTBRIDGES	0x08d1
 #define VENDOR_SMC              0x0707
 #define VENDOR_SOHOWARE         0x15e8
 
-
 #else	/* PEGASUS_DEV */
 
-
+PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
@@ -175,6 +176,8 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "D-Link DU-E100", VENDOR_DLINK2, 0x4002,
 		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "FiberLine USB", VENDOR_DLINK2, 0x4102,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
@@ -189,10 +192,11 @@
 		LINKSYS_GPIO_RESET )
 PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
 		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
 		DEFAULT_GPIO_RESET )
-
 
 #endif	/* PEGASUS_DEV */
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/plusb.c linux/drivers/usb/plusb.c
--- v2.4.4/linux/drivers/usb/plusb.c	Wed Apr 18 11:49:12 2001
+++ linux/drivers/usb/plusb.c	Mon May 21 15:02:06 2001
@@ -140,6 +140,13 @@
 #define dev_kfree_skb_any dev_kfree_skb
 #endif
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5.7"
+#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
+#define DRIVER_DESC "PL-2302 USB Interface Driver for Linux (c)2000"
+
 /* Definitions formerly in plusb.h relocated. No need to export them -EZA */
 
 #define _PLUSB_INTPIPE		0x1
@@ -1007,6 +1014,9 @@
 
 	dbg("plusb_init: driver registered");
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -1041,8 +1051,8 @@
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
-MODULE_DESCRIPTION ("PL-2302 USB Interface Driver for Linux (c)2000");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 
 module_init (plusb_init);
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.4.4/linux/drivers/usb/printer.c	Fri Mar  2 17:50:22 2001
+++ linux/drivers/usb/printer.c	Mon May 21 15:02:06 2001
@@ -50,6 +50,13 @@
 #undef DEBUG
 #include <linux/usb.h>
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.8"
+#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
+#define DRIVER_DESC "USB Printer Device Class driver"
+
 #define USBLP_BUF_SIZE		8192
 #define DEVICE_ID_SIZE		1024
 
@@ -655,6 +662,8 @@
 {
 	if (usb_register(&usblp_driver))
 		return -1;
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -666,5 +675,6 @@
 module_init(usblp_init);
 module_exit(usblp_exit);
 
-MODULE_AUTHOR("Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap");
-MODULE_DESCRIPTION("USB Printer Device Class driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc-ctrl.c linux/drivers/usb/pwc-ctrl.c
--- v2.4.4/linux/drivers/usb/pwc-ctrl.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc-ctrl.c	Tue May 22 10:25:36 2001
@@ -0,0 +1,939 @@
+/* Driver for Philips webcam
+   Functions that send various control messages to the webcam, including
+   video modes.
+   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   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
+*/
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h> 
+#endif
+#include <asm/errno.h>
+ 
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+
+/* Request types: video */
+#define SET_LUM_CTL			0x01
+#define GET_LUM_CTL			0x02
+#define SET_CHROM_CTL			0x03
+#define GET_CHROM_CTL			0x04
+#define SET_STATUS_CTL			0x05
+#define GET_STATUS_CTL			0x06
+#define SET_EP_STREAM_CTL		0x07
+#define GET_EP_STREAM_CTL		0x08
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER			0x2000
+#define PRESET_AGC_FORMATTER			0x2100
+#define SHUTTER_MODE_FORMATTER			0x2200
+#define PRESET_SHUTTER_FORMATTER		0x2300
+#define PRESET_CONTOUR_FORMATTER		0x2400
+#define AUTO_CONTOUR_FORMATTER			0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER	0x2600
+#define CONTRAST_FORMATTER			0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER		0x2800
+#define FLICKERLESS_MODE_FORMATTER		0x2900
+#define AE_CONTROL_SPEED			0x2A00
+#define BRIGHTNESS_FORMATTER			0x2B00
+#define GAMMA_FORMATTER				0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER			0x1000
+#define AWB_CONTROL_SPEED_FORMATTER		0x1100
+#define AWB_CONTROL_DELAY_FORMATTER		0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER	0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER	0x1400
+#define COLOUR_MODE_FORMATTER			0x1500
+#define SATURATION_MODE_FORMATTER1		0x1600
+#define SATURATION_MODE_FORMATTER2		0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER		0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER		0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER	0x0400
+#define READ_AGC_FORMATTER			0x0500
+#define READ_SHUTTER_FORMATTER			0x0600
+#define READ_RED_GAIN_FORMATTER			0x0700
+#define READ_BLUE_GAIN_FORMATTER		0x0800
+#define READ_RAW_Y_MEAN_FORMATTER		0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER		0x3200
+#define MIRROR_IMAGE_FORMATTER			0x3300
+#define LED_FORMATTER				0x3400
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
+
+static char *size2name[PSZ_MAX] =
+{
+	"subQCIF",
+	"QSIF",
+	"QCIF",
+	"SIF",
+	"CIF",
+	"VGA",
+};  
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
+   preferences, so you either get compressed or non-compressed streams.
+   
+   An alternate value of 0 means this mode is not available at all.
+ */
+
+struct Nala_table_entry {
+	char alternate;			/* USB alternate setting */
+	int compressed;			/* Compressed yes/no */
+
+	unsigned char mode[3];		/* precomputed mode table */
+};
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
+{
+#include "nala.inc"
+};
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface 
+   number. An alternate of 0 means that the mode is unavailable.
+   
+   There are 6 * 4 * 4 entries: 
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+     
+   When an uncompressed mode is not available, the next available compressed mode 
+   will be choosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+struct Timon_table_entry 
+{
+	char alternate;			/* USB alternate interface */
+	unsigned short packetsize;	/* Normal packet size */
+	unsigned short bandlength;	/* Bandlength when decompressing */
+	unsigned char mode[13];		/* precomputed mode settings for cam */
+};
+
+static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = 
+{
+#include "timon.inc"
+};
+
+/* Entries for the Kiara (730/740) camera */
+
+struct Kiara_table_entry
+{
+	char alternate;			/* USB alternate interface */
+	unsigned short packetsize;	/* Normal packet size */
+	unsigned short bandlength;	/* Bandlength when decompressing */
+	unsigned char mode[12];		/* precomputed mode settings for cam */
+};
+
+static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+#include "kiara.inc"
+};
+
+
+/****************************************************************************/
+
+
+
+
+#if PWC_DEBUG
+void pwc_hexdump(void *p, int len)
+{
+	int i;
+	unsigned char *s;
+	char buf[100], *d;
+	
+	s = (unsigned char *)p;
+	d = buf;
+	*d = '\0';
+	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
+	for (i = 0; i < len; i++) {
+		d += sprintf(d, "%02X ", *s++);
+		if ((i & 0xF) == 0xF) {
+			Debug("%s\n", buf);
+			d = buf;
+			*d = '\0';
+		}
+	}
+	if ((i & 0xF) != 0)
+		Debug("%s\n", buf);
+}
+#endif
+
+static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+{
+#ifdef __KERNEL__
+	return usb_control_msg(udev,
+		usb_sndctrlpipe(udev, 0),
+		SET_EP_STREAM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		VIDEO_OUTPUT_CONTROL_FORMATTER,
+		index,
+		buf, buflen, HZ);
+#else
+	return 0;
+#endif	
+}
+
+
+
+static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+{
+	unsigned char buf[3];
+	int ret, fps;
+	struct Nala_table_entry *pEntry;
+	int frames2frames[31] = 
+	{ /* closest match of framerate */
+	   0,  0,  0,  0,  4,  /*  0-4  */
+	   5,  5,  7,  7, 10,  /*  5-9  */
+          10, 10, 12, 12, 15,  /* 10-14 */
+          15, 15, 15, 20, 20,  /* 15-19 */
+          20, 20, 20, 24, 24,  /* 20-24 */
+          24, 24, 24, 24, 24,  /* 25-29 */
+          24                   /* 30    */
+	};
+	int frames2table[31] = 
+	{ 0, 0, 0, 0, 0, /*  0-4  */
+	  1, 1, 1, 2, 2, /*  5-9  */
+	  3, 3, 4, 4, 4, /* 10-14 */
+	  5, 5, 5, 5, 5, /* 15-19 */
+	  6, 6, 6, 6, 7, /* 20-24 */
+	  7, 7, 7, 7, 7, /* 25-29 */
+	  7              /* 30    */
+	};
+	
+	if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+		return -EINVAL;
+	frames = frames2frames[frames];
+	fps = frames2table[frames];
+	pEntry = &Nala_table[size][fps];
+	if (pEntry->alternate == 0)
+		return -EINVAL;
+
+	if (pEntry->compressed && pdev->decompressor == NULL)
+		return -ENOENT; /* Not supported. */
+
+	memcpy(buf, pEntry->mode, 3);	
+	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+	if (ret < 0)
+		return ret;
+	if (pEntry->compressed)
+		ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data);
+	if (ret < 0)
+		return ret;
+		
+	/* Set various parameters */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->valternate = pEntry->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+	if (pEntry->compressed) {
+		if (pdev->release < 5) { /* 4 fold compression */
+			pdev->vbandlength = 528;
+			pdev->frame_size /= 4;
+		}
+		else {
+			pdev->vbandlength = 704;
+			pdev->frame_size /= 3;
+		}
+	}
+	else
+		pdev->vbandlength = 0;
+	return 0;
+}
+
+
+static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+	unsigned char buf[13];
+	struct Timon_table_entry *pChoose;
+	int ret, fps;
+
+	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+		return -EINVAL;
+	if (size == PSZ_VGA && frames > 15)
+		return -EINVAL;
+	fps = (frames / 5) - 1;
+	
+	/* Find a supported framerate with progressively higher compression ratios
+	   if the preferred ratio is not available.
+	*/
+	pChoose = NULL;
+	if (pdev->decompressor == NULL) {
+#if PWC_DEBUG	
+		Debug("Trying to find uncompressed mode.\n");
+#endif
+		pChoose = &Timon_table[size][fps][0];
+	}
+	else {
+		while (compression <= 3) {
+			pChoose = &Timon_table[size][fps][compression];
+			if (pChoose->alternate != 0)
+				break;
+			compression++;	
+		}
+	}
+	if (pChoose == NULL || pChoose->alternate == 0)
+		return -ENOENT; /* Not supported. */
+
+	memcpy(buf, pChoose->mode, 13);
+	if (snapshot)
+		buf[0] |= 0x80;
+	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
+	if (ret < 0)
+		return ret;
+
+	if (pChoose->bandlength > 0)
+		ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data);
+	if (ret < 0)
+		return ret;
+	
+	/* Set various parameters */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->vsnapshot = snapshot;
+	pdev->valternate = pChoose->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->vbandlength = pChoose->bandlength;
+	if (pChoose->bandlength > 0) 
+		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+	else
+		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	return 0;
+}
+
+
+static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+	struct Kiara_table_entry *pChoose;
+	int fps, ret;
+	unsigned char buf[12];
+	
+	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+		return -EINVAL;
+	if (size == PSZ_VGA && frames > 15)
+		return -EINVAL;
+	fps = (frames / 5) - 1;
+	
+	/* Find a supported framerate with progressively higher compression ratios
+	   if the preferred ratio is not available.
+	*/
+	pChoose = NULL;
+	if (pdev->decompressor == NULL) {
+#if PWC_DEBUG	
+		Debug("Trying to find uncompressed mode.\n");
+#endif		
+		pChoose = &Kiara_table[size][fps][0];
+	}
+	else {
+		while (compression <= 3) {
+			pChoose = &Kiara_table[size][fps][compression];
+			if (pChoose->alternate != 0)
+				break;
+			compression++;	
+		}
+	}
+	if (pChoose == NULL || pChoose->alternate == 0)
+		return -ENOENT; /* Not supported. */
+
+	/* usb_control_msg won't take staticly allocated arrays as argument?? */
+	memcpy(buf, pChoose->mode, 12);
+	if (snapshot)
+		buf[0] |= 0x80;
+
+	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+	ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
+	if (ret < 0)
+		return ret;
+
+	if (pChoose->bandlength > 0)
+		ret = pdev->decompressor->init(pdev->release, buf, &pdev->decompress_data);
+	if (ret < 0)
+		return ret;
+		
+	/* All set and go */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->vsnapshot = snapshot;
+	pdev->valternate = pChoose->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->vbandlength = pChoose->bandlength;
+	if (pChoose->bandlength > 0)
+		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+	else 
+		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size);
+	return 0;
+}
+
+
+/**
+   @pdev: device structure
+   @width: viewport width
+   @height: viewport height
+   @frame: framerate, in fps
+   @compression: preferred compression ratio
+   @snapshot: snapshot mode or streaming
+ */
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+{
+	int ret, size;
+	
+	size = pwc_decode_size(pdev, width, height);
+	if (size < 0) {
+		Debug("Could not find suitable size.\n");
+		return -ERANGE;
+	}
+	ret = -EINVAL;	
+	switch(pdev->type) {
+	case 645:
+	case 646:
+		ret = set_video_mode_Nala(pdev, size, frames);
+		break;
+
+	case 675:
+	case 680:
+	case 690:
+		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+		break;
+		
+	case 730:
+	case 740:
+		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+		break;
+	}
+	if (ret < 0) {
+		if (ret == -ENOENT)
+			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
+		else {
+			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+			return ret;
+		}
+	}
+	/* If the video mode was not supported, we still adjust the view size,
+	   since xawtv (Again! Stupid program...) doesn't care zit about 
+	   return values.
+	 */
+	pdev->view.x = width;
+	pdev->view.y = height;
+	pwc_set_image_buffer_size(pdev);
+	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d. Palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette);
+	return 0;
+}
+
+
+void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+	int factor, i, filler = 0;
+
+	switch(pdev->vpalette) {
+	case VIDEO_PALETTE_RGB32 | 0x80:
+	case VIDEO_PALETTE_RGB32:
+		factor = 16;
+		filler = 0;
+		break;
+	case VIDEO_PALETTE_RGB24 | 0x80:
+	case VIDEO_PALETTE_RGB24:
+		factor = 12;
+		filler = 0;
+		break;
+	case VIDEO_PALETTE_YUYV:
+	case VIDEO_PALETTE_YUV422:
+		factor = 8;
+		filler = 128;
+		break;
+	case VIDEO_PALETTE_YUV420:
+	case VIDEO_PALETTE_YUV420P:
+		factor = 6;
+		filler = 128;
+		break;
+#if PWC_DEBUG		
+	case VIDEO_PALETTE_RAW:
+		pdev->image.size = pdev->frame_size;
+		pdev->view.size = pdev->frame_size;
+		return;
+		break;
+#endif	
+	default:
+		factor = 0;
+		break;
+	}
+
+	/* Set sizes in bytes */
+	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
+
+	pdev->offset.x = (pdev->view.x - pdev->image.x) / 2;
+	pdev->offset.y = (pdev->view.y - pdev->image.y) / 2;
+	if (pdev->vpalette == VIDEO_PALETTE_YUV420 || pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+		/* Align offset, or you'll get some very weird results in
+		   YUV mode... x must be multiple of 4 (to get the Y's in 
+		   place), and y even (or you'll mixup U & V).
+		 */
+		pdev->offset.x &= 0xFFFC;
+		pdev->offset.y &= 0xFFFE;	
+		/* This is the offset in the Y area, hence no factor */
+		pdev->offset.size = (pdev->offset.y * pdev->view.x + pdev->offset.x);
+	}
+	else
+		pdev->offset.size = (pdev->offset.y * pdev->view.x + pdev->offset.x) * factor / 4;
+	
+	/* Set buffers to gray */
+	for (i = 0; i < MAX_IMAGES; i++) {
+		if (pdev->image_ptr[i] != NULL)
+			memset(pdev->image_ptr[i], filler, pdev->view.size);
+	}
+}
+
+
+#ifdef __KERNEL__
+/* BRIGHTNESS */
+
+int pwc_get_brightness(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		BRIGHTNESS_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return buf << 9;
+}
+
+int pwc_set_brightness(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 9) & 0x7f;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		BRIGHTNESS_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+/* CONTRAST */
+
+int pwc_get_contrast(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		CONTRAST_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return buf << 10;
+}
+
+int pwc_set_contrast(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 10) & 0x3f;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		CONTRAST_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+/* GAMMA */
+
+int pwc_get_gamma(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		GAMMA_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return buf << 11;
+}
+
+int pwc_set_gamma(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 11) & 0x1f;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		GAMMA_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+
+/* SATURATION */
+
+int pwc_get_saturation(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+
+	if (pdev->type < 730)
+		return -1;
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_CHROM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SATURATION_MODE_FORMATTER1,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return 32768 + buf * 327;
+}
+
+int pwc_set_saturation(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (pdev->type < 730)
+		return -EINVAL;
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	/* saturation ranges from -100 to +100 */
+	buf = (value - 32768) / 327;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_CHROM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SATURATION_MODE_FORMATTER1,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+/* AGC */
+
+static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+{
+	char buf;
+	int ret;
+	
+	if (mode)
+		buf = 0x0; /* auto */
+	else
+		buf = 0xff; /* fixed */
+
+	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		AGC_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	
+	if (!mode && ret >= 0) {
+		if (value < 0)
+			value = 0;
+		if (value > 0xffff)
+			value = 0xffff;
+		buf = (value >> 10) & 0x3F;
+		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+			SET_LUM_CTL,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			PRESET_AGC_FORMATTER,
+			pdev->vcinterface,
+			&buf, 1, HZ / 2);
+	}
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		AGC_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+
+	if (buf != 0) { /* fixed */
+		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+			GET_LUM_CTL,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			PRESET_AGC_FORMATTER,
+			pdev->vcinterface,
+			&buf, 1, HZ / 2);
+		if (ret < 0)
+			return ret;
+		if (buf > 0x3F)
+			buf = 0x3F;
+		*value = (buf << 10);		
+	}
+	else { /* auto */
+		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+			GET_STATUS_CTL,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			READ_AGC_FORMATTER,
+			pdev->vcinterface,
+			&buf, 1, HZ / 2);
+		if (ret < 0)
+			return ret;
+		/* Gah... this value ranges from 0x00 ... 0x9F */
+		if (buf > 0x9F)
+			buf = 0x9F;
+		*value = -(48 + buf * 409);
+	}
+
+	return 0;
+}
+
+static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+{
+	char buf[2];
+	int speed, ret;
+
+
+	if (mode)
+		buf[0] = 0x0;	/* auto */
+	else
+		buf[0] = 0xff; /* fixed */
+	
+	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SHUTTER_MODE_FORMATTER,
+		pdev->vcinterface,
+		buf, 1, HZ / 2);
+
+	if (!mode && ret >= 0) {
+		if (value < 0)
+			value = 0;
+		if (value > 0xffff)
+			value = 0xffff;
+		switch(pdev->type) {
+		case 675:
+		case 680:
+		case 690:
+			/* speed ranges from 0x0 to 0x290 (656) */
+			speed = (value / 100);
+			buf[1] = speed >> 8;
+			buf[0] = speed & 0xff;
+			break;
+		case 730:
+		case 740:
+			/* speed seems to range from 0x0 to 0xff */
+			buf[1] = 0;
+			buf[0] = value >> 8;
+			break;
+		}
+
+		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+			SET_LUM_CTL,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			PRESET_SHUTTER_FORMATTER,
+			pdev->vcinterface,
+			&buf, 2, HZ / 2);
+	}
+	return ret;
+}	
+
+
+/* POWER */
+
+int pwc_camera_power(struct pwc_device *pdev, int power)
+{
+	char buf;
+
+	if (pdev->type < 675 || pdev->release < 6)
+		return 0;	/* Not supported by Nala or Timon < release 6 */
+
+	if (power)
+		buf = 0x00; /* active */
+	else
+		buf = 0xFF; /* power save */
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SET_POWER_SAVE_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+
+
+/* private calls */
+
+static inline int pwc_restore_user(struct pwc_device *pdev)
+{
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		RESTORE_USER_DEFAULTS_FORMATTER,
+		pdev->vcinterface,
+		NULL, 0, HZ / 2);
+}
+
+static inline int pwc_save_user(struct pwc_device *pdev)
+{
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SAVE_USER_DEFAULTS_FORMATTER,
+		pdev->vcinterface,
+		NULL, 0, HZ / 2);
+}
+
+static inline int pwc_restore_factory(struct pwc_device *pdev)
+{
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		RESTORE_FACTORY_DEFAULTS_FORMATTER,
+		pdev->vcinterface,
+		NULL, 0, HZ / 2);
+}
+
+int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+{
+	switch(cmd) {
+	case VIDIOCPWCRUSER:
+	{
+		if (pwc_restore_user(pdev))
+			return -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSUSER:
+	{
+		if (pwc_save_user(pdev))
+			return -EINVAL;
+		break;
+	}
+		
+	case VIDIOCPWCFACTORY:
+	{
+		if (pwc_restore_factory(pdev))
+			return -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSCQUAL:
+	{	
+		int qual, ret;
+
+		if (copy_from_user(&qual, arg, sizeof(int)))
+			return -EFAULT;
+			
+		if (qual < 0 || qual > 3)
+			return -EINVAL;
+		ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);
+		if (ret < 0)
+			return ret;
+		pdev->vcompression = qual;
+		break;
+	}
+	
+	case VIDIOCPWCGCQUAL:
+	{
+		if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))
+			return -EFAULT;
+		break;
+	}
+
+	case VIDIOCPWCSAGC:
+	{
+		int agc;
+		
+		if (copy_from_user(&agc, arg, sizeof(agc)))
+			return -EFAULT;	
+		else {
+			if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))
+				return -EINVAL;
+		}
+		break;
+	}
+	
+	case VIDIOCPWCGAGC:
+	{
+		int agc;
+		
+		if (pwc_get_agc(pdev, &agc))
+			return -EINVAL;
+		if (copy_to_user(arg, &agc, sizeof(agc)))
+			return -EFAULT;
+		break;
+	}
+	
+	case VIDIOCPWCSSHUTTER:
+	{
+		int shutter_speed, ret;
+
+		if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))
+			return -EFAULT;
+		else {
+			ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);
+			if (ret < 0)
+				return ret;
+		}
+		break;
+	}
+	
+	default:
+		return -ENOIOCTLCMD;
+		break;
+	}
+	return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc-if.c linux/drivers/usb/pwc-if.c
--- v2.4.4/linux/drivers/usb/pwc-if.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc-if.c	Tue May 22 10:25:36 2001
@@ -0,0 +1,1896 @@
+/* Linux driver for Philips webcam 
+   USB and Video4Linux interface part.
+   (C) 1999-2001 Nemosoft Unv.
+
+   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
+
+*/
+
+/*  
+   This code forms the interface between the USB layers and the Philips
+   specific stuff. Some adanved stuff of the driver falls under an
+   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+   is thus not distributed in source form. The binary pwcx.o module 
+   contains the code that falls under the NDA.
+   
+   In case you're wondering: 'pwc' stands for "Philips WebCam", but 
+   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+   without explanation).
+   
+   Oh yes, convention: to disctinguish between all the various pointers to
+   device-structures, I use these names for the pointer variables:
+   udev: struct usb_device *
+   vdev: struct video_device *
+   pdev: struct pwc_devive *
+*/   
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+
+#if !defined(MAP_NR)
+#define MAP_NR(a) virt_to_page(a)
+#endif
+
+/* Function prototypes and driver templates */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+
+/* hotplug device table support */
+static __devinitdata struct usb_device_id pwc_device_table [] = {
+	{ USB_DEVICE(0x0471, 0x0302) },
+	{ USB_DEVICE(0x0471, 0x0303) },
+	{ USB_DEVICE(0x0471, 0x0304) },
+	{ USB_DEVICE(0x0471, 0x0307) },
+	{ USB_DEVICE(0x0471, 0x0308) },
+	{ USB_DEVICE(0x0471, 0x030C) },
+	{ USB_DEVICE(0x0471, 0x0310) },
+	{ USB_DEVICE(0x0471, 0x0311) },
+	{ USB_DEVICE(0x069A, 0x0001) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id);
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
+
+static struct usb_driver pwc_driver =
+{
+	name:			"Philips webcam",	/* name */
+	id_table:		pwc_device_table,
+	probe:			usb_pwc_probe,		/* probe() */
+	disconnect:		usb_pwc_disconnect,	/* disconnect() */
+};
+
+#else
+
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum);
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
+
+static struct usb_driver pwc_driver =
+{
+	name:			"Philips webcam",	/* name */
+	probe:			usb_pwc_probe,		/* probe() */
+	disconnect:		usb_pwc_disconnect,	/* disconnect() */
+};
+#endif
+ 
+
+static int default_size = PSZ_QCIF;
+static int default_fps = 10;
+static int default_palette = VIDEO_PALETTE_RGB24; /* This is normal for webcams */
+static int default_fbufs = 3;   /* Default number of frame buffers */
+static int default_mbufs = 2;	/* Default number of mmap() buffers */
+       int pwc_trace = TRACE_MODULE | TRACE_FLOW;
+static int power_save = 0;
+int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+
+static struct semaphore mem_lock;
+static void *mem_leak = NULL; /* For delayed kfree()s. See below */
+
+static int video_nr = -1;
+
+/***/
+
+static int  pwc_video_open(struct video_device *vdev, int mode);
+static void pwc_video_close(struct video_device *vdev);
+static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock);
+static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock);
+static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait);
+static int  pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg);
+static int  pwc_video_mmap(struct video_device *dev, const char *adr, unsigned long size);
+
+static struct video_device pwc_template = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
+	owner:		NULL,
+#endif
+	name:		"Philips Webcam",	/* Filled in later */
+	type:		VID_TYPE_CAPTURE,
+#ifdef VID_HARDWARE_PWC
+	hardware:	VID_HARDWARE_PWC,	/* Let's pretend for now */
+#else
+	hardware:	0,			/* 2.2.14 backport (?) */
+#endif		
+	open:		pwc_video_open,
+	close:		pwc_video_close,
+	read:		pwc_video_read,
+	write:		pwc_video_write,
+	poll:		pwc_video_poll,
+	ioctl:		pwc_video_ioctl,
+	mmap:		pwc_video_mmap,
+	initialize:	NULL,			/* initialize */
+	minor:		0			/* minor */
+};
+
+/***************************************************************************/
+
+/* Okay, this is some magic that I worked out and the reasoning behind it...
+
+   The biggest problem with any USB device is of course: "what to do 
+   when the user unplugs the device while it is in use by an application?"
+   We have several options:
+   1) Curse them with the 7 plagues when they do (requires divine intervention)
+   2) Tell them not to (won't work: they'll do it anyway)
+   3) Oops the kernel (this will have a negative effect on a user's uptime)
+   4) Do something sensible.
+   
+   Of course, we go for option 4.
+
+   It happens that this device will be linked to two times, once from
+   usb_device and once from the video_device in their respective 'private'
+   pointers. This is done when the device is probed() and all initialization
+   succeeded. The pwc_device struct links back to both structures.
+
+   When a device is unplugged while in use it will be removed from the 
+   list of known USB devices; I also de-register as a V4L device, but 
+   unfortunately I can't free the memory since the struct is still in use
+   by the file descriptor. This free-ing is then deferend until the first
+   opportunity. Crude, but it works.
+   
+   A small 'advantage' is that if a user unplugs the cam and plugs it back
+   in, it should get assigned the same video device minor, but unfortunately
+   it's non-trivial to re-link the cam back to the video device... (that 
+   would surely be magic! :))
+*/
+
+/***************************************************************************/
+/* Private functions */
+
+/* Memory management functions, nicked from cpia.c, which nicked them from
+   bttv.c. So far, I've counted duplication of this code 6 times 
+   (bttv, cpia, ibmcam, ov511, pwc, ieee1394).
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+	unsigned long ret = 0UL;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	if (!pgd_none(*pgd)) {
+		pmd = pmd_offset(pgd, adr);
+		if (!pmd_none(*pmd)) {
+			ptep = pte_offset(pmd, adr);
+			pte = *ptep;
+			if (pte_present(pte)) {
+				ret = (unsigned long) page_address(pte_page(pte));
+				ret |= (adr & (PAGE_SIZE-1));
+			}
+		}
+	}
+	return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+	ret = virt_to_bus((void *)kva);
+	return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+	unsigned long va, kva, ret;
+
+	va = VMALLOC_VMADDR(adr);
+	kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = virt_to_bus((void *)kva);
+	return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+	unsigned long va, kva, ret;
+
+	va = VMALLOC_VMADDR(adr);
+	kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = __pa(kva);
+	return ret;
+}
+
+static void *rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr, page;
+
+	/* Round it off to PAGE_SIZE */
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	mem = vmalloc(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		page = kvirt_to_pa(adr);
+		mem_map_reserve(MAP_NR(__va(page)));
+		adr += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr, page;
+
+	if (!mem)
+		return;
+
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	adr=(unsigned long) mem;
+	while (size > 0) {
+		page = kvirt_to_pa(adr);
+		mem_map_unreserve(MAP_NR(__va(page)));
+		adr += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	vfree(mem);
+}
+
+
+
+static int pwc_allocate_buffers(struct pwc_device *pdev)
+{
+	int i;
+	void *kbuf;
+
+	Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev);
+
+	if (pdev == NULL)
+		return -ENXIO;
+		
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("allocate_buffers(): magic failed.\n");
+		return -ENXIO;
+	}
+#endif	
+	/* Allocate Isochronuous pipe buffers */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		if (pdev->sbuf[i].data == NULL) {
+			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+			if (kbuf == NULL) {
+				Err("Failed to allocate iso buffer %d.\n", i);
+				return -ENOMEM;
+			}
+			pdev->sbuf[i].data = kbuf;
+			memset(kbuf, 0, ISO_BUFFER_SIZE);
+		}
+	}
+
+	/* Allocate frame buffer structure */
+	if (pdev->fbuf == NULL) {
+		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+		if (kbuf == NULL) {
+			Err("Failed to allocate frame buffer structure.\n");
+			return -ENOMEM;
+		}
+		pdev->fbuf = kbuf;
+		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
+	}
+	/* create frame buffers, and make circular ring */
+	for (i = 0; i < default_fbufs; i++) {
+		if (pdev->fbuf[i].data == NULL) {
+			kbuf = vmalloc(FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
+			if (kbuf == NULL) {
+				Err("Failed to allocate frame buffer %d.\n", i);
+				return -ENOMEM;
+			}
+			pdev->fbuf[i].data = kbuf;
+			memset(kbuf, 0, FRAME_SIZE);
+		}
+	}
+	
+	/* Allocate decompressor buffer space */
+	kbuf = vmalloc(FRAME_SIZE);
+	if (kbuf == NULL) {
+		Err("Failed to allocate compressed image buffer.\n");
+		return -ENOMEM;
+	}
+	memset(kbuf, 0, FRAME_SIZE);
+	pdev->decompress_buffer = kbuf;
+	
+	/* Allocate image buffer; double buffer for mmap() */
+	kbuf = rvmalloc(default_mbufs * pdev->view_max.size * 4);
+	if (kbuf == NULL) {
+		Err("Failed to allocate image buffer(s).\n");
+		return -ENOMEM;
+	}
+	pdev->image_data = kbuf;
+	for (i = 0; i < default_mbufs; i++)
+		pdev->image_ptr[i] = kbuf + (i * pdev->view_max.size * 4);
+	for (; i < MAX_IMAGES; i++)
+		pdev->image_ptr[i] = NULL;
+
+	Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
+
+	return 0;
+}
+
+static void pwc_free_buffers(struct pwc_device *pdev)
+{
+	int i;
+
+	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+
+	if (pdev == NULL)
+		return;
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("free_buffers(): magic failed.\n");
+		return;
+	}
+#endif	
+	/* Release Iso-pipe buffers */
+	Trace(TRACE_MEMORY, "Freeing ISO buffers.\n");
+	for (i = 0; i < MAX_ISO_BUFS; i++)
+		if (pdev->sbuf[i].data != NULL) {
+			kfree(pdev->sbuf[i].data);
+			pdev->sbuf[i].data = NULL;
+		}
+	/* The same for frame buffers */
+	Trace(TRACE_MEMORY, "Freeing frame buffers.\n");
+	if (pdev->fbuf != NULL) {
+		for (i = 0; i < default_fbufs; i++) {
+			if (pdev->fbuf[i].data != NULL) {
+				vfree(pdev->fbuf[i].data);
+				pdev->fbuf[i].data = NULL;
+			}
+		}
+		kfree(pdev->fbuf);
+		pdev->fbuf = NULL;
+	}
+	/* Intermediate decompression buffer */
+	Trace(TRACE_MEMORY, "Freeing decompression buffer\n");
+	if (pdev->decompress_buffer != NULL)
+		vfree(pdev->decompress_buffer);
+	pdev->decompress_buffer = NULL;
+
+	/* Release image buffers */
+	Trace(TRACE_MEMORY, "Freeing image buffers\n");
+	if (pdev->image_data != NULL)
+		rvfree(pdev->image_data, default_mbufs * pdev->view_max.size * 4);
+	pdev->image_data = NULL;
+	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+}
+
+/* The frame & image buffer mess. 
+
+   Yes, this is a mess. Well, it used to be simple, but alas...  In this
+   module, 3 buffers schemes are used to get the data from the USB bus to
+   the user program. The first scheme involves the ISO buffers (called thus
+   since they transport ISO data from the USB controller), and not really
+   interesting. Suffices to say the data from this buffer is quickly 
+   gathered in an interrupt handler (pwc_isoc_hanlder) and placed into the 
+   frame buffer.
+   
+   The frame buffer is the second scheme, and is the central element here.
+   It collects the data from a single frame from the camera (hence, the
+   name). Frames are delimited by the USB camera with a short USB packet,
+   so that's easy to detect. The frame buffers form a list that is filled
+   by the camera+USB controller and drained by the user process through 
+   either read() or mmap().
+   
+   The image buffer is the third scheme, in which frames are decompressed
+   and converted into any of the desired image formats (rgb, bgr, yuv, etc).
+   For mmap() there is more than one image buffer available.
+
+   The frame buffers provide the image buffering, in case the user process
+   is a bit slow. This introduces lag and some undesired side-effects.
+   The problem arises when the frame buffer is full. I used to drop the last 
+   frame, which makes the data in the queue stale very quickly. But dropping 
+   the frame at the head of the queue proved to be a litte bit more difficult.
+   I tried a circular linked scheme, but this introduced more problems than
+   it solved.
+
+   Because filling and draining are completely asynchronous processes, this
+   requires some fiddling with pointers and mutexes.
+   
+   Eventually, I came up with a system with 2 lists: an 'empty' frame list
+   and a 'full' frame list:
+     * Initially, all frame buffers but one are on the 'empty' list; the one
+       remaining buffer is our initial fill frame.
+     * If a frame is needed for filling, we take it from the 'empty' list, 
+       unless that list is empty, in which case we take the buffer at the 
+       head of the 'full' list.
+     * When our fill buffer has been filled, it is appended to the 'full' 
+       list.
+     * If a frame is needed by read() or mmap(), it is taken from the head of 
+       the 'full' list, handled, and then appended to the 'empty' list. If no
+       buffer is present on the 'full' list, we wait.
+   The advantage is that the buffer that is currently being decompressed/
+   converted, is on neither list, and thus not in our way (any other scheme 
+   I tried had the problem of old data lingering in the queue).
+
+   Whatever strategy you choose, it always remains a tradeoff: with more
+   frame buffers the chances of a missed frame are reduced. On the other
+   hand, on slower machines it introduces lag because the queue will 
+   always be full.
+ */
+
+/**
+  \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
+ */
+static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+{
+	int ret, flags;
+	
+	ret = 0;
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	if (pdev->fill_frame != NULL) {
+		/* append to 'full' list */
+		if (pdev->full_frames == NULL) {
+			pdev->full_frames = pdev->fill_frame;
+			pdev->full_frames_tail = pdev->full_frames;
+		}
+		else {
+			pdev->full_frames_tail->next = pdev->fill_frame;
+			pdev->full_frames_tail = pdev->fill_frame;
+		}
+	}
+	if (pdev->empty_frames != NULL) {
+		/* We have empty frames available. That's easy */
+		pdev->fill_frame = pdev->empty_frames;
+		pdev->empty_frames = pdev->empty_frames->next;	
+	}
+	else {
+		/* Hmm. Take it from the full list */
+#if PWC_DEBUG		
+		/* sanity check */
+		if (pdev->full_frames == NULL) {
+			Err("Neither empty or full frames available!\n");
+			spin_unlock_irqrestore(&pdev->ptrlock, flags);
+			return -EINVAL;
+		}
+#endif
+		pdev->fill_frame = pdev->full_frames;
+		pdev->full_frames = pdev->full_frames->next;
+		ret = 1;
+	}
+	pdev->fill_frame->next = NULL;
+#if PWC_DEBUG
+	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
+	pdev->fill_frame->sequence = pdev->sequence++;
+#endif
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+	return ret;
+}
+ 
+
+/**
+  \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. 
+  
+  If the image_used[] buffer is cleared too mmap()/VIDIOCSYNC will run into trouble.
+ */
+static void pwc_reset_buffers(struct pwc_device *pdev)
+{
+	int i, flags;
+
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	pdev->full_frames = NULL;
+	pdev->full_frames_tail = NULL;
+	for (i = 0; i < default_fbufs; i++) {
+		pdev->fbuf[i].filled = 0;
+		if (i > 0)
+			pdev->fbuf[i].next = &pdev->fbuf[i - 1];
+		else
+			pdev->fbuf->next = NULL;
+	}
+	pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
+	pdev->empty_frames_tail = pdev->fbuf;
+	pdev->read_frame = NULL;
+	pdev->fill_frame = pdev->empty_frames;
+	pdev->empty_frames = pdev->empty_frames->next;
+
+	pdev->image_read_pos = 0;
+	pdev->fill_image = 0;
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+}
+
+
+/**
+  \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
+ */
+static int pwc_handle_frame(struct pwc_device *pdev)
+{
+	int ret = 0, flags;
+	
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	/* First grab our read_frame; this is removed from all lists, so
+	   we can release the lock after this without problems */
+	if (pdev->read_frame != NULL) {
+		/* This can't theoretically happen */
+		Err("Huh? Read frame still in use?\n");
+	}
+	else {
+		if (pdev->full_frames == NULL) {
+			Err("Woops. No frames ready.\n");
+		}
+		else {
+			pdev->read_frame = pdev->full_frames;
+			pdev->full_frames = pdev->full_frames->next;
+			pdev->read_frame->next = NULL;
+		}
+
+		if (pdev->read_frame != NULL) {
+#if PWC_DEBUG
+			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
+#endif
+			/* Decompression is a lenghty process, so it's outside of the lock.
+			   This gives the isoc_handler the opportunity to fill more frames 
+			   in the mean time.
+			*/
+			spin_unlock_irqrestore(&pdev->ptrlock, flags);
+			ret = pwc_decompress(pdev);
+			spin_lock_irqsave(&pdev->ptrlock, flags);
+
+			/* We're done with read_buffer, tack it to the end of the empty buffer list */
+			if (pdev->empty_frames == NULL) {
+				pdev->empty_frames = pdev->read_frame;
+				pdev->empty_frames_tail = pdev->empty_frames;
+			}
+			else {
+				pdev->empty_frames_tail->next = pdev->read_frame;
+				pdev->empty_frames_tail = pdev->read_frame;
+			}
+			pdev->read_frame = NULL;
+		}
+	}
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+	return ret;
+}
+
+/**
+  \brief Advance pointers of image buffer (after each user request) 
+*/
+static inline void pwc_next_image(struct pwc_device *pdev)
+{
+	pdev->image_used[pdev->fill_image] = 0;
+	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+}
+
+static int pwc_set_palette(struct pwc_device *pdev, int pal)
+{
+	if (   pal == VIDEO_PALETTE_RGB24 
+	    || pal == VIDEO_PALETTE_RGB32 
+            || pal == (VIDEO_PALETTE_RGB24 | 0x80)
+            || pal == (VIDEO_PALETTE_RGB32 | 0x80)
+            || pal == VIDEO_PALETTE_YUYV
+            || pal == VIDEO_PALETTE_YUV422
+            || pal == VIDEO_PALETTE_YUV420
+            || pal == VIDEO_PALETTE_YUV420P
+#if PWC_DEBUG
+            || pal == VIDEO_PALETTE_RAW
+#endif
+	) {
+		pdev->vpalette = pal;
+		pwc_set_image_buffer_size(pdev);
+		return 0;
+	}
+	return -1;
+}
+
+
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(purb_t urb)
+{
+	struct pwc_device *pdev;
+	int i, fst, flen;
+	int awake;
+	struct pwc_frame_buf *fbuf;
+	unsigned char *fillptr, *iso_buf;
+
+	pdev = (struct pwc_device *)urb->context;
+	if (pdev == NULL) {
+		Err("isoc_handler() called with NULL device?!\n");
+		return;
+	}
+#ifdef PWC_MAGIC	
+	if (pdev->magic != PWC_MAGIC) {
+		Err("isoc_handler() called with bad magic!\n");
+		return;
+	}
+#endif
+	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n");
+		return;
+	}
+	if (urb->status != -EINPROGRESS && urb->status != 0) {
+		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d.\n", urb->status);
+		return;
+	}
+
+	fbuf = pdev->fill_frame;
+	if (fbuf == NULL) {
+		Err("pwc_isoc_handler without valid fill frame.\n");
+		if (waitqueue_active(&pdev->frameq))
+			wake_up_interruptible(&pdev->frameq);
+		if (waitqueue_active(&pdev->pollq))
+			wake_up_interruptible(&pdev->pollq);
+		return;
+	}
+	fillptr = fbuf->data + fbuf->filled;
+	awake = 0;
+
+	/* vsync: 0 = don't copy data
+	          1 = sync-hunt
+	          2 = synched 
+	 */
+	/* Compact data */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		fst  = urb->iso_frame_desc[i].status;
+		flen = urb->iso_frame_desc[i].actual_length;
+		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		if (fst == 0) {
+			if (flen > 0) { /* if valid data... */
+				if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
+					pdev->vsync = 2;
+
+					/* ...copy data to frame buffer, if possible */
+					if (flen + fbuf->filled > pdev->frame_size) {
+						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_size = %d).\n", flen, pdev->frame_size);
+						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
+						pdev->vframes_error++;
+					}
+					else {
+						memmove(fillptr, iso_buf, flen);
+						fillptr += flen;
+					}
+				}
+				fbuf->filled += flen;
+			} /* ..flen > 0 */
+
+			if (flen < pdev->vlast_packet_size) {
+				/* Shorter packet... We probably have the end of an image-frame; 
+				   wake up read() process and let select()/poll() do something.
+				   Decompression is done in user time over there. 
+				 */
+				if (pdev->vsync == 2) {
+					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
+					   frames on the USB wire after an exposure change. This conditition is 
+					   however detected  in the cam and a bit is set in the header.
+					 */
+					if (pdev->type == 730) {
+						unsigned char *ptr = (unsigned char *)fbuf->data;
+						
+						if (ptr[1] == 1 && ptr[0] & 0x10) {
+#if PWC_DEBUG
+							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
+#endif
+							pdev->drop_frames = 2;
+							pdev->vframes_error++;
+						}
+						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
+						   after a short frame; this condition is filtered out specifically. A 4 byte
+						   frame doesn't make sense anyway.
+						   So we get either this sequence: 
+						   	drop_bit set -> 4 byte frame -> short frame -> good frame
+						   Or this one:
+						   	drop_bit set -> short frame -> good frame
+						   So we drop either 3 or 2 frames in all!
+						 */
+						if (fbuf->filled == 4)
+							pdev->drop_frames++;
+					}
+
+					/* In case we were instructed to drop the frame, do so silently.
+					   The buffer pointers are not updated either (but the counters are reset below).
+					 */
+					if (pdev->drop_frames)
+						pdev->drop_frames--;
+					else {
+						/* Check for underflow first */
+						if (fbuf->filled < pdev->frame_size) {
+							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
+							pdev->vframes_error++;
+						}
+						else {
+							/* Send only once per EOF */
+							awake = 1; /* delay wake_ups */
+							
+							/* Find our next frame to fill. This will always succeed, since we
+							 * nick a frame from either empty or full list, but if we had to
+							 * take it from the full list, it means a frame got dropped.
+							 */
+							if (pwc_next_fill_frame(pdev)) {
+								pdev->vframes_dumped++;
+								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
+									if (pdev->vframes_dumped < 20)
+										Info("Dumping frame %d.\n", pdev->vframe_count);
+									if (pdev->vframes_dumped == 20)
+										Info("Dumping frame %d (last message).\n", pdev->vframe_count);
+								}
+							}
+							fbuf = pdev->fill_frame;
+						}
+					} /* !drop_frames */
+					pdev->vframe_count++;
+				}
+				fbuf->filled = 0;
+				fillptr = fbuf->data;
+				pdev->vsync = 1;
+			} /* .. flen < last_packet_size */
+			pdev->vlast_packet_size = flen;
+		} /* ..status == 0 */
+	}
+	if (awake) {
+		if (waitqueue_active(&pdev->frameq))
+			wake_up_interruptible(&pdev->frameq);
+		if (waitqueue_active(&pdev->pollq))
+			wake_up_interruptible(&pdev->pollq);
+	}
+}
+
+
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+	struct usb_device *udev;
+	purb_t urb;
+	int i, j, ret;
+
+	struct usb_interface_descriptor *idesc;
+	int cur_alt;
+
+	if (pdev == NULL)
+		return -EFAULT;
+	if (pdev->iso_init)
+		return 0;
+	pdev->vsync = 0;
+	udev = pdev->udev;
+	
+	/* Get the current alternate interface, adjust packet size */
+	if (!udev->actconfig)
+		return -EFAULT;
+	cur_alt = udev->actconfig->interface[0].act_altsetting;
+	idesc = &udev->actconfig->interface[0].altsetting[cur_alt];
+	if (!idesc)
+		return -EFAULT;
+
+	/* Search video endpoint */
+	pdev->vmax_packet_size = -1;
+	for (i = 0; i < idesc->bNumEndpoints; i++)
+		if ((idesc->endpoint[i].bEndpointAddress & 0xF) == pdev->vendpoint) {
+			pdev->vmax_packet_size = idesc->endpoint[i].wMaxPacketSize;
+			break;
+		}
+	
+	if (pdev->vmax_packet_size < 0) {
+		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+		return -ENFILE; /* Odd error, that should be noticable */
+	}
+
+	ret = 0;
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC);
+		if (urb == NULL) {
+			Err("Failed to allocate urb %d\n", i);
+			ret = -ENOMEM;
+			break;
+		}
+		pdev->sbuf[i].urb = urb;
+	}
+	if (ret) {
+		/* De-allocate in reverse order */
+		while (i >= 0) {
+			if (pdev->sbuf[i].urb != NULL)
+				usb_free_urb(pdev->sbuf[i].urb);
+			i--;
+		}
+		return ret;
+	}
+	
+	
+	/* init URB structure */	
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = pdev->sbuf[i].urb;
+
+		urb->next = pdev->sbuf[(i + 1) % MAX_ISO_BUFS].urb;
+		urb->dev = udev;
+	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+		urb->transfer_flags = USB_ISO_ASAP;
+	        urb->transfer_buffer = pdev->sbuf[i].data;
+	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+	        urb->complete = pwc_isoc_handler;
+	        urb->context = pdev;
+		urb->start_frame = 0;
+		urb->number_of_packets = ISO_FRAMES_PER_DESC;
+		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+			urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
+		}
+	}
+
+	/* link */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		ret = usb_submit_urb(pdev->sbuf[i].urb);
+		if (ret)
+			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+	}
+
+	/* data should stream in now */
+	pdev->iso_init = 1;
+	return 0;
+}
+
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+	int i;
+	
+	if (pdev == NULL)
+		return;
+	if (!pdev->iso_init)
+		return;
+	/* Stop camera, but only if we are sure the camera is still there */
+	if (!pdev->unplugged)
+		usb_set_interface(pdev->udev, 0, 0);
+	for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
+		pdev->sbuf[i].urb->next = NULL;
+		usb_unlink_urb(pdev->sbuf[i].urb);
+		usb_free_urb(pdev->sbuf[i].urb);
+		pdev->sbuf[i].urb = NULL;
+	}
+	pdev->iso_init = 0;
+}
+
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
+{
+	int ret;
+
+	/* Stop isoc stuff */
+	pwc_isoc_cleanup(pdev);
+	/* Reset parameters */
+	pwc_reset_buffers(pdev);
+	/* Try to set video mode... */
+	ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+	if (ret) /* That failed... restore old mode (we know that worked) */
+		ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+	else /* Set (new) alternate interface */
+		ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+	if (!ret)
+		ret = pwc_isoc_init(pdev);
+	pdev->drop_frames = 1; /* try to avoid garbage during switch */
+	return ret;
+}
+
+
+static inline void set_mem_leak(void *ptr)
+{
+	down(&mem_lock);
+	if (mem_leak != NULL)
+		Err("Memleak: overwriting mem_leak pointer!\n");
+	Trace(TRACE_MEMORY, "Setting mem_leak to 0x%p.\n", ptr);
+	mem_leak = ptr;
+	up(&mem_lock);
+}
+
+static inline void free_mem_leak(void)
+{
+	down(&mem_lock);
+	if (mem_leak != NULL) {
+		Trace(TRACE_MEMORY, "Freeing mem_leak ptr 0x%p.\n", mem_leak);
+		kfree(mem_leak);
+		mem_leak = NULL;
+	}
+	up(&mem_lock);
+}
+
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static int pwc_video_open(struct video_device *vdev, int mode)
+{
+	int i;
+	struct pwc_device *pdev;
+
+	Trace(TRACE_OPEN, "video_open called(0x%p, 0%o).\n", vdev, mode);
+	
+	if (vdev == NULL) {
+		Err("video_open() called with NULL structure?\n");
+		return -EFAULT;
+	}
+	pdev = (struct pwc_device *)vdev->priv;
+	if (pdev == NULL) {
+		Err("video_open() called with NULL pwc_device.\n");
+		return -EFAULT;
+	}
+	
+	MOD_INC_USE_COUNT;
+	down(&pdev->modlock);
+	if (!pdev->usb_init) {
+		Trace(TRACE_OPEN, "Doing first time initialization.\n");
+		/* Reset camera */
+		if (usb_set_interface(pdev->udev, 0, 0))
+			Info("Failed to set alternate interface to 0.\n");
+		pdev->usb_init = 1;
+	}
+	else {
+		/* Turn on camera */
+		if (power_save) {
+			i = pwc_camera_power(pdev, 1);
+			if (i < 0)
+				Info("Failed to restore power to the camera! (%d)\n", i);
+		}
+	}
+
+	/* So far, so good. Allocate memory. */
+	i = pwc_allocate_buffers(pdev);
+	if (i < 0) {
+		Trace(TRACE_OPEN, "Failed to allocate memory.\n");
+		MOD_DEC_USE_COUNT;
+		up(&pdev->modlock);
+		return i;
+	}
+	
+	/* Reset buffers & parameters */
+	pwc_reset_buffers(pdev);
+	for (i = 0; i < default_mbufs; i++)
+		pdev->image_used[i] = 0;
+	pdev->vframe_count = 0;
+	pdev->vframes_dumped = 0;
+	pdev->vframes_error = 0;
+	pdev->vpalette = default_palette;
+#if PWC_DEBUG	
+	pdev->sequence = 0;
+#endif
+
+	/* Find our decompressor, if any */
+	pdev->decompressor = pwc_find_decompressor(pdev->type);
+#if PWC_DEBUG	
+	Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor);
+#endif
+
+	/* Set some defaults */
+	pdev->vsnapshot = 0;
+	if (pdev->type == 730 || pdev->type == 740)
+		pdev->vsize = PSZ_QSIF;
+	else
+		pdev->vsize = PSZ_QCIF;
+	pdev->vframes = 10;
+
+	/* Start iso pipe for video; first try user-supplied size/fps, if
+	   that fails try QCIF/10 or QSIF/10 (a reasonable default), 
+	   then give up 
+	 */
+	i = pwc_set_video_mode(pdev, pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y, default_fps, pdev->vcompression, 0);
+	if (i)	{
+		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
+		if (pdev->type == 730 || pdev->type == 740) 
+			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+		else
+			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+	}
+	if (i) {
+		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+		MOD_DEC_USE_COUNT;
+		up(&pdev->modlock);
+		return i;
+	}
+	i = usb_set_interface(pdev->udev, 0, pdev->valternate);
+	if (i) {
+		Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
+		MOD_DEC_USE_COUNT;
+		up(&pdev->modlock);
+		return -EINVAL;
+	}
+	i = pwc_isoc_init(pdev);
+	if (i) {
+		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+		MOD_DEC_USE_COUNT;
+		up(&pdev->modlock);
+		return i;
+	}
+
+	pdev->vopen++;
+	/* lock decompressor; this has a small race condition, since we 
+	   could in theory unload pwcx.o between pwc_find_decompressor()
+	   above and this call. I doubt it's ever going to be a problem.
+	 */
+	if (pdev->decompressor != NULL)
+		pdev->decompressor->lock();
+	up(&pdev->modlock);
+	Trace(TRACE_OPEN, "video_open() returning 0.\n");
+	return 0;
+}
+
+/* Note that all cleanup is done in the reverse order as in _open */
+static void pwc_video_close(struct video_device *vdev)
+{
+	struct pwc_device *pdev;
+	int i;
+
+	Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev);
+	if (vdev == NULL) {
+		Err("video_close() called with NULL structure?\n");
+		return;
+	}
+	pdev = (struct pwc_device *)vdev->priv;
+	if (pdev == NULL) {
+		Err("video_close() called with NULL pwc_device.\n");
+		return;
+	}
+	if (pdev->vopen == 0)
+		Info("video_close() called on closed device?\n");
+
+	/* Free isoc URBs */
+	pwc_isoc_cleanup(pdev);
+
+	/* Dump statistics, but only if a reasonable amount of frames were
+	   processed (to prevent endless log-entries in case of snap-shot
+	   programs) 
+	 */
+	if (pdev->vframe_count > 20)
+		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+
+	if (pdev->unplugged) {
+		/* The device was unplugged or some other error occured */
+		/* We unregister the video_device */
+		Trace(TRACE_OPEN, "Delayed video device unregistered.\n");
+		video_unregister_device(pdev->vdev);
+	}
+	else {
+		/* Normal close: stop isochronuous and interrupt endpoint */
+		Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
+		usb_set_interface(pdev->udev, 0, 0);
+
+		/* Turn off LED by powering down camera */
+		if (power_save) {
+			i = pwc_camera_power(pdev, 0);
+			if (i < 0) 
+				Err("Failed to power down camera (%d)\n", i);
+		}
+	}
+
+	pdev->vopen = 0;
+	pwc_free_buffers(pdev);
+	if (pdev->decompressor != NULL) {
+		pdev->decompressor->exit(&pdev->decompress_data);
+		pdev->decompressor->unlock();
+	}
+	pdev->decompressor = NULL;
+
+	/* wake up _disconnect() routine */
+	if (pdev->unplugged)
+		wake_up(&pdev->remove_ok);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock)
+{
+	struct pwc_device *pdev;
+
+	Trace(TRACE_READ, "video_read(0x%p, %p, %ld, %d) called.\n", vdev, buf, count, noblock);
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+	if (pdev->unplugged) {
+		Debug("pwc_video_read: Device got unplugged (1).\n");
+		return -EPIPE; /* unplugged device! */
+	}
+
+	/* In case we're doing partial reads, we don't have to wait for a frame */
+	if (pdev->image_read_pos == 0) {
+		/* See if a frame is completed, process that */
+		if (noblock && pdev->full_frames == NULL)
+			return -EAGAIN;
+		while (pdev->full_frames == NULL) {
+			interruptible_sleep_on(&pdev->frameq);
+			if (pdev->unplugged) {
+				Debug("pwc_video_read: Device got unplugged (2).\n");
+				return -EPIPE;
+			}
+			if (signal_pending(current))
+				return -EINTR;
+		}
+ 
+		/* Decompress & convert now */
+		if (pwc_handle_frame(pdev))
+			return -EFAULT;
+	}
+
+	Trace(TRACE_READ, "Copying data to user space.\n");
+	/* copy bytes to user space; we allow for partial reads */
+	if (count + pdev->image_read_pos > pdev->view.size)
+		count = pdev->view.size - pdev->image_read_pos;
+	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+		return -EFAULT;
+	pdev->image_read_pos += count;
+	if (pdev->image_read_pos >= pdev->view.size) { /* All data has been read */
+		pdev->image_read_pos = 0;
+		pwc_next_image(pdev);
+	}
+	return count;
+}
+
+
+static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock)
+{
+	return -EINVAL;   
+}
+
+static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait)
+{
+	struct pwc_device *pdev;
+	
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+	
+	poll_wait(file, &pdev->pollq, wait);
+	if (pdev->unplugged) {
+		Debug("pwc_video_poll: Device got unplugged.\n");
+		return POLLERR;
+	}		
+	if (pdev->full_frames != NULL) /* we have frames waiting */
+		return (POLLIN | POLLRDNORM);
+
+	return 0;
+}
+        
+static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+	struct pwc_device *pdev;
+	
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+	switch (cmd) {
+		/* Query cabapilities */
+		case VIDIOCGCAP: 
+		{
+			struct video_capability caps;
+
+			strcpy(caps.name, vdev->name);
+			caps.type = VID_TYPE_CAPTURE;
+			caps.channels = 1;
+			caps.audios = 1;
+			caps.minwidth  = pdev->view_min.x;
+			caps.minheight = pdev->view_min.y;
+			caps.maxwidth  = pdev->view_max.x;
+			caps.maxheight = pdev->view_max.y;
+			if (copy_to_user(arg, &caps, sizeof(caps)))
+				return -EFAULT;
+			break;
+		}
+
+		/* Channel functions (simulate 1 channel) */
+		case VIDIOCGCHAN:
+		{
+			struct video_channel v;
+
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.channel != 0)
+				return -EINVAL;
+
+			v.flags = 0;
+			v.tuners = 0;
+			v.type = VIDEO_TYPE_CAMERA;
+			strcpy(v.name, "Webcam");
+
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+
+			return 0;
+		}
+
+		case VIDIOCSCHAN:
+		{	
+			/* The spec says the argument is an integer, but
+			   the bttv driver uses a video_channel arg, which
+			   makes sense becasue it also has the norm flag.
+			 */
+			struct video_channel v;
+
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+
+			if (v.channel != 0)
+				return -EINVAL;
+
+			return 0;
+		}
+
+
+		/* Picture functions; contrast etc. */
+		case VIDIOCGPICT:
+		{
+			struct video_picture p;
+			int val;
+
+			p.colour = 0x8000;
+			p.hue = 0x8000;
+			val = pwc_get_brightness(pdev);
+			if (val >= 0)
+				p.brightness = val;
+			else
+				p.brightness = 0xffff;
+			val = pwc_get_contrast(pdev);
+			if (val >= 0)
+				p.contrast = val;
+			else
+				p.contrast = 0xffff;
+			/* Gamma, Whiteness, what's the difference? :) */
+			val = pwc_get_gamma(pdev);
+			if (val >= 0)
+				p.whiteness = val;
+			else
+				p.whiteness = 0xffff;
+			val = pwc_get_saturation(pdev);
+			if (val >= 0)
+				p.colour = val;
+			else
+				p.colour = 0xffff;
+			p.depth = 24;
+			p.palette = pdev->vpalette;
+			p.hue = 0xFFFF; /* N/A */
+
+			if (copy_to_user(arg, &p, sizeof(p)))
+				return -EFAULT;
+			break;
+		}
+		
+		case VIDIOCSPICT:
+		{
+			struct video_picture p;
+
+			if (copy_from_user(&p, arg, sizeof(p)))
+				return -EFAULT;
+
+			pwc_set_brightness(pdev, p.brightness);
+			pwc_set_contrast(pdev, p.contrast);
+			pwc_set_gamma(pdev, p.whiteness);
+			pwc_set_saturation(pdev, p.colour);
+			if (p.palette && p.palette != pdev->vpalette) {
+				if (pwc_set_palette(pdev, p.palette) < 0)
+					return -EINVAL;
+			}
+			break;
+		}
+
+		/* Window/size parameters */		
+		case VIDIOCGWIN:
+		{
+			struct video_window vw;
+			
+			vw.x = 0;
+			vw.y = 0;
+			vw.width = pdev->view.x;
+			vw.height = pdev->view.y;
+			vw.chromakey = 0;
+			vw.flags = (pdev->vframes << PWC_FPS_SHIFT) | 
+			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+			
+			if (copy_to_user(arg, &vw, sizeof(vw)))
+				return -EFAULT;			
+			break;
+		}
+		
+		case VIDIOCSWIN:
+		{
+			struct video_window vw;
+			int fps, snapshot, ret;
+		
+			if (copy_from_user(&vw, arg, sizeof(vw)))
+				return -EFAULT;
+
+/*
+			size = pwc_decode_size(pdev, vw.width, vw.height);
+			if (size < 0)
+				return -EINVAL;
+*/				
+			fps = (vw.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+			snapshot = vw.flags & PWC_FPS_SNAPSHOT;
+			if (fps == 0)
+				fps = pdev->vframes;
+			if (pdev->view.x == vw.width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+				return 0;
+			ret = pwc_try_video_mode(pdev, vw.width, vw.height, fps, pdev->vcompression, snapshot);
+			if (ret)
+				return ret;
+			break;		
+		}
+		
+		/* We don't have overlay support (yet) */
+		case VIDIOCGFBUF:
+		{
+			struct video_buffer vb;
+			
+			vb.base = NULL;
+			vb.height = 0;
+			vb.width = 0;
+			vb.depth = 0;
+			vb.bytesperline = 0;
+			
+			if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
+				return -EFAULT;
+			break;
+		}
+
+		/* mmap() functions */
+		case VIDIOCGMBUF:
+		{
+			/* Tell the user program how much memory is needed for a mmap() */
+			struct video_mbuf vm;
+			int i;
+
+			memset(&vm, 0, sizeof(vm));
+			vm.size = default_mbufs * pdev->view_max.size * 4;
+			vm.frames = default_mbufs; /* double buffering should be enough */
+			for (i = 0; i < default_mbufs; i++)
+				vm.offsets[i] = i * pdev->view_max.size * 4;
+
+			if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+				return -EFAULT;
+			break;
+		}
+
+		case VIDIOCMCAPTURE:
+		{
+			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+			struct video_mmap vm;
+
+			if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
+				return -EFAULT;
+			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm.width, vm.height, vm.frame, vm.format);
+			if (vm.frame < 0 || vm.frame >= default_mbufs)
+				return -EINVAL;
+
+			/* xawtv is nasty. It probes the available palettes
+			   by setting a very small image size and trying
+			   various palettes... The driver doesn't support
+			   such small images, so I'm working around it.
+			 */
+			if (vm.format && vm.format != pdev->vpalette)
+				if (pwc_set_palette(pdev, vm.format) < 0)
+					return -EINVAL;
+			 
+			if ((vm.width != pdev->view.x || vm.height != pdev->view.y) &&
+			    (vm.width >= pdev->view_min.x && vm.height >= pdev->view_min.y)) {
+				int ret;
+				
+				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+/*
+				size = pwc_decode_size(pdev, vm.width, vm.height);
+				if (size < 0)
+					return -EINVAL;
+*/					
+				ret = pwc_try_video_mode(pdev, vm.width, vm.height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+				if (ret)
+					return ret;
+			} /* ... size mismatch */
+
+			/* FIXME: should we lock here? */
+			if (pdev->image_used[vm.frame])
+				return -EBUSY;	/* buffer wasn't available. Bummer */
+			pdev->image_used[vm.frame] = 1;
+
+			/* Okay, we're done here. In the SYNC call we wait until a 
+			   frame comes available, then expand image into the given 
+			   buffer.
+			   In contrast to the CPiA cam the Philips cams deliver a 
+			   constant stream, almost like a grabber card. Also,
+			   we have separate buffers for the rawdata and the image,
+			   meaning we can nearly always expand into the requested buffer.
+			 */
+			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
+			break;
+		}
+
+		case VIDIOCSYNC:
+		{
+			/* The doc says: "Whenever a buffer is used it should
+			   call VIDIOCSYNC to free this frame up and continue."
+			   
+			   The only odd thing about this whole procedure is 
+			   that MCAPTURE flags the buffer as "in use", and
+			   SYNC immediately unmarks it, while it isn't 
+			   after SYNC that you know that the buffer actually
+			   got filled! So you better not start a CAPTURE in
+			   the same frame immediately (use double buffering). 
+			   This is not a problem for this cam, since it has 
+			   extra intermediate buffers, but a hardware 
+			   grabber card will then overwrite the buffer 
+			   you're working on.
+			 */
+			int mbuf, ret;
+
+			if (copy_from_user((void *)&mbuf, arg, sizeof(int)))
+				return -EFAULT;
+
+			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", mbuf);
+
+			if (mbuf < 0 || mbuf >= default_mbufs)
+				return -EINVAL;
+			/* check if this buffer was requested anyway */
+			if (pdev->image_used[mbuf] == 0)
+				return -EINVAL;
+
+			/* We (re)use the frame-waitqueue here. That may
+			   conflict with read(), but any programmer that uses
+			   read() and mmap() simultaneously should be given 
+			   a job at Micro$oft. As janitor.
+			 */
+			while (pdev->full_frames == NULL) {
+				interruptible_sleep_on(&pdev->frameq);
+				if (pdev->unplugged) {
+					Debug("VIDIOCSYNC: Device got unplugged.\n");
+					return -EPIPE;
+				}
+				if (signal_pending(current))
+					return -EINTR;
+			}
+			/* The frame is ready. Expand in the image buffer 
+			   requested by the user. I don't care if you 
+			   mmap() 5 buffers and request data in this order: 
+			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+			   Grabber hardware may not be so forgiving.
+			 */
+			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
+			pdev->fill_image = mbuf; /* tell in which buffer we want the image to be expanded */
+			/* Decompress, etc */
+			ret = pwc_handle_frame(pdev);
+			pdev->image_used[mbuf] = 0;
+			if (ret)
+				return -EFAULT;
+			break;
+		}
+
+		default:
+			return pwc_ioctl(pdev, cmd, arg);
+	} /* ..switch */
+	return 0;
+}	
+
+static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size)
+{
+	struct pwc_device *pdev;
+	unsigned long start = (unsigned long)adr;
+	unsigned long page, pos;
+	
+	Trace(TRACE_READ, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size);
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+	pos = (unsigned long)pdev->image_data;
+	while (size > 0) {
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+}
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)
+#else
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum)
+#endif
+{
+	struct pwc_device *pdev = NULL;
+	struct video_device *vdev;
+	struct usb_config_descriptor *config;
+	struct usb_interface *iface;
+	int vendor_id, product_id, type_id;
+	int i;
+
+	free_mem_leak();
+	
+	/* Check if we can handle this device */
+	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum);
+
+	/* the interfaces are probed one by one. We are only interested in the
+	   video interface (0) now.
+	   Interface 1 is the Audio Control, and interface 2 Audio itself.
+	 */
+	if (ifnum > 0) 
+		return NULL;
+
+	vendor_id = udev->descriptor.idVendor;
+	product_id = udev->descriptor.idProduct;
+	
+	if (vendor_id != 0x0471 && vendor_id != 0x069A)
+		return NULL; /* Not Philips or Askey, for sure. */
+
+	if (vendor_id == 0x0471) {
+		switch (product_id) {
+		case 0x0302:
+			Info("Philips PCA645VC USB webcam detected.\n");
+			type_id = 645;
+			break;
+		case 0x0303:
+			Info("Philips PCA646VC USB webcam detected.\n");
+			type_id = 646;
+			break;
+		case 0x0304:
+			Info("Askey VC010 type 2 USB webcam detected.\n");
+			type_id = 646;
+			break;
+		case 0x0307:
+			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+			type_id = 675;
+			break;
+		case 0x0308:
+			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+			type_id = 680;
+			break;
+		case 0x030C:
+			Info("Philips PCVC690K (Vesta Scanner) USB webcam detected.\n");
+			type_id = 690;
+			break;
+		case 0x0310:
+			Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
+			type_id = 730;
+			break;
+		case 0x0311:
+			Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
+			type_id = 740;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	if (vendor_id == 0x069A) {
+		switch(product_id) {
+		case 0x0001:
+			Info("Askey VC010 type 1 USB webcam detected.\n");
+			type_id = 645;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	if (udev->descriptor.bNumConfigurations > 1)
+		Info("Warning: more than 1 configuration available.\n");
+
+	config = udev->actconfig;
+	iface = &config->interface[0];
+
+	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
+	if (pdev == NULL) {
+		Err("Oops, could not allocate memory for pwc_device.\n");
+		return NULL;
+	}
+	memset(pdev, 0, sizeof(struct pwc_device));
+	pdev->type = type_id;
+	pwc_construct(pdev);
+
+	init_MUTEX(&pdev->modlock);
+	pdev->ptrlock = SPIN_LOCK_UNLOCKED;
+
+	pdev->udev = udev;
+	init_waitqueue_head(&pdev->frameq);
+	init_waitqueue_head(&pdev->pollq);
+	init_waitqueue_head(&pdev->remove_ok);
+	pdev->vcompression = pwc_preferred_compression;
+
+	/* Now hook it up to the video subsystem */
+	vdev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+	if (vdev == NULL) {
+		Err("Oops, could not allocate memory for video_device.\n");
+		return NULL;
+	}
+	memcpy(vdev, &pwc_template, sizeof(pwc_template));
+	sprintf(vdev->name, "Philips %d webcam", pdev->type);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
+	SET_MODULE_OWNER(vdev);
+#endif	
+	pdev->vdev = vdev;
+	vdev->priv = pdev;
+
+	pdev->release = udev->descriptor.bcdDevice;
+	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
+	i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr);
+	if (i < 0) {
+		Err("Failed to register as video device (%d).\n", i);
+		return NULL;
+	}
+	else {
+		Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev);
+		Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F);
+	}
+
+#if 0
+	/* Shut down camera now (some people like the LED off) */
+	if (power_save) {
+		Trace(TRACE_PROBE, "Powering down camera");
+		i = pwc_camera_power(pdev, 0);
+		if (i < 0)
+			Info("Failed to power-down the camera (%d)\n", i);
+	}
+#endif
+
+	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+	return pdev;
+}
+
+/* The user janked out the cable... */
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
+{
+	struct pwc_device *pdev;
+
+	free_mem_leak();
+
+	pdev = (struct pwc_device *)ptr;
+	if (pdev == NULL) {
+		Err("pwc_disconnect() Called without private pointer.\n");
+		return;
+	}
+	if (pdev->udev == NULL) {
+		Err("pwc_disconnect() already called for %p\n", pdev);
+		return;
+	}
+	if (pdev->udev != udev) {
+		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
+		return;
+	}
+#ifdef PWC_MAGIC	
+	if (pdev->magic != PWC_MAGIC) {
+		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
+		return;
+	}
+#endif	
+	
+	pdev->unplugged = 1;
+	if (pdev->vdev != NULL) {
+		if (pdev->vopen) {
+			Info("Disconnected while device/video is open!\n");
+			
+			/* Wake up any processes that might be waiting for
+			   a frame, let them return an error condition
+			 */
+			wake_up(&pdev->frameq);
+			wake_up(&pdev->pollq);
+			
+			/* Wait until we get a 'go' from _close(). This
+			   had a gigantic race condition, since we kfree()
+			   stuff here, but we have to wait until close() 
+			   is finished. */
+			   
+			Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
+			sleep_on(&pdev->remove_ok);
+			Trace(TRACE_PROBE, "Done sleeping.\n");
+			set_mem_leak(pdev->vdev);
+			pdev->vdev = NULL;
+		}
+		else {
+			/* Normal disconnect; remove from available devices */
+			Trace(TRACE_PROBE, "Unregistering video device normally.\n");
+			video_unregister_device(pdev->vdev); 
+			kfree(pdev->vdev);
+			pdev->vdev = NULL;
+		}
+	}
+	pdev->udev = NULL;
+	kfree(pdev);
+}
+
+
+
+/* 
+ * Initialization code & module stuff 
+ */
+
+static char *size = NULL;
+static int fps = 0;
+static char *palette = NULL;
+static int fbufs = 0;
+static int mbufs = 0;
+static int trace = -1;
+static int compression = -1;
+
+MODULE_PARM(video_nr, "i");
+MODULE_PARM(size, "s");
+MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
+MODULE_PARM(fps, "i");
+MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
+MODULE_PARM(palette, "s");
+MODULE_PARM_DESC(palette, "Initial colour format of images. One of rgb24, bgr24, rgb32, bgr32, yuyv, yuv420, yuv420p");
+MODULE_PARM(fbufs, "i");
+MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
+MODULE_PARM(mbufs, "i");
+MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
+MODULE_PARM(trace, "i");
+MODULE_PARM_DESC(trace, "For debugging purposes");
+MODULE_PARM(power_save, "i");
+MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
+MODULE_PARM(compression, "i");
+MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
+
+MODULE_DESCRIPTION("Philips USB webcam driver");
+MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
+
+static int __init usb_pwc_init(void)
+{
+	int s;
+	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+
+	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740 webcam module version " PWC_VERSION " loaded.\n");
+	Info("Also supports Askey VC010 cam.\n");
+
+	if (fps) {
+		if (fps < 5 || fps > 30) {
+			Err("Framerate out of bounds (5-30).\n");
+			return -EINVAL;
+		}
+		default_fps = fps;
+		Info("Default framerate set to %d.\n", default_fps);
+	}
+	
+	if (size) {
+		/* string; try matching with array */
+		for (s = 0; s < PSZ_MAX; s++) {
+			if (!strcmp(sizenames[s], size)) { /* Found! */
+				default_size = s;
+				break;
+			}
+		}
+		if (s == PSZ_MAX) {
+			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+			return -EINVAL;
+		}
+		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+	}
+	if (palette) {
+		/* Determine default palette */
+		if (!strcmp(palette, "bgr24"))
+			default_palette = VIDEO_PALETTE_RGB24;
+		else if (!strcmp(palette, "rgb24"))
+			default_palette = VIDEO_PALETTE_RGB24 | 0x80;
+		else if (!strcmp(palette, "bgr32"))
+			default_palette = VIDEO_PALETTE_RGB32;
+		else if (!strcmp(palette, "rgb32"))
+			default_palette = VIDEO_PALETTE_RGB32 | 0x80;
+		else if (!strcmp(palette, "yuyv"))
+			default_palette = VIDEO_PALETTE_YUYV;
+		else if (!strcmp(palette, "yuv420"))
+			default_palette = VIDEO_PALETTE_YUV420;
+		else if (!strcmp(palette, "yuv420p"))
+			default_palette = VIDEO_PALETTE_YUV420P;
+		else {
+			Err("Palette not recognized: try palette=[bgr24 | rgb24 | bgr32 | rgb32 | yuyv | yuv420 | yuv420p].\n");
+			return -EINVAL;
+		}
+		Info("Default palette set to %d.\n", default_palette);
+	}
+	if (mbufs) {
+		if (mbufs < 1 || mbufs > MAX_IMAGES) {
+			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+			return -EINVAL;
+		}
+		default_mbufs = mbufs;
+		Info("Number of image buffers set to %d.\n", default_mbufs);
+	}
+	if (fbufs) {
+		if (fbufs < 2 || fbufs > MAX_FRAMES) {
+			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+			return -EINVAL;
+		}
+		default_fbufs = fbufs;
+		Info("Number of frame buffers set to %d.\n", default_fbufs);
+	}
+	if (trace >= 0) {
+		Info("Trace options: 0x%04x\n", trace);
+		pwc_trace = trace;
+	}
+	if (compression >= 0) {
+		if (compression > 3) {
+			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+			return -EINVAL;
+		}
+		pwc_preferred_compression = compression;
+		Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+	}
+	if (power_save)
+		Info("Enabling power save on open/close.\n");
+
+	init_MUTEX(&mem_lock);
+ 	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+	return usb_register(&pwc_driver);
+}
+
+static void __exit usb_pwc_exit(void)
+{
+	free_mem_leak();
+	Trace(TRACE_MODULE, "Deregistering driver.\n");
+	usb_deregister(&pwc_driver);
+	Info("Philips webcam module removed.\n");
+}
+
+module_init(usb_pwc_init);
+module_exit(usb_pwc_exit);
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc-ioctl.h linux/drivers/usb/pwc-ioctl.h
--- v2.4.4/linux/drivers/usb/pwc-ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc-ioctl.h	Tue May 22 10:25:36 2001
@@ -0,0 +1,75 @@
+/* (C) 2001 Nemosoft Unv.    webcam@smcc.demon.nl
+   
+   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
+*/
+
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API. 
+   
+   The #define names are built up like follows:
+   VIDIOC		VIDeo IOCtl prefix
+         PWC		Philps WebCam
+            G           optional: Get
+            S           optional: Set
+             ... 	the function
+ */
+
+
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour 
+   balance controls.
+ */
+#define PWC_FPS_SHIFT		16
+#define PWC_FPS_MASK		0x00FF0000
+#define PWC_FPS_FRMASK		0x003F0000
+#define PWC_FPS_SNAPSHOT	0x00400000
+
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER		_IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER		_IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY	_IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC		_IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC		_IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc-misc.c linux/drivers/usb/pwc-misc.c
--- v2.4.4/linux/drivers/usb/pwc-misc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc-misc.c	Tue May 22 10:25:36 2001
@@ -0,0 +1,101 @@
+/* Linux driver for Philips webcam 
+   Various miscellaneous functions and tables.
+   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/  
+
+#include <linux/slab.h>
+
+#include "pwc.h"
+
+struct pwc_coord pwc_image_sizes[PSZ_MAX] = 
+{
+	{ 128,  96, 0 },
+	{ 160, 120, 0 },
+	{ 176, 144, 0 },
+	{ 320, 240, 0 },
+	{ 352, 288, 0 },
+	{ 640, 480, 0 },
+};
+
+/* x,y -> PSZ_ */
+int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+{
+	int i, find;
+
+	/* Make sure we don't go beyond our max size */
+	if (width > pdev->view_max.x || height > pdev->view_max.y)
+		return -1;
+	/* Find the largest size supported by the camera that fits into the
+	   requested size. 
+	 */
+	find = -1;
+	for (i = 0; i < PSZ_MAX; i++) {
+		if (pdev->image_mask & (1 << i)) {
+			if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
+				find = i;
+		}
+	}
+	return find;
+}
+
+/* initialize variables depending on type */
+void pwc_construct(struct pwc_device *pdev)
+{
+	switch(pdev->type) {
+	case 645:
+	case 646:
+		pdev->view_min.x = 128;
+		pdev->view_min.y =  96;
+		pdev->view_max.x = 352;
+		pdev->view_max.y = 288;
+		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+		pdev->vcinterface = 2;
+		pdev->vendpoint = 4;
+		pdev->frame_header_size = 0;
+		pdev->frame_trailer_size = 0;
+		break;
+	case 675:
+	case 680:
+	case 690:
+		pdev->view_min.x = 128;
+		pdev->view_min.y =  96;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 4;
+		pdev->frame_header_size = 0;
+		pdev->frame_trailer_size = 0;
+		break;
+	case 730:
+	case 740:
+		pdev->view_min.x = 160;
+		pdev->view_min.y = 120;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 5;
+		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+		break;
+	}
+	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
+	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
+}
+
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc-uncompress.c linux/drivers/usb/pwc-uncompress.c
--- v2.4.4/linux/drivers/usb/pwc-uncompress.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc-uncompress.c	Tue May 22 10:25:36 2001
@@ -0,0 +1,220 @@
+/* Linux driver for Philips webcam 
+   Decompression frontend.
+   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   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
+*/
+/*
+   This is where the decompression routines register and unregister 
+   themselves. It also has a decompressor wrapper function.
+*/
+
+#include "ccvt.h"
+#include "vcvt.h"
+#include "pwc.h"
+#include "pwc-uncompress.h"
+
+
+/* This contains a list of all registered decompressors */
+LIST_HEAD(pwc_decompressor_list);
+
+/* Should the pwc_decompress structure ever change, we increase the 
+   version number so that we don't get nasty surprises, or can 
+   dynamicly adjust our structure.
+ */
+const int pwc_decompressor_version = PWC_MAJOR;
+
+/* Add decompressor to list, ignoring duplicates */
+void pwc_register_decompressor(struct pwc_decompressor *pwcd)
+{
+	if (pwc_find_decompressor(pwcd->type) == NULL) {
+		Debug("Adding decompressor for model %d.\n", pwcd->type);
+		list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list);
+	}
+}
+
+/* Remove decompressor from list */
+void pwc_unregister_decompressor(int type)
+{
+	struct pwc_decompressor *find;
+	
+	find = pwc_find_decompressor(type);
+	if (find != NULL) {
+		Debug("Removing decompressor for model %d.\n", type);
+		list_del(&find->pwcd_list);
+	}
+}
+
+/* Find decompressor in list */
+struct pwc_decompressor *pwc_find_decompressor(int type)
+{
+	struct list_head *tmp;
+	struct pwc_decompressor *pwcd;
+
+	list_for_each(tmp, &pwc_decompressor_list) {
+		pwcd  = list_entry(tmp, struct pwc_decompressor, pwcd_list);
+		if (pwcd->type == type)
+			return pwcd;
+	}
+	return NULL;
+}
+
+
+
+int pwc_decompress(struct pwc_device *pdev)
+{
+	struct pwc_frame_buf *fbuf;
+	int n, l, c, w;
+	void *yuv, *image, *dst;
+	
+	if (pdev == NULL)
+		return -EFAULT;
+#if defined(__KERNEL__) && defined(PWC_MAGIC)
+	if (pdev->magic != PWC_MAGIC) {
+		Err("pwc_decompress(): magic failed.\n");
+		return -EFAULT;
+	}
+#endif
+
+	fbuf = pdev->read_frame;
+	if (fbuf == NULL)
+		return -EFAULT;
+	image = pdev->image_ptr[pdev->fill_image];
+	if (!image)
+		return -EFAULT;
+
+#if PWC_DEBUG
+	/* This is a quickie */
+	if (pdev->vpalette == VIDEO_PALETTE_RAW) {
+		memcpy(image, fbuf->data, pdev->frame_size);
+		return 0;
+	}
+#endif
+
+	/* Compressed formats are decompressed in decompress_buffer, then 
+	 * transformed into the desired format 
+	 */
+	yuv = pdev->decompress_buffer;
+	n = 0;
+	if (pdev->vbandlength == 0) { /* uncompressed */
+		yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
+	}
+	else {
+		if (pdev->decompressor)
+			n = pdev->decompressor->decompress(pdev->decompress_data, pdev->image.x, pdev->image.y, pdev->vbandlength, yuv, fbuf->data + pdev->frame_header_size, 0);
+		else
+			n = -ENXIO; /* No such device or address: missing decompressor */
+	}
+	if (n < 0) {
+		Err("Error in decompression engine: %d\n", n);
+		return n;
+	}
+
+	/* At this point 'yuv' always points to the uncompressed, non-scaled YUV420I data */
+	if (pdev->image.x == pdev->view.x && pdev->image.y == pdev->view.y) {
+		/* Sizes matches; make it quick */
+		switch(pdev->vpalette) {
+		case VIDEO_PALETTE_RGB24 | 0x80:
+			ccvt_420i_rgb24(pdev->image.x, pdev->image.y, yuv, image);
+			break;
+		case VIDEO_PALETTE_RGB24:
+			ccvt_420i_bgr24(pdev->image.x, pdev->image.y, yuv, image);
+			break;
+		case VIDEO_PALETTE_RGB32 | 0x80:
+			ccvt_420i_rgb32(pdev->image.x, pdev->image.y, yuv, image);
+			break;
+		case VIDEO_PALETTE_RGB32:
+			ccvt_420i_bgr32(pdev->image.x, pdev->image.y, yuv, image);
+			break;
+		case VIDEO_PALETTE_YUYV:
+		case VIDEO_PALETTE_YUV422:
+			ccvt_420i_yuyv(pdev->image.x, pdev->image.y, yuv, image); 
+			break;
+		case VIDEO_PALETTE_YUV420:
+			memcpy(image, yuv, pdev->image.size);
+			break;
+		case VIDEO_PALETTE_YUV420P:
+			n = pdev->image.x * pdev->image.y;
+			ccvt_420i_420p(pdev->image.x, pdev->image.y, yuv, image, image + n, image + n + (n / 4));
+			break;
+		}
+	}
+	else {
+ 		/* Size mismatch; use viewport conversion routines */
+	 	switch(pdev->vpalette) {
+ 		case VIDEO_PALETTE_RGB24 | 0x80:
+ 			vcvt_420i_rgb24(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+	 		break;
+ 		case VIDEO_PALETTE_RGB24:
+ 			vcvt_420i_bgr24(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+	 		break;
+ 		case VIDEO_PALETTE_RGB32 | 0x80:
+ 			vcvt_420i_rgb32(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+	 		break;
+ 		case VIDEO_PALETTE_RGB32:
+ 			vcvt_420i_bgr32(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+ 			break;
+		case VIDEO_PALETTE_YUYV:
+		case VIDEO_PALETTE_YUV422:
+			vcvt_420i_yuyv(pdev->image.x, pdev->image.y, pdev->view.x, yuv, image + pdev->offset.size);
+			break;
+		case VIDEO_PALETTE_YUV420:
+			dst = image + pdev->offset.size;
+			w = pdev->view.x * 6;
+			c = pdev->image.x * 6;
+			for (l = 0; l < pdev->image.y; l++) {
+				memcpy(dst, yuv, c);
+				dst += w;
+				yuv += c;
+			}
+			break;
+		case VIDEO_PALETTE_YUV420P:
+			n = pdev->view.x * pdev->view.y;
+			vcvt_420i_420p(pdev->image.x, pdev->image.y, pdev->view.x, yuv,
+					image +             pdev->offset.size,
+					image + n +         pdev->offset.size / 4,
+					image + n + n / 4 + pdev->offset.size / 4);
+			break;
+ 		}
+ 	}
+	return 0;
+}
+
+
+/* wrapper functions.
+   By using these wrapper functions and exporting them with no VERSIONING,
+   I can be sure the pwcx.o module will load on all systems.
+*/
+
+void *pwc_kmalloc(size_t size, int priority)
+{
+	return kmalloc(size, priority);
+}
+
+void pwc_kfree(const void *pointer)
+{
+	kfree(pointer);
+}
+
+/* Make sure these functions are available for the decompressor plugin
+   both when this code is compiled into the kernel or as as module.
+   We are using unversioned names!
+ */
+EXPORT_SYMBOL_NOVERS(pwc_decompressor_version);
+EXPORT_SYMBOL_NOVERS(pwc_register_decompressor);
+EXPORT_SYMBOL_NOVERS(pwc_unregister_decompressor);
+EXPORT_SYMBOL_NOVERS(pwc_find_decompressor);
+EXPORT_SYMBOL_NOVERS(pwc_kmalloc);
+EXPORT_SYMBOL_NOVERS(pwc_kfree);
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc-uncompress.h linux/drivers/usb/pwc-uncompress.h
--- v2.4.4/linux/drivers/usb/pwc-uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc-uncompress.h	Tue May 22 10:25:36 2001
@@ -0,0 +1,67 @@
+/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   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
+*/
+
+#ifndef PWC_DEC_H
+#define PWC_DEC_H
+
+#include <linux/config.h>
+
+#include <linux/list.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The decompressor structure. 
+   Every type of decompressor registers itself with the main module. 
+   When a device is opened, it looks up the correct compressor, and
+   uses that when a compressed video mode is requested.
+ */
+struct pwc_decompressor
+{
+	int  type;	/* type of camera (645, 646, etc) */
+	int  (* init)(int release, void *buffer, void **data);	/* Initialization routine; should be called after each set_video_mode */
+	void (* exit)(void **data);	/* Cleanup routine */
+	int  (* decompress)(void *data, int width, int height, int bandlength, void *dst, void *src, int planar); /* The decompression routine itself */
+	void (* lock)(void); /* make sure module cannot be unloaded */
+	void (* unlock)(void); /* release lock on module */
+
+	struct list_head pwcd_list;
+};
+
+
+/* Our structure version number. Is set to the version number major */
+extern const int pwc_decompressor_version;
+
+/* Adds decompressor to list, based on its 'type' field (which matches the 'type' field in pwc_device; ignores any double requests */
+extern void pwc_register_decompressor(struct pwc_decompressor *pwcd);
+/* Removes decompressor, based on the type number */
+extern void pwc_unregister_decompressor(int type);
+/* Returns pointer to decompressor struct, or NULL if it doesn't exist */
+extern struct pwc_decompressor *pwc_find_decompressor(int type);
+
+#ifdef CONFIG_USB_PWCX
+/* If the decompressor is compiled in, we must call these manually */
+extern int usb_pwcx_init(void);
+extern void usb_pwcx_exit(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/pwc.h linux/drivers/usb/pwc.h
--- v2.4.4/linux/drivers/usb/pwc.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/pwc.h	Thu May 24 15:00:58 2001
@@ -0,0 +1,304 @@
+/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   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
+*/
+
+#ifndef PWC_H
+#define PWC_H
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#else
+#include <errno.h>
+#include <sys/types.h>
+
+#define printk printf
+#define KERN_DEBUG "<7>"
+#define KERN_INFO  "<6>"
+#define KERN_ERR   "<3>"
+#endif
+
+#include <linux/config.h>
+#include <linux/videodev.h>
+#include <linux/wait.h>
+
+/* Defines and structures for the Philips webcam */
+/* Used for checking memory corruption/pointer validation */
+#define PWC_MAGIC 0x89DC10ABUL
+#undef PWC_MAGIC
+
+/* Debugging info on/off */
+#define PWC_DEBUG 0
+
+#define TRACE_MODULE	0x0001
+#define TRACE_PROBE	0x0002
+#define TRACE_OPEN	0x0004
+#define TRACE_READ	0x0008
+#define TRACE_MEMORY	0x0010
+#define TRACE_FLOW	0x0020
+#define TRACE_SIZE	0x0040
+#define TRACE_SEQUENCE	0x1000
+
+#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " ##A)
+#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " ##A)
+#define Info(A...)  printk(KERN_INFO  PWC_NAME " " ##A)
+#define Err(A...)   printk(KERN_ERR   PWC_NAME " " ##A)
+
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE		8
+#define TOUCAM_TRAILER_SIZE		4
+
+/* Version block */
+#define PWC_MAJOR	7
+#define PWC_MINOR	1
+#define PWC_RELEASE 	"7.1"
+
+#if defined(CONFIG_ARM)
+  #define PWC_PROCESSOR "ARM"
+#endif
+#if defined(CONFIG_M686)
+  #define PWC_PROCESSOR "PPro"
+#endif
+#if !defined(PWC_PROCESSOR)
+  #define PWC_PROCESSOR "P5"
+#endif  
+
+#if defined(__SMP__) || defined(CONFIG_SMP)
+#define PWC_SMP "(SMP)"
+#else
+#define PWC_SMP "(UP)"
+#endif
+
+#define PWC_VERSION PWC_RELEASE " " PWC_PROCESSOR " " PWC_SMP
+#define PWC_NAME "pwc"
+
+/* Turn certain features on/off */
+#define PWC_INT_PIPE 0
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS		2
+#define ISO_FRAMES_PER_DESC	10
+#define ISO_MAX_FRAME_SIZE	960
+#define ISO_BUFFER_SIZE 	(ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Frame buffers: contains compressed or uncompressed video data. */
+#define MAX_FRAMES		5
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define FRAME_SIZE 		(460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute maximum number of buffers available for mmap() */
+#define MAX_IMAGES 		4
+
+struct pwc_coord
+{
+	int x, y;		/* guess what */
+	int size;		/* size, or offset */
+};
+
+/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
+struct pwc_iso_buf
+{
+	void *data;
+	int  length;
+	int  read;
+#ifdef __KERNEL__
+	purb_t urb;
+#endif
+};
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+   void *data;
+   volatile int filled;		/* number of bytes filled */
+   struct pwc_frame_buf *next;	/* list */
+#if PWC_DEBUG
+   int sequence;		/* Sequence number */
+#endif
+};
+
+struct pwc_device
+{
+#ifdef PWC_MAGIC
+   int magic;
+#endif
+   /* Pointer to our usb_device */
+   struct usb_device *udev;
+   
+   int type;                    /* type of cam (645, 646, 675, 680, 690) */
+   int release;			/* release number */
+   int unplugged;		/* set when the plug is pulled */
+   int usb_init;		/* set when the cam has been initialized over USB */
+
+   /*** Video data ***/
+   int vopen;			/* flag */
+   struct video_device *vdev;
+   int vendpoint;		/* video isoc endpoint */
+   int vcinterface;		/* video control interface */
+   int valternate;		/* alternate interface needed */
+   int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
+   int vpalette;		/* YUV, RGB24, RGB32, etc */
+   int vframe_count;		/* received frames */
+   int vframes_dumped; 		/* counter for dumped frames */
+   int vframes_error;		/* frames received in error */
+   int vmax_packet_size;	/* USB maxpacket size */
+   int vlast_packet_size;	/* for frame synchronisation */
+   int vcompression;		/* desired compression factor */
+   int vbandlength;		/* compressed band length; 0 is uncompressed */
+   char vsnapshot;		/* snapshot mode */
+   char vsync;			/* used by isoc handler */
+
+   /* The image acquisition requires 3 to 5 steps:
+      1. data is gathered in short packets from the USB controller
+      2. data is synchronized and packed into a frame buffer
+      3. in case data is compressed, decompress it into a separate buffer
+      4. data is optionally converted to RGB/YUV 
+      5. data is transfered to the user process
+
+      Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... 
+      We have in effect a back-to-back-double-buffer system.
+    */
+   /* 1: isoc */
+   struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
+   char iso_init;
+   
+   /* 2: frame */
+   struct pwc_frame_buf *fbuf;
+   struct pwc_frame_buf *empty_frames, *empty_frames_tail;
+   struct pwc_frame_buf *full_frames, *full_frames_tail;
+   struct pwc_frame_buf *read_frame;
+   struct pwc_frame_buf *fill_frame;
+   int frame_size;
+   int frame_header_size, frame_trailer_size;
+   int drop_frames;
+#if PWC_DEBUG
+   int sequence;			/* Debugging aid */
+#endif
+   
+   /* 3: decompression */
+   struct pwc_decompressor *decompressor;	/* function block with decompression routines */
+   void *decompress_data;		/* private data for decompression engine */
+   void *decompress_buffer;		/* decompressed data */
+
+   /* 4: image */
+   /* We have an 'image' and a 'view', where 'image' is the fixed-size image
+      as delivered by the camera, and 'view' is the size requested by the
+      program. The camera image is centered in this viewport, laced with 
+      a gray or black border. view_min <= image <= view <= view_max;
+    */
+   int image_mask;			/* bitmask of supported sizes */
+   struct pwc_coord view_min, view_max;	/* minimum and maximum sizes */
+   struct pwc_coord image, view;	/* image and viewport size */
+   struct pwc_coord offset;		/* offset within the viewport */
+
+   void *image_data;			/* total buffer, which is subdivided into ... */
+   void *image_ptr[MAX_IMAGES];		/* ...several images... */
+   int fill_image;			/* ...which are rotated. */
+   int image_read_pos;			/* In case we read data in pieces, keep track of were we are in the imagebuffer */
+   int image_used[MAX_IMAGES];		/* For MCAPTURE and SYNC */
+
+#ifdef __KERNEL__
+   /* Kernel specific structures. These were once moved to the end 
+      of the structure and padded with bytes after I found out
+      some of these have different sizes in different kernel versions.
+      But since this is now a source release, I don't have this problem
+      anymore.
+
+      Fortunately none of these structures are needed in the pwcx module.
+    */
+   struct semaphore modlock;		/* to prevent races in video_open(), etc */
+   spinlock_t ptrlock;			/* for manipulating the buffer pointers */
+
+   /*** Misc. data ***/
+   wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
+   wait_queue_head_t pollq;		/* poll() has it's own waitqueue */
+   wait_queue_head_t remove_ok;		/* When we got hot unplugged, we have to avoid a few race conditions */
+#if PWC_INT_PIPE
+   void *usb_int_handler;		/* for the interrupt endpoint */
+#endif   
+#endif   
+};
+
+/* Enumeration of image sizes */
+#define PSZ_SQCIF	0x00
+#define PSZ_QSIF	0x01
+#define PSZ_QCIF	0x02
+#define PSZ_SIF		0x03
+#define PSZ_CIF		0x04
+#define PSZ_VGA		0x05
+#define PSZ_MAX		6
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global variables */
+extern int pwc_trace;
+extern int pwc_preferred_compression;
+
+/** functions in pwc-if.c */
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+
+int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
+
+/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
+extern int pwc_get_brightness(struct pwc_device *pdev);
+extern int pwc_set_brightness(struct pwc_device *pdev, int value);
+extern int pwc_get_contrast(struct pwc_device *pdev);
+extern int pwc_set_contrast(struct pwc_device *pdev, int value);
+extern int pwc_get_gamma(struct pwc_device *pdev);
+extern int pwc_set_gamma(struct pwc_device *pdev, int value);
+extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+
+/* Power down or up the camera; not supported by all models */
+extern int pwc_camera_power(struct pwc_device *pdev, int power);
+
+/* Private ioctl()s; see pwc-ioctl.h */
+extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+extern int pwc_decompress(struct pwc_device *pdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c
--- v2.4.4/linux/drivers/usb/rio500.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/rio500.c	Mon May 21 15:02:06 2001
@@ -24,6 +24,7 @@
  * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
  *
  * */
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -40,6 +41,13 @@
 
 #include "rio500_usb.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
+#define DRIVER_DESC "USB Rio 500 driver"
+
 #define RIO_MINOR   64
 
 /* stall/wait timeout for rio */
@@ -484,7 +492,9 @@
 	if (usb_register(&rio_driver) < 0)
 		return -1;
 
-	info("USB Rio support registered.");
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -502,5 +512,6 @@
 module_init(usb_rio_init);
 module_exit(usb_rio_cleanup);
 
-MODULE_AUTHOR("Cesar Miquel <miquel@df.uba.ar>");
-MODULE_DESCRIPTION("USB Rio 500 driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h
--- v2.4.4/linux/drivers/usb/scanner.h	Fri Mar  2 17:50:22 2001
+++ linux/drivers/usb/scanner.h	Thu May 24 15:14:08 2001
@@ -120,8 +120,9 @@
 	{ USB_DEVICE(0x04b8, 0x0104) },	/* Perfection 1200U and 1200Photo*/
 	{ USB_DEVICE(0x04b8, 0x0106) },	/* Stylus Scan 2500 */
 	{ USB_DEVICE(0x04b8, 0x0107) },	/* Expression 1600 */
-	{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
 	{ USB_DEVICE(0x04b8, 0x010a) }, /* Perfection 1640SU and 1640SU Photo */
+	{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
+	{ USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */
 	/* Umax */
 	{ USB_DEVICE(0x1606, 0x0010) },	/* Astra 1220U */
 	{ USB_DEVICE(0x1606, 0x0030) },	/* Astra 2000U */
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c
--- v2.4.4/linux/drivers/usb/serial/belkin_sa.c	Fri Apr  6 15:51:50 2001
+++ linux/drivers/usb/serial/belkin_sa.c	Mon May 21 15:02:06 2001
@@ -23,6 +23,9 @@
  *    framework in, but haven't analyzed the "tty_flip" interface yet.
  * -- Add support for flush commands
  * -- Add everything that is missing :)
+ * 
+ * 08-Apr-2001 gb
+ *	- Identify version on module load.
  *
  * 12-Mar-2001 gkh
  *	- Added support for the GoHubs GO-COM232 device which is the same as the
@@ -79,6 +82,13 @@
 #include "usb-serial.h"
 #include "belkin_sa.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
+#define DRIVER_DESC "USB Belkin Serial converter driver"
+
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
 static int  belkin_sa_startup		(struct usb_serial *serial);
 static void belkin_sa_shutdown		(struct usb_serial *serial);
@@ -590,6 +600,8 @@
 	usb_serial_register (&belkin_old_device);
 	usb_serial_register (&peracom_device);
 	usb_serial_register (&gocom232_device);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -606,7 +618,8 @@
 module_init (belkin_sa_init);
 module_exit (belkin_sa_exit);
 
-MODULE_DESCRIPTION("USB Belkin Serial converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c
--- v2.4.4/linux/drivers/usb/serial/digi_acceleport.c	Fri Apr  6 15:51:50 2001
+++ linux/drivers/usb/serial/digi_acceleport.c	Mon May 21 15:02:06 2001
@@ -13,6 +13,9 @@
 *
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
+* 
+* (04/08/2001) gb
+*	Identify version on module load.
 *
 * (11/01/2000) Adam J. Richter
 *	usb_device_id table support
@@ -254,6 +257,13 @@
 
 /* Defines */
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.80.1.2"
+#define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
+#define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
+
 /* port output buffer length -- must be <= transfer buffer length - 2 */
 /* so we can be sure to send the full buffer in one urb */
 #define DIGI_OUT_BUF_SIZE		8
@@ -2068,6 +2078,8 @@
 {
 	usb_serial_register (&digi_acceleport_2_device);
 	usb_serial_register (&digi_acceleport_4_device);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -2083,8 +2095,8 @@
 module_exit(digi_exit);
 
 
-MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>");
-MODULE_DESCRIPTION("Digi AccelePort USB-2/USB-4 Serial Converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c
--- v2.4.4/linux/drivers/usb/serial/empeg.c	Fri Apr  6 15:51:51 2001
+++ linux/drivers/usb/serial/empeg.c	Mon May 21 15:02:06 2001
@@ -13,6 +13,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (04/08/2001) gb
+ *      Identify version on module load.
+ * 
  * (01/22/2001) gb
  *	Added write_room() and chars_in_buffer() support. 
  * 
@@ -65,6 +68,13 @@
 
 #include "usb-serial.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
+#define DRIVER_DESC "USB Empeg Mark I/II Driver"
+
 #define EMPEG_VENDOR_ID			0x084f
 #define EMPEG_PRODUCT_ID		0x0001
 
@@ -670,6 +680,9 @@
 		}
 	}
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 
 }
@@ -704,8 +717,8 @@
 module_init(empeg_init);
 module_exit(empeg_exit);
 
-MODULE_AUTHOR("Gary Brubaker <xavyer@ix.netcom.com>");
-MODULE_DESCRIPTION("USB Empeg Mark I/II Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- v2.4.4/linux/drivers/usb/serial/ftdi_sio.c	Wed Apr 18 11:49:12 2001
+++ linux/drivers/usb/serial/ftdi_sio.c	Thu May 24 14:55:51 2001
@@ -14,7 +14,22 @@
  *
  * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info
  *     and extra documentation
+ * 
+ * (23/May/2001)   Bill Ryder
+ *     Added runtime debug patch (thanx Tyson D Sawyer).
+ *     Cleaned up comments for 8U232
+ *     Added parity, framing and overrun error handling
+ *     Added receive break handling.
+ * 
+ * (04/08/2001) gb
+ *	Identify version on module load.
  *       
+ * (18/March/2001) Bill Ryder
+ *     (Not released)
+ *     Added send break handling. (requires kernel patch too)
+ *     Fixed 8U232AM hardware RTS/CTS etc status reporting.
+ *     Added flipbuf fix copied from generic device
+ * 
  * (12/3/2000) Bill Ryder
  *     Added support for 8U232AM device.
  *     Moved PID and VIDs into header file only.
@@ -90,14 +105,24 @@
 #include "ftdi_sio.h"
 
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.1.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>"
+#define DRIVER_DESC "USB FTDI RS232 Converters Driver"
+
 static __devinitdata struct usb_device_id id_table_sio [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ }						/* Terminating entry */
 };
 
-/* THe 8U232AM has the same API as the sio - but it can support MUCH 
-   higher baudrates (921600 at 48MHz/230400 at 12MHz 
-   so .. it's baudrate setting codes are different */
+/* THe 8U232AM has the same API as the sio except for:
+   - it can support MUCH higher baudrates (921600 at 48MHz/230400 
+     at 12MHz so .. it's baudrate setting codes are different 
+   - it has a two byte status code.
+   - it returns characters very 16ms (the FTDI does it every 40ms)
+  */
 
    
 static __devinitdata struct usb_device_id id_table_8U232AM [] = {
@@ -117,9 +142,7 @@
 
 struct ftdi_private {
 	ftdi_type_t ftdi_type;
-	char last_status_byte; /* device sends this every 40ms when open */
-	
-	
+	__u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */
 };
 /* function prototypes for a FTDI serial converter */
 static int  ftdi_sio_startup		(struct usb_serial *serial);
@@ -132,6 +155,7 @@
 static void ftdi_sio_read_bulk_callback	(struct urb *urb);
 static void ftdi_sio_set_termios	(struct usb_serial_port *port, struct termios * old);
 static int  ftdi_sio_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void ftdi_sio_break_ctl		(struct usb_serial_port *port, int break_state );
 
 /* Should rename most ftdi_sio's to ftdi_ now since there are two devices 
    which share common code */ 
@@ -153,6 +177,7 @@
 	write_bulk_callback:	ftdi_sio_write_bulk_callback,
 	ioctl:			ftdi_sio_ioctl,
 	set_termios:		ftdi_sio_set_termios,
+	break_ctl:		ftdi_sio_break_ctl,
 	startup:		ftdi_sio_startup,
         shutdown:               ftdi_sio_shutdown,
 };
@@ -174,6 +199,7 @@
 	write_bulk_callback:	ftdi_sio_write_bulk_callback,
 	ioctl:			ftdi_sio_ioctl,
 	set_termios:		ftdi_sio_set_termios,
+	break_ctl:		ftdi_sio_break_ctl,
 	startup:		ftdi_8U232AM_startup,
         shutdown:               ftdi_sio_shutdown,
 };
@@ -227,7 +253,7 @@
 	
 	priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
 	if (!priv){
-		err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private));
+		err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private));
 		return -ENOMEM;
 	}
 
@@ -245,7 +271,7 @@
 
 	priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
 	if (!priv){
-		err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct ftdi_private));
+		err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private));
 		return -ENOMEM;
 	}
 
@@ -291,7 +317,8 @@
 
 		spin_unlock_irqrestore (&port->port_lock, flags);
 
-		/* do not allow a task to be queued to deliver received data */
+		/* This will push the characters through immediately rather 
+		   than queue a task to deliver them */
 		port->tty->low_latency = 1;
 
 		/* No error checking for this (will get errors later anyway) */
@@ -422,7 +449,7 @@
 		unsigned char *first_byte = port->write_urb->transfer_buffer;
 
 		/* Was seeing a race here, got a read callback, then write callback before
-		   hitting interruptible_sleep_on  - so wrapping in a wait_queue */
+		   hitting interuptible_sleep_on  - so wrapping in a wait_queue */
 
 		add_wait_queue(&port->write_wait, &wait);
 		set_current_state (TASK_INTERRUPTIBLE);
@@ -520,9 +547,9 @@
 static void ftdi_sio_read_bulk_callback (struct urb *urb)
 { /* ftdi_sio_serial_buld_callback */
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-	struct ftdi_private *priv = (struct ftdi_private *)port->private;
 	struct usb_serial *serial;
        	struct tty_struct *tty = port->tty ;
+	char error_flag;
        	unsigned char *data = urb->transfer_buffer;
 
 	const int data_offset = 2;
@@ -549,23 +576,76 @@
 	if (urb->actual_length > 2) {
 		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 	} else {
-                dbg("Just status");
+                dbg("Just status 0o%03o0o%03o",data[0],data[1]);
         }
 
-	priv->last_status_byte = data[0]; /* this has modem control lines */
 
 	/* TO DO -- check for hung up line and handle appropriately: */
 	/*   send hangup  */
 	/* See acm.c - you do a tty_hangup  - eg tty_hangup(tty) */
 	/* if CD is dropped and the line is not CLOCAL then we should hangup */
 
-
+	/* Handle errors and break */
+	error_flag = TTY_NORMAL;
+        /* Although the device uses a bitmask and hence can have multiple */
+        /* errors on a packet - the order here sets the priority the */
+        /* error is returned to the tty layer  */
+	
+	if ( data[1] & FTDI_RS_OE ) { 
+		error_flag = TTY_OVERRUN;
+                dbg("OVERRRUN error");
+	}
+	if ( data[1] & FTDI_RS_BI ) { 
+		error_flag = TTY_BREAK;
+                dbg("BREAK received");
+	}
+	if ( data[1] & FTDI_RS_PE ) { 
+		error_flag = TTY_PARITY;
+                dbg("PARITY error");
+	}
+	if ( data[1] & FTDI_RS_FE ) { 
+		error_flag = TTY_FRAME;
+                dbg("FRAMING error");
+	}
 	if (urb->actual_length > data_offset) {
+
 		for (i = data_offset ; i < urb->actual_length ; ++i) {
-			tty_insert_flip_char(tty, data[i], 0);
-	  	}
+			/* have to make sure we don't overflow the buffer
+			  with tty_insert_flip_char's */
+			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+			}
+			/* Note that the error flag is duplicated for 
+			   every character received since we don't know
+			   which character it applied to */
+			tty_insert_flip_char(tty, data[i], error_flag);
+		}
 	  	tty_flip_buffer_push(tty);
+
+
+	} 
+
+#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
+	/* if a parity error is detected you get status packets forever
+	   until a character is sent without a parity error.
+	   This doesn't work well since the application receives a never
+	   ending stream of bad data - even though new data hasn't been sent.
+	   Therefore I (bill) have taken this out.
+	   However - this might make sense for framing errors and so on 
+	   so I am leaving the code in for now.
+	*/
+      else {
+		if (error_flag != TTY_NORMAL){
+			dbg("error_flag is not normal");
+				/* In this case it is just status - if that is an error send a bad character */
+				if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+					tty_flip_buffer_push(tty);
+				}
+				tty_insert_flip_char(tty, 0xff, error_flag);
+				tty_flip_buffer_push(tty);
+		}
 	}
+#endif
 
 	/* Continue trying to always read  */
 	FILL_BULK_URB(urb, serial->dev, 
@@ -627,6 +707,38 @@
 	return(urb_value);
 }
 
+static void ftdi_sio_break_ctl( struct usb_serial_port *port, int break_state )
+{
+	struct usb_serial *serial = port->serial;
+	struct ftdi_private *priv = (struct ftdi_private *)port->private;
+	__u16 urb_value = 0; 
+	char buf[1];
+	
+	/* break_state = -1 to turn on break, and 0 to turn off break */
+	/* see drivers/char/tty_io.c to see it used */
+	/* last_set_data_urb_value NEVER has the break bit set in it */
+
+	if (break_state) {
+		urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
+	} else {
+		urb_value = priv->last_set_data_urb_value; 
+	}
+
+	
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_DATA_REQUEST, 
+			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
+			    urb_value , 0,
+			    buf, 0, WDR_TIMEOUT) < 0) {
+		err(__FUNCTION__ " FAILED to enable/disable break state (state was %d)",break_state);
+	}	   
+
+	dbg(__FUNCTION__ " break state is %d - urb is %d",break_state, urb_value);
+	
+}
+
+
+
 /* As I understand this - old_termios contains the original termios settings */
 /*  and tty->termios contains the new setting to be used */
 /* */
@@ -670,6 +782,11 @@
 			err("CSIZE was set but not CS5-CS8");
 		}
 	}
+
+	/* This is needed by the break command since it uses the same command - but is
+	 *  or'ed with this value  */
+	priv->last_set_data_urb_value = urb_value;
+	
 	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
@@ -743,7 +860,7 @@
 	struct usb_serial *serial = port->serial;
 	struct ftdi_private *priv = (struct ftdi_private *)port->private;
 	__u16 urb_value=0; /* Will hold the new flags */
-	char buf[1];
+	char buf[2];
 	int  ret, mask;
 	
 	dbg(__FUNCTION__ " cmd 0x%04x", cmd);
@@ -753,12 +870,7 @@
 
 	case TIOCMGET:
 		dbg(__FUNCTION__ " TIOCMGET");
-		/* The MODEM_STATUS_REQUEST works for the sio but not the 232 */
 		if (priv->ftdi_type == sio){
-			/* TO DECIDE - use the 40ms status packets or not? */
-			/*   PRO: No need to send urb */
-			/*   CON: Could be 40ms out of date */
-
 			/* Request the status from the device */
 			if ((ret = usb_control_msg(serial->dev, 
 						   usb_rcvctrlpipe(serial->dev, 0),
@@ -771,8 +883,18 @@
 				return(ret);
 			}
 		} else {
-			/* This gets updated every 40ms - so just copy it in */
-			buf[0] = priv->last_status_byte;
+			/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same 
+			   format as the data returned from the in point */
+			if ((ret = usb_control_msg(serial->dev, 
+						   usb_rcvctrlpipe(serial->dev, 0),
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+						   0, 0, 
+						   buf, 2, WDR_TIMEOUT)) < 0 ) {
+				err(__FUNCTION__ " Could not get modem status of device - err: %d",
+				    ret);
+				return(ret);
+			}
 		}
 
 		return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
@@ -863,6 +985,8 @@
 	dbg(__FUNCTION__);
 	usb_serial_register (&ftdi_sio_device);
 	usb_serial_register (&ftdi_8U232AM_device);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -878,8 +1002,8 @@
 module_init(ftdi_sio_init);
 module_exit(ftdi_sio_exit);
 
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>");
-MODULE_DESCRIPTION("USB FTDI RS232 converters driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/ftdi_sio.h linux/drivers/usb/serial/ftdi_sio.h
--- v2.4.4/linux/drivers/usb/serial/ftdi_sio.h	Tue Dec  5 23:15:12 2000
+++ linux/drivers/usb/serial/ftdi_sio.h	Thu May 24 14:55:51 2001
@@ -146,7 +146,7 @@
 #define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
 #define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
 #define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
-
+#define FTDI_SIO_SET_BREAK (0x1 << 14)
 /* FTDI_SIO_SET_DATA */
 
 /*
@@ -170,7 +170,10 @@
  *           0 = 1
  *           1 = 1.5
  *           2 = 2
- *   B14..15 Reserved
+ *   B14
+ *           1 = TX ON (break)
+ *           0 = TX OFF (normal state)
+ *   B15 Reserved
  *
  */
 
@@ -434,6 +437,17 @@
  * B6	Transmitter Empty (TEMT)
  * B7	Error in RCVR FIFO
  * 
+ */
+#define FTDI_RS_DR  1
+#define FTDI_RS_OE (1<<1)
+#define FTDI_RS_PE (1<<2)
+#define FTDI_RS_FE (1<<3)
+#define FTDI_RS_BI (1<<4)
+#define FTDI_RS_THRE (1<<5)
+#define FTDI_RS_TEMT (1<<6)
+#define FTDI_RS_FIFO  (1<<7)
+
+/*
  * OUT Endpoint
  * 
  * This device reserves the first bytes of data on this endpoint contain the length
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c
--- v2.4.4/linux/drivers/usb/serial/io_edgeport.c	Thu Apr 12 12:16:36 2001
+++ linux/drivers/usb/serial/io_edgeport.c	Mon May 21 15:02:06 2001
@@ -24,6 +24,9 @@
  *	Edgeport/8i
  *
  * Version history:
+ * 
+ *     (04/08/2001) gb
+ *	- Identify version on module load.
  *
  * 2.0 2001_03_05 greg kroah-hartman
  *	- reworked entire driver to fit properly in with the other usb-serial
@@ -254,6 +257,13 @@
 #include "io_ionsp.h"		/* info for the iosp messages */
 #include "io_16654.h"		/* 16654 UART defines */
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v2.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
+#define DRIVER_DESC "Edgeport USB Serial Driver"
+
 /* First, the latest boot code - for first generation edgeports */
 #define IMAGE_ARRAY_NAME	BootCodeImage_GEN1
 #define IMAGE_VERSION_NAME	BootCodeImageVersion_GEN1
@@ -275,13 +285,6 @@
 #include "io_fw_down2.h"	/* Define array OperationalCodeImage[] */
 
 
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli");
-MODULE_DESCRIPTION("Edgeport USB Serial Driver");
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 #define MAX_NAME_LEN		64
 
 
@@ -3034,7 +3037,8 @@
 	usb_serial_register (&edgeport_16dual_device);
 	usb_serial_register (&edgeport_compat_id_device);
 	usb_serial_register (&edgeport_8i_device);
-	
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -3066,4 +3070,11 @@
 
 module_init(edgeport_init);
 module_exit(edgeport_exit);
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c
--- v2.4.4/linux/drivers/usb/serial/keyspan.c	Thu Apr 12 12:16:36 2001
+++ linux/drivers/usb/serial/keyspan.c	Mon May 21 15:02:06 2001
@@ -28,6 +28,9 @@
   open source projects.
 
   Change History
+   (04/08/2001) gb
+	Identify version on module load.
+   
    (11/01/2000) Adam J. Richter
 	usb_device_id table support.
    
@@ -74,6 +77,13 @@
 #include "usb-serial.h"
 #include "keyspan.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Hugh Blemings <hugh@linuxcare.com>"
+#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
+
 #define INSTAT_BUFLEN	32
 #define GLOCONT_BUFLEN	64
 
@@ -166,6 +176,10 @@
 	usb_serial_register (&keyspan_usa28_device);
 	usb_serial_register (&keyspan_usa28x_device);
 	usb_serial_register (&keyspan_usa49w_device);
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -1287,7 +1301,21 @@
 		msg.setPrescaler = 0xff;
 	}
 
-	msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1;
+	msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+	switch (p_priv->cflag & CSIZE) {
+	case CS5:
+		msg.lcr |= USA_DATABITS_5;
+		break;
+	case CS6:
+		msg.lcr |= USA_DATABITS_6;
+		break;
+	case CS7:
+		msg.lcr |= USA_DATABITS_7;
+		break;
+	case CS8:
+		msg.lcr |= USA_DATABITS_8;
+		break;
+	}
 	if (p_priv->cflag & PARENB) {
 		/* note USA_PARITY_NONE == 0 */
 		msg.lcr |= (p_priv->cflag & PARODD)?
@@ -1480,7 +1508,21 @@
 		//msg.setPrescaler = 0xff;
 	}
 
-	msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1;
+	msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
+	switch (p_priv->cflag & CSIZE) {
+	case CS5:
+		msg.lcr |= USA_DATABITS_5;
+		break;
+	case CS6:
+		msg.lcr |= USA_DATABITS_6;
+		break;
+	case CS7:
+		msg.lcr |= USA_DATABITS_7;
+		break;
+	case CS8:
+		msg.lcr |= USA_DATABITS_8;
+		break;
+	}
 	if (p_priv->cflag & PARENB) {
 		/* note USA_PARITY_NONE == 0 */
 		msg.lcr |= (p_priv->cflag & PARODD)?
@@ -1673,6 +1715,9 @@
 		kfree(port->private);
 	}
 }
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c
--- v2.4.4/linux/drivers/usb/serial/keyspan_pda.c	Fri Apr  6 15:51:51 2001
+++ linux/drivers/usb/serial/keyspan_pda.c	Mon May 21 15:02:06 2001
@@ -12,6 +12,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (04/08/2001) gb
+ *	Identify version on module load.
+ * 
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
  * 
@@ -85,6 +88,13 @@
 #include "keyspan_pda_fw.h"
 #include "usb-serial.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
+#define DRIVER_DESC "USB Keyspan PDA Converter driver"
+
 struct keyspan_pda_private {
 	int			tx_room;
 	int			tx_throttled;
@@ -807,6 +817,8 @@
 {
 	usb_serial_register (&keyspan_pda_fake_device);
 	usb_serial_register (&keyspan_pda_device);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -821,8 +833,8 @@
 module_init(keyspan_pda_init);
 module_exit(keyspan_pda_exit);
 
-MODULE_AUTHOR("Brian Warner <warner@lothar.com>");
-MODULE_DESCRIPTION("USB Keyspan PDA Converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/keyspan_pda_fw.h linux/drivers/usb/serial/keyspan_pda_fw.h
--- v2.4.4/linux/drivers/usb/serial/keyspan_pda_fw.h	Fri Mar 10 13:19:34 2000
+++ linux/drivers/usb/serial/keyspan_pda_fw.h	Sat May 19 17:47:55 2001
@@ -1,9 +1,15 @@
 /*
- * keyspan_pda_fw.h
+ * USB Keyspan PDA Firmware
+ *
+ * Copyright (c) 1999, 2000 Brian Warner	<warner@lothar.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.
  *
  * Generated from keyspan_pda.s by ezusb_convert.pl
- * This file is presumed to be under the same copyright as the source file
- * from which it was derived.
+ *
  */
 
 static const struct ezusb_hex_record keyspan_pda_firmware[] = {
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c
--- v2.4.4/linux/drivers/usb/serial/mct_u232.c	Fri Apr  6 15:51:52 2001
+++ linux/drivers/usb/serial/mct_u232.c	Thu May 24 14:55:51 2001
@@ -24,6 +24,17 @@
  *   Basic tests have been performed with minicom/zmodem transfers and
  *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
  *
+ * 04-May-2001 Stelian Pop
+ *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
+ *     instead of the device reported 32 (using 32 bytes causes many data
+ *     loss, Windows driver uses 16 too).
+ *
+ * 02-May-2001 Stelian Pop
+ *   - Fixed the baud calculation for Sitecom U232-P25 model
+ *
+ * 08-Apr-2001 gb
+ *   - Identify version on module load.
+ *
  * 06-Jan-2001 Cornel Ciocirlan 
  *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
  *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
@@ -66,6 +77,13 @@
 
 
 /*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
+#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
+
+/*
  * Some not properly written applications do not handle the return code of
  * write() correctly. This can result in character losses. A work-a-round
  * can be compiled in with the following definition. This work-a-round
@@ -218,11 +236,31 @@
 
 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
 
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
+	if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID) {
+		switch (value) {
+			case    300: return 0x01;
+			case    600: return 0x02; /* this one not tested */
+			case   1200: return 0x03;
+			case   2400: return 0x04;
+			case   4800: return 0x06;
+			case   9600: return 0x08;
+			case  19200: return 0x09;
+			case  38400: return 0x0a;
+			case  57600: return 0x0b;
+			case 115200: return 0x0c;
+			default:     return -1; /* normally not reached */
+		}
+	}
+	else
+		return MCT_U232_BAUD_RATE(value);
+}
+
 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
 {
 	unsigned int divisor;
         int rc;
-	divisor = MCT_U232_BAUD_RATE(value);
+	divisor = mct_u232_calculate_baud_rate(serial, value);
         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                              MCT_U232_SET_BAUD_RATE_REQUEST,
 			     MCT_U232_SET_REQUEST_TYPE,
@@ -230,7 +268,7 @@
 			     WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
-	dbg("set_baud_rate: 0x%x", divisor);
+	dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
         return rc;
 } /* mct_u232_set_baud_rate */
 
@@ -367,6 +405,14 @@
 	if (!port->active) {
 		port->active = 1;
 
+		/* Compensate for a hardware bug: although the Sitecom U232-P25
+		 * device reports a maximum output packet size of 32 bytes,
+		 * it seems to be able to accept only 16 bytes (and that's what
+		 * SniffUSB says too...)
+		 */
+		if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
+			port->bulk_out_size = 16;
+
 		/* Do a defined restart: the normal serial device seems to 
 		 * always turn on DTR and RTS here, so do the same. I'm not
 		 * sure if this is really necessary. But it should not harm
@@ -824,7 +870,8 @@
 	usb_serial_register (&mct_u232_device);
 	usb_serial_register (&mct_u232_sitecom_device);
 	usb_serial_register (&mct_u232_du_h3sp_device);
-	
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -840,8 +887,8 @@
 module_init (mct_u232_init);
 module_exit(mct_u232_exit);
 
-MODULE_AUTHOR("Wolfgang Grandegger <wolfgang@ces.ch>");
-MODULE_DESCRIPTION("Magic Control Technology USB-RS232 converter driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 #ifdef FIX_WRITE_RETURN_CODE_PROBLEM
 MODULE_PARM(write_blocking, "i");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c
--- v2.4.4/linux/drivers/usb/serial/omninet.c	Fri Apr  6 15:51:52 2001
+++ linux/drivers/usb/serial/omninet.c	Mon May 21 15:02:06 2001
@@ -9,6 +9,9 @@
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
  * Please report both successes and troubles to the author at omninet@kroah.com
+ * 
+ * (04/08/2001) gb
+ *	Identify version on module load.
  *
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
@@ -54,6 +57,13 @@
 #include "usb-serial.h"
 
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Anonymous"
+#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
+
 #define ZYXEL_VENDOR_ID		0x0586
 #define ZYXEL_OMNINET_ID	0x1000
 
@@ -396,6 +406,8 @@
 static int __init omninet_init (void)
 {
 	usb_serial_register (&zyxel_omninet_device);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -408,6 +420,9 @@
 
 module_init(omninet_init);
 module_exit(omninet_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- v2.4.4/linux/drivers/usb/serial/usbserial.c	Fri Apr  6 15:51:52 2001
+++ linux/drivers/usb/serial/usbserial.c	Mon May 21 15:02:06 2001
@@ -14,6 +14,9 @@
  * based on a driver by Brad Keryan)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (04/08/2001) gb
+ *	Identify version on module load.
  *
  * 2001_02_05 gkh
  *	Fixed buffer overflows bug with the generic serial driver.  Thanks to
@@ -282,14 +285,12 @@
 
 #include "usb-serial.h"
 
-
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
-MODULE_DESCRIPTION("USB Serial Driver");
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"
+#define DRIVER_DESC "USB Serial Driver"
 
 #define MAX(a,b)	(((a)>(b))?(a):(b))
 
@@ -309,11 +310,6 @@
 #ifdef CONFIG_USB_SERIAL_GENERIC
 static __u16	vendor	= 0x05f9;
 static __u16	product	= 0xffff;
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
 
 static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
 
@@ -1398,8 +1394,10 @@
 		err("usb_register failed for the usb-serial driver. Error number %d", result);
 		return -1;
 	}
-	
-	
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -1463,4 +1461,18 @@
 	EXPORT_SYMBOL(ezusb_writememory);
 	EXPORT_SYMBOL(ezusb_set_reset);
 #endif
+
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- v2.4.4/linux/drivers/usb/serial/visor.c	Fri Apr  6 15:51:52 2001
+++ linux/drivers/usb/serial/visor.c	Mon May 21 15:02:06 2001
@@ -10,6 +10,9 @@
  *	(at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (04/08/2001) gb
+ *	Identify version on module load.
  *
  * (01/21/2000) gkh
  *	Added write_room and chars_in_buffer, as they were previously using the
@@ -103,6 +106,13 @@
 #include "usb-serial.h"
 #include "visor.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC "USB HandSpring Visor driver"
+
 #define MIN(a,b)                (((a)<(b))?(a):(b))
 
 /* function prototypes for a handspring visor */
@@ -653,7 +663,10 @@
 			continue;
 		}
 	}
-	
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 }
 
@@ -686,8 +699,8 @@
 module_init(visor_init);
 module_exit(visor_exit);
 
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
-MODULE_DESCRIPTION("USB HandSpring Visor driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c
--- v2.4.4/linux/drivers/usb/serial/whiteheat.c	Fri Apr  6 15:51:52 2001
+++ linux/drivers/usb/serial/whiteheat.c	Mon May 21 15:02:06 2001
@@ -10,6 +10,9 @@
  *	(at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * (04/08/2001) gb
+ *	Identify version on module load.
  * 
  * 2001_Mar_19 gkh
  *	Fixed MOD_INC and MOD_DEC logic, the ability to open a port more 
@@ -79,6 +82,13 @@
 #include "whiteheat_fw.h"		/* firmware for the ConnectTech WhiteHEAT device */
 #include "whiteheat.h"			/* WhiteHEAT specific commands */
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
+
 #define CONNECT_TECH_VENDOR_ID		0x0710
 #define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001
 #define CONNECT_TECH_WHITE_HEAT_ID	0x8001
@@ -616,6 +626,8 @@
 {
 	usb_serial_register (&whiteheat_fake_device);
 	usb_serial_register (&whiteheat_device);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
@@ -630,8 +642,8 @@
 module_init(whiteheat_init);
 module_exit(whiteheat_exit);
 
-MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
-MODULE_DESCRIPTION("USB ConnectTech WhiteHEAT driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/storage/dpcm.c linux/drivers/usb/storage/dpcm.c
--- v2.4.4/linux/drivers/usb/storage/dpcm.c	Mon Aug 28 16:59:14 2000
+++ linux/drivers/usb/storage/dpcm.c	Sat Apr 28 11:28:08 2001
@@ -10,7 +10,7 @@
  *   (c) 2000 Brian Webb (webbb@earthlink.net)
  *
  * This device contains both a CompactFlash card reader, which
- * usest the Control/Bulk w/o Interrupt protocol and
+ * uses the Control/Bulk w/o Interrupt protocol and
  * a SmartMedia card reader that uses the same protocol
  * as the SDDR09.
  *
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h
--- v2.4.4/linux/drivers/usb/storage/unusual_devs.h	Fri Apr 27 15:49:28 2001
+++ linux/drivers/usb/storage/unusual_devs.h	Tue May 22 11:19:08 2001
@@ -79,6 +79,12 @@
 		"CameraMate (DPCM_USB)",
  		US_SC_SCSI, US_PR_DPCM_USB, NULL,
 		US_FL_START_STOP ),
+
+UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
+		"SCM Microsystems Inc",
+		"eUSB SmartMedia / CompactFlash Adapter",
+		US_SC_SCSI, US_PR_DPCM_USB, NULL,
+		US_FL_START_STOP ),
 #endif
 
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0200, 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/timon.inc linux/drivers/usb/timon.inc
--- v2.4.4/linux/drivers/usb/timon.inc	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/timon.inc	Tue May 22 10:25:36 2001
@@ -0,0 +1,270 @@
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+         {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+         {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+         {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+         {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+         {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+         {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+         {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+         {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+         {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+         {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+         {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+         {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+         {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+         {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+         {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+         {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+         {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+         {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+         {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+         {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+         {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+         {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+         {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+         {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+         {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+         {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+         {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+         {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+         {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+         {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+         {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+         {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+         {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+         {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+         {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+         {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+         {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+         {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+         {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+         {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+         {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+         {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+         {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+         {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+         {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/uhci-debug.h linux/drivers/usb/uhci-debug.h
--- v2.4.4/linux/drivers/usb/uhci-debug.h	Fri Apr 27 15:50:01 2001
+++ linux/drivers/usb/uhci-debug.h	Tue May 22 11:19:30 2001
@@ -9,6 +9,7 @@
  * (C) Copyright 1999-2001 Johannes Erdfelt
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.4.4/linux/drivers/usb/uhci.c	Wed Apr 25 14:10:49 2001
+++ linux/drivers/usb/uhci.c	Mon May 21 15:02:06 2001
@@ -57,6 +57,15 @@
 
 #include <linux/pm.h>
 
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION ""
+#define DRIVER_AUTHOR "Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
+
 /*
  * debug = 0, no debugging messages
  * debug = 1, dump failed URB's except for stalls
@@ -644,21 +653,23 @@
 
 	urb->hcpriv = urbp;
 
-	if (urb->transfer_buffer_length) {
-		urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
-			urb->transfer_buffer, urb->transfer_buffer_length,
-			usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
-			PCI_DMA_TODEVICE);
-		if (!urbp->transfer_buffer_dma_handle)
-			return NULL;
-	}
-
-	if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
-		urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
-			urb->setup_packet, sizeof(devrequest),
-			PCI_DMA_TODEVICE);
-		if (!urbp->setup_packet_dma_handle)
-			return NULL;
+	if (urb->dev != uhci->rh.dev) {
+		if (urb->transfer_buffer_length) {
+			urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
+				urb->transfer_buffer, urb->transfer_buffer_length,
+				usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
+				PCI_DMA_TODEVICE);
+			if (!urbp->transfer_buffer_dma_handle)
+				return NULL;
+		}
+
+		if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
+			urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
+				urb->setup_packet, sizeof(devrequest),
+				PCI_DMA_TODEVICE);
+			if (!urbp->setup_packet_dma_handle)
+				return NULL;
+		}
 	}
 
 	return urbp;
@@ -722,11 +733,11 @@
 		uhci_free_td(uhci, td);
 	}
 
-	if (urb->setup_packet)
+	if (urbp->setup_packet_dma_handle)
 		pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
 			sizeof(devrequest), PCI_DMA_TODEVICE);
 
-	if (urb->transfer_buffer_length)
+	if (urbp->transfer_buffer_dma_handle)
 		pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
 			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
 			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
@@ -2247,12 +2258,12 @@
 	if (!killed)
 		urb->status = status;
 
-	if (urb->transfer_buffer_length)
+	if (urbp->transfer_buffer_dma_handle)
 		pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
 			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
 			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
 
-	if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet)
+	if (urbp->setup_packet_dma_handle)
 		pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
 			sizeof(devrequest), PCI_DMA_TODEVICE);
 
@@ -2910,6 +2921,7 @@
 	release_uhci(uhci);
 }
 
+#ifdef CONFIG_PM
 static void uhci_pci_suspend(struct pci_dev *dev)
 {
 	reset_hc((struct uhci *) dev->driver_data);
@@ -2920,6 +2932,7 @@
 	reset_hc((struct uhci *) dev->driver_data);
 	start_hc((struct uhci *) dev->driver_data);
 }
+#endif
 
 static const struct pci_device_id __devinitdata uhci_pci_ids[] = { {
 
@@ -2977,6 +2990,9 @@
 	if (retval)
 		goto init_failed;
 
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return 0;
 
 init_failed:
@@ -3016,6 +3032,6 @@
 module_init(uhci_hcd_init);
 module_exit(uhci_hcd_cleanup);
 
-MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
-MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.4.4/linux/drivers/usb/usb-ohci.c	Wed Apr 25 14:10:49 2001
+++ linux/drivers/usb/usb-ohci.c	Tue May 22 13:55:49 2001
@@ -12,6 +12,7 @@
  * 
  * History:
  * 
+ * 2001/04/08 Identify version on module load gb
  * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
  	pci_map_single (db)
  * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
@@ -85,6 +86,13 @@
 #endif
 
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v5.2"
+#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
+#define DRIVER_DESC "USB OHCI Host Controller Driver"
+
 /* For initializing controller (mask in an HCFS mode too) */
 #define	OHCI_CONTROL_INIT \
 	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
@@ -597,12 +605,14 @@
 	urb_priv->length = size;
 	urb_priv->ed = ed;	
 
-	/* allocate the TDs */
+	/* allocate the TDs (updating hash chains) */
+	spin_lock_irqsave (&usb_ed_lock, flags);
 	for (i = 0; i < size; i++) { 
-		urb_priv->td[i] = td_alloc (ohci, mem_flags);
+		urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
 		if (!urb_priv->td[i]) {
 			urb_priv->length = i;
 			urb_free_priv (ohci, urb_priv);
+			spin_unlock_irqrestore (&usb_ed_lock, flags);
 			usb_dec_dev_use (urb->dev);	
 			return -ENOMEM;
 		}
@@ -610,6 +620,7 @@
 
 	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
 		urb_free_priv (ohci, urb_priv);
+		spin_unlock_irqrestore (&usb_ed_lock, flags);
 		usb_dec_dev_use (urb->dev);	
 		return -EINVAL;
 	}
@@ -631,6 +642,7 @@
 			}
 			if (bustime < 0) {
 				urb_free_priv (ohci, urb_priv);
+				spin_unlock_irqrestore (&usb_ed_lock, flags);
 				usb_dec_dev_use (urb->dev);	
 				return bustime;
 			}
@@ -640,7 +652,6 @@
 #endif
 	}
 
-	spin_lock_irqsave (&usb_ed_lock, flags);
 	urb->actual_length = 0;
 	urb->hcpriv = urb_priv;
 	urb->status = USB_ST_URB_PENDING;
@@ -1182,7 +1193,7 @@
 	if (ed->state == ED_NEW) {
 		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
   		/* dummy td; end of td list for ed */
-		td = td_alloc (ohci, mem_flags);
+		td = td_alloc (ohci, SLAB_ATOMIC);
 		/* hash the ed for later reverse mapping */
  		if (!td || !hash_add_ed (ohci, (ed_t *)ed)) {
 			/* out of memory */
@@ -2248,6 +2259,7 @@
 		// Count and limit the retries though; either hardware or
 		// software errors can go forever...
 #endif
+		hc_reset (ohci);
 	}
   
 	if (ints & OHCI_INTR_WDH) {
@@ -2261,6 +2273,7 @@
 		writel (OHCI_INTR_SO, &regs->intrenable); 	 
 	}
 
+	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...
 	if (ints & OHCI_INTR_SF) { 
 		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
 		writel (OHCI_INTR_SF, &regs->intrdisable);	
@@ -2504,6 +2517,11 @@
 
 	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
+
+        if (!dev->irq) {
+        	err("found OHCI device with no IRQ assigned. check BIOS settings!");
+   	        return -ENODEV;
+        }
 	
 	/* we read its hardware registers as memory */
 	mem_resource = pci_resource_start(dev, 0);
@@ -2756,6 +2774,8 @@
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_register_sleep_notifier (&ohci_sleep_notifier);
 #endif  
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return ret;
 }
 
@@ -2773,5 +2793,5 @@
 module_exit (ohci_hcd_cleanup);
 
 
-MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>, David Brownell");
-MODULE_DESCRIPTION ("USB OHCI Host Controller Driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usb-ohci.h linux/drivers/usb/usb-ohci.h
--- v2.4.4/linux/drivers/usb/usb-ohci.h	Wed Apr 25 14:10:49 2001
+++ linux/drivers/usb/usb-ohci.h	Sun May 20 12:11:39 2001
@@ -29,6 +29,7 @@
 	/* Not Access */               USB_ST_NORESPONSE 
 };
 
+#include <linux/config.h>
 
 /* ED States */
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usb-uhci-debug.h linux/drivers/usb/usb-uhci-debug.h
--- v2.4.4/linux/drivers/usb/usb-uhci-debug.h	Sat Jul  8 19:38:16 2000
+++ linux/drivers/usb/usb-uhci-debug.h	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
 		dbg("qh has not QH_TYPE");
 		return;
 	}
-	dbg("QH @ %p/%08lX:", qh, virt_to_bus (qh));
+	dbg("QH @ %p/%08X:", qh, qh->dma_addr);
 
 	if (qh->hw.qh.head & UHCI_PTR_TERM)
 		dbg("    Head Terminate");
@@ -23,6 +23,7 @@
 }
 #endif
 
+#if 0
 static void uhci_show_td (puhci_desc_t td)
 {
 	char *spid;
@@ -42,8 +43,8 @@
 		break;
 	}
 
-	warn("  TD @ %p/%08lX, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x",
-	     td, virt_to_bus (td),
+	warn("  TD @ %p/%08X, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x",
+	     td, td->dma_addr,
 	     td->hw.td.info >> 21,
 	     ((td->hw.td.info >> 19) & 1),
 	     (td->hw.td.info >> 15) & 15,
@@ -74,10 +75,15 @@
 		     td->hw.td.link & ~UHCI_PTR_BITS,
 		     (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first"));
 }
+#endif
+
 #ifdef DEBUG
 static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td)
 {
-	//dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td));
+	//dbg("uhci_show_td_queue %p (%08lX):", td, td->dma_addr);
+#if 1
+	return;
+#else
 	while (1) {
 		uhci_show_td (td);
 		if (td->hw.td.link & UHCI_PTR_TERM)
@@ -89,13 +95,19 @@
 			break;
 		}
 	}
+#endif
 }
 
 static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh)
 {
+#if 0
 	uhci_desc_t *start_qh=qh;
+#endif
 
 	dbg("uhci_show_queue %p:", qh);
+#if 1
+	return;
+#else
 	while (1) {
 		uhci_show_qh (qh);
 
@@ -117,6 +129,7 @@
 			break;
 		}
 	}		
+#endif
 }
 
 static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- v2.4.4/linux/drivers/usb/usb-uhci.c	Fri Apr 27 15:13:07 2001
+++ linux/drivers/usb/usb-uhci.c	Mon May 21 15:02:06 2001
@@ -58,6 +58,13 @@
 #include "usb-uhci.h"
 #include "usb-uhci-debug.h"
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.251"
+#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
 #undef DEBUG
 #undef dbg
 #define dbg(format, arg...) do {} while (0)
@@ -75,7 +82,6 @@
 #define async_dbg dbg //err
 
 #ifdef DEBUG_SLAB
-	static kmem_cache_t *uhci_desc_kmem;
 	static kmem_cache_t *urb_priv_kmem;
 #endif
 
@@ -128,17 +134,17 @@
 {
 
 	if (!list_empty(&s->urb_unlinked)) {
-		s->td1ms->hw.td.status |= TD_CTRL_IOC;
+		s->td1ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC);
 	}
 	else {
-		s->td1ms->hw.td.status &= ~TD_CTRL_IOC;
+		s->td1ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC);
 	}
 
 	if (s->timeout_urbs) {
-		s->td32ms->hw.td.status |= TD_CTRL_IOC;
+		s->td32ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC);
 	}
 	else {
-		s->td32ms->hw.td.status &= ~TD_CTRL_IOC;
+		s->td32ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC);
 	}
 
 	wmb();
@@ -153,7 +159,7 @@
 		return;
 
 	spin_lock_irqsave (&s->qh_lock, flags);
-	s->chain_end->hw.qh.head&=~UHCI_PTR_TERM; 
+	s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM);
 	mb();
 	s->loop_usage++;
 	((urb_priv_t*)urb->hcpriv)->use_loop=1;
@@ -172,7 +178,7 @@
 		s->loop_usage--;
 
 		if (!s->loop_usage) {
-			s->chain_end->hw.qh.head|=UHCI_PTR_TERM;
+			s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM);
 			mb();
 		}
 		((urb_priv_t*)urb->hcpriv)->use_loop=0;
@@ -226,17 +232,16 @@
 
 }
 /*-------------------------------------------------------------------*/
-_static int alloc_td (uhci_desc_t ** new, int flags)
+_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags)
 {
-#ifdef DEBUG_SLAB
-	*new= kmem_cache_alloc(uhci_desc_kmem, SLAB_FLAG);
-#else
-	*new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), KMALLOC_FLAG);
-#endif
+	dma_addr_t dma_handle;
+
+	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
 	if (!*new)
 		return -ENOMEM;
-	 memset (*new, 0, sizeof (uhci_desc_t));
-	(*new)->hw.td.link = UHCI_PTR_TERM | (flags & UHCI_PTR_BITS);	// last by default
+	memset (*new, 0, sizeof (uhci_desc_t));
+	(*new)->dma_addr = dma_handle;
+	(*new)->hw.td.link = cpu_to_le32(UHCI_PTR_TERM | (flags & UHCI_PTR_BITS));	// last by default
 	(*new)->type = TD_TYPE;
 	mb();
 	INIT_LIST_HEAD (&(*new)->vertical);
@@ -252,7 +257,7 @@
 	
 	spin_lock_irqsave (&s->td_lock, xxx);
 
-	td->hw.td.link = virt_to_bus (qh) | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH;
+	td->hw.td.link = cpu_to_le32(qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH);
        
 	mb();
 	spin_unlock_irqrestore (&s->td_lock, xxx);
@@ -272,11 +277,11 @@
 
 	if (qh == prev ) {
 		// virgin qh without any tds
-		qh->hw.qh.element = virt_to_bus (new) | UHCI_PTR_TERM;
+		qh->hw.qh.element = cpu_to_le32(new->dma_addr | UHCI_PTR_TERM);
 	}
 	else {
 		// already tds inserted, implicitely remove TERM bit of prev
-		prev->hw.td.link = virt_to_bus (new) | (flags & UHCI_PTR_DEPTH);
+		prev->hw.td.link = cpu_to_le32(new->dma_addr | (flags & UHCI_PTR_DEPTH));
 	}
 	mb();
 	spin_unlock_irqrestore (&s->td_lock, xxx);
@@ -295,7 +300,7 @@
 	next = list_entry (td->horizontal.next, uhci_desc_t, horizontal);
 	list_add (&new->horizontal, &td->horizontal);
 	new->hw.td.link = td->hw.td.link;
-	td->hw.td.link = virt_to_bus (new);
+	td->hw.td.link = cpu_to_le32(new->dma_addr);
 	mb();
 	spin_unlock_irqrestore (&s->td_lock, flags);	
 	
@@ -340,29 +345,24 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static int delete_desc (uhci_desc_t *element)
+_static int delete_desc (uhci_t *s, uhci_desc_t *element)
 {
-#ifdef DEBUG_SLAB
-	kmem_cache_free(uhci_desc_kmem, element);
-#else
-	kfree (element);
-#endif
+	pci_pool_free(s->desc_pool, element, element->dma_addr);
 	return 0;
 }
 /*-------------------------------------------------------------------*/
 // Allocates qh element
-_static int alloc_qh (uhci_desc_t ** new)
+_static int alloc_qh (uhci_t *s, uhci_desc_t ** new)
 {
-#ifdef DEBUG_SLAB
-	*new= kmem_cache_alloc(uhci_desc_kmem, SLAB_FLAG);
-#else
-	*new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), KMALLOC_FLAG);
-#endif	
+	dma_addr_t dma_handle;
+
+	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
 	if (!*new)
 		return -ENOMEM;
 	memset (*new, 0, sizeof (uhci_desc_t));
-	(*new)->hw.qh.head = UHCI_PTR_TERM;
-	(*new)->hw.qh.element = UHCI_PTR_TERM;
+	(*new)->dma_addr = dma_handle;
+	(*new)->hw.qh.head = cpu_to_le32(UHCI_PTR_TERM);
+	(*new)->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM);
 	(*new)->type = QH_TYPE;
 	
 	mb();
@@ -387,16 +387,16 @@
 		// (OLD) (POS) -> (OLD) (NEW) (POS)
 		old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal);
 		list_add_tail (&new->horizontal, &pos->horizontal);
-		new->hw.qh.head = MAKE_QH_ADDR (pos) ;
-		if (!(old->hw.qh.head & UHCI_PTR_TERM))
-			old->hw.qh.head = MAKE_QH_ADDR (new) ;
+		new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (pos)) ;
+		if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM)))
+			old->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ;
 	}
 	else {
 		// (POS) (OLD) -> (POS) (NEW) (OLD)
 		old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal);
 		list_add (&new->horizontal, &pos->horizontal);
-		new->hw.qh.head = MAKE_QH_ADDR (old);
-		pos->hw.qh.head = MAKE_QH_ADDR (new) ;
+		new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (old));
+		pos->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ;
 	}
 
 	mb ();
@@ -418,7 +418,7 @@
 	prev->hw.qh.head = element->hw.qh.head;
 
 	dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, 
-	    list_entry (element->horizontal.next, uhci_desc_t, horizontal),element->hw.qh.head &~15);
+	    list_entry (element->horizontal.next, uhci_desc_t, horizontal),le32_to_cpu(element->hw.qh.head) &~15);
 	
 	list_del(&element->horizontal);
 
@@ -439,15 +439,15 @@
 		td = list_entry (p, uhci_desc_t, vertical);
 		dbg("unlink td @ %p",td);
 		unlink_td (s, td, 0); // no physical unlink
-		delete_desc (td);
+		delete_desc (s, td);
 	}
 
-	delete_desc (qh);
+	delete_desc (s, qh);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static void clean_td_chain (uhci_desc_t *td)
+_static void clean_td_chain (uhci_t *s, uhci_desc_t *td)
 {
 	struct list_head *p;
 	uhci_desc_t *td1;
@@ -457,18 +457,18 @@
 	
 	while ((p = td->horizontal.next) != &td->horizontal) {
 		td1 = list_entry (p, uhci_desc_t, horizontal);
-		delete_desc (td1);
+		delete_desc (s, td1);
 	}
 	
-	delete_desc (td);
+	delete_desc (s, td);
 }
 
 /*-------------------------------------------------------------------*/
 _static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer)
 {
-	td->hw.td.status = status;
-	td->hw.td.info = info;
-	td->hw.td.buffer = buffer;
+	td->hw.td.status = cpu_to_le32(status);
+	td->hw.td.info = cpu_to_le32(info);
+	td->hw.td.buffer = cpu_to_le32(buffer);
 }
 /*-------------------------------------------------------------------*/
 // Removes ALL qhs in chain (paranoia!)
@@ -485,24 +485,25 @@
 	if (s->td32ms) {
 	
 		unlink_td(s,s->td32ms,1);
-		delete_desc(s->td32ms);
+		delete_desc(s, s->td32ms);
 	}
 
 	for (n = 0; n < 8; n++) {
 		td = s->int_chain[n];
-		clean_td_chain (td);
+		clean_td_chain (s, td);
 	}
 
 	if (s->iso_td) {
 		for (n = 0; n < 1024; n++) {
 			td = s->iso_td[n];
-			clean_td_chain (td);
+			clean_td_chain (s, td);
 		}
 		kfree (s->iso_td);
 	}
 
 	if (s->framelist)
-		free_page ((unsigned long) s->framelist);
+		pci_free_consistent(s->uhci_pci, PAGE_SIZE,
+				    s->framelist, s->framelist_dma);
 
 	if (s->control_chain) {
 		// completed init_skel?
@@ -519,14 +520,20 @@
 	}
 	else {
 		if (s->ls_control_chain)
-			delete_desc (s->ls_control_chain);
+			delete_desc (s, s->ls_control_chain);
 		if (s->control_chain)
-			 delete_desc(s->control_chain);
+			 delete_desc(s, s->control_chain);
 		if (s->bulk_chain)
-			delete_desc (s->bulk_chain);
+			delete_desc (s, s->bulk_chain);
 		if (s->chain_end)
-			delete_desc (s->chain_end);
+			delete_desc (s, s->chain_end);
+	}
+
+	if (s->desc_pool) {
+		pci_pool_destroy(s->desc_pool);
+		s->desc_pool = NULL;
 	}
+
 	dbg("cleanup_skel finished");	
 }
 /*-------------------------------------------------------------------*/
@@ -539,13 +546,22 @@
 	
 	dbg("init_skel");
 	
-	s->framelist = (__u32 *) get_free_page (GFP_KERNEL);
+	s->framelist = pci_alloc_consistent(s->uhci_pci, PAGE_SIZE,
+					    &s->framelist_dma);
 
 	if (!s->framelist)
 		return -ENOMEM;
 
 	memset (s->framelist, 0, 4096);
 
+	dbg("creating descriptor pci_pool");
+
+	s->desc_pool = pci_pool_create("uhci_desc", s->uhci_pci,
+				       sizeof(uhci_desc_t), 16, 0,
+				       GFP_DMA | GFP_ATOMIC);	
+	if (!s->desc_pool)
+		goto init_skel_cleanup;
+
 	dbg("allocating iso desc pointer list");
 	s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL);
 	
@@ -560,33 +576,33 @@
 	dbg("allocating iso descs");
 	for (n = 0; n < 1024; n++) {
 	 	// allocate skeleton iso/irq-tds
-		ret = alloc_td (&td, 0);
+		ret = alloc_td (s, &td, 0);
 		if (ret)
 			goto init_skel_cleanup;
 		s->iso_td[n] = td;
-		s->framelist[n] = ((__u32) virt_to_bus (td));
+		s->framelist[n] = cpu_to_le32((__u32) td->dma_addr);
 	}
 
 	dbg("allocating qh: chain_end");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	
 	if (ret)
 		goto init_skel_cleanup;
 				
 	s->chain_end = qh;
 
-	ret = alloc_td (&td, 0);
+	ret = alloc_td (s, &td, 0);
 
 	if (ret)
 		goto init_skel_cleanup;
 	
 	fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
 	insert_td (s, qh, td, 0);
-	qh->hw.qh.element &= ~UHCI_PTR_TERM; // remove TERM bit
+	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // remove TERM bit
 	s->td1ms=td;
 
 	dbg("allocating qh: bulk_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -594,7 +610,7 @@
 	s->bulk_chain = qh;
 
 	dbg("allocating qh: control_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -603,11 +619,11 @@
 
 #ifdef	CONFIG_USB_UHCI_HIGH_BANDWIDTH
 	// disabled reclamation loop
-	s->chain_end->hw.qh.head=virt_to_bus(s->control_chain) | UHCI_PTR_QH | UHCI_PTR_TERM;
+	s->chain_end->hw.qh.head = cpu_to_le32(s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM);
 #endif
 
 	dbg("allocating qh: ls_control_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -622,15 +638,15 @@
 	for (n = 0; n < 8; n++) {
 		uhci_desc_t *td;
 
-		alloc_td (&td, 0);
+		alloc_td (s, &td, 0);
 		if (!td)
 			goto init_skel_cleanup;
 		s->int_chain[n] = td;
 		if (n == 0) {
-			s->int_chain[0]->hw.td.link = virt_to_bus (s->ls_control_chain) | UHCI_PTR_QH;
+			s->int_chain[0]->hw.td.link = cpu_to_le32(s->ls_control_chain->dma_addr | UHCI_PTR_QH);
 		}
 		else {
-			s->int_chain[n]->hw.td.link = virt_to_bus (s->int_chain[0]);
+			s->int_chain[n]->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr);
 		}
 	}
 
@@ -639,16 +655,17 @@
 	for (n = 0; n < 1024; n++) {
 		// link all iso-tds to the interrupt chains
 		int m, o;
-		dbg("framelist[%i]=%x",n,s->framelist[n]);
+		dbg("framelist[%i]=%x",n,le32_to_cpu(s->framelist[n]));
 		if ((n&127)==127) 
-			((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus(s->int_chain[0]);
+			((uhci_desc_t*) s->iso_td[n])->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr);
 		else 
 			for (o = 1, m = 2; m <= 128; o++, m += m)
 				if ((n & (m - 1)) == ((m - 1) / 2))
-					((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
+					((uhci_desc_t*) s->iso_td[n])->hw.td.link =
+						cpu_to_le32(s->int_chain[o]->dma_addr);
 	}
 
-	ret = alloc_td (&td, 0);
+	ret = alloc_td (s, &td, 0);
 
 	if (ret)
 		goto init_skel_cleanup;
@@ -689,12 +706,12 @@
 	}
 
 	dbg("uhci_submit_control start");
-	alloc_qh (&qh);		// alloc qh for this request
+	alloc_qh (s, &qh);		// alloc qh for this request
 
 	if (!qh)
 		return -ENOMEM;
 
-	alloc_td (&td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
+	alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
 
 	if (!td) {
 		delete_qh (s, qh);
@@ -709,7 +726,7 @@
 		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
 
 	/*  Build the TD for the control request, try forever, 8 bytes of data */
-	fill_td (td, status, destination | (7 << 21), virt_to_bus (urb->setup_packet));
+	fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma);
 
 	insert_td (s, qh, td, 0);	// queue 'setup stage'-td in qh
 #if 0
@@ -732,19 +749,18 @@
 	while (len > 0) {
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
-		if (!td) {
-			delete_qh (s, qh);
-			return -ENOMEM;
-		}
+		alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);
+		if (!td)
+			goto fail_unmap_enomem;
 
 		if (pktsze > maxsze)
 			pktsze = maxsze;
 
 		destination ^= 1 << TD_TOKEN_TOGGLE;	// toggle DATA0/1
 
+		// Status, pktsze bytes of data
 		fill_td (td, status, destination | ((pktsze - 1) << 21),
-			 virt_to_bus (data));	// Status, pktsze bytes of data
+			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
 
 		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue 'data stage'-td in qh
 
@@ -764,12 +780,11 @@
 
 	destination |= 1 << TD_TOKEN_TOGGLE;	/* End in Data1 */
 
-	alloc_td (&td, UHCI_PTR_DEPTH);
+	alloc_td (s, &td, UHCI_PTR_DEPTH);
 	
-	if (!td) {
-		delete_qh (s, qh);
-		return -ENOMEM;
-	}
+	if (!td)
+		goto fail_unmap_enomem;
+
 	status &=~TD_CTRL_SPD;
 
 	/* no limit on errors on final packet , 0 bytes of data */
@@ -783,7 +798,7 @@
 	urb->status = -EINPROGRESS;
 	queue_urb (s, urb);	// queue before inserting in desc chain
 
-	qh->hw.qh.element &= ~UHCI_PTR_TERM;
+	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);
 
 	//uhci_show_queue(qh);
 	/* Start it up... put low speed first */
@@ -794,6 +809,10 @@
 
 	dbg("uhci_submit_control end");
 	return 0;
+
+fail_unmap_enomem:
+	delete_qh(s, qh);
+	return -ENOMEM;
 }
 /*-------------------------------------------------------------------*/
 // For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh)
@@ -829,15 +848,15 @@
 	upriv = (urb_priv_t*)urb->hcpriv;
 
 	if (!bulk_urb) {
-		alloc_qh (&qh);		// get qh for this request
+		alloc_qh (s, &qh);		// get qh for this request
 		
 		if (!qh)
 			return -ENOMEM;
 
 		if (urb->transfer_flags & USB_QUEUE_BULK) {
-			alloc_qh(&nqh); // placeholder for clean unlink
+			alloc_qh(s, &nqh); // placeholder for clean unlink
 			if (!nqh) {
-				delete_desc (qh);
+				delete_desc (s, qh);
 				return -ENOMEM;
 			}
 			upriv->next_qh = nqh;
@@ -853,17 +872,17 @@
 	}
 
 	if (urb->transfer_flags & USB_QUEUE_BULK) {
-		alloc_qh (&bqh); // "bottom" QH,
+		alloc_qh (s, &bqh); // "bottom" QH,
 		
 		if (!bqh) {
 			if (!bulk_urb) { 
-				delete_desc(qh);
-				delete_desc(nqh);
+				delete_desc(s, qh);
+				delete_desc(s, nqh);
 			}
 			return -ENOMEM;
 		}
-		bqh->hw.qh.element = UHCI_PTR_TERM;
-		bqh->hw.qh.head = virt_to_bus(nqh) | UHCI_PTR_QH; // element
+		bqh->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM);
+		bqh->hw.qh.head = cpu_to_le32(nqh->dma_addr | UHCI_PTR_QH); // element
 		upriv->bottom_qh = bqh;
 	}
 	queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh);
@@ -882,7 +901,7 @@
 	do {					// TBD: Really allow zero-length packets?
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
+		alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);
 
 		if (!td) {
 			delete_qh (s, qh);
@@ -896,7 +915,8 @@
 		info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
 			(usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
 
-		fill_td (td, status, info, virt_to_bus (data));
+		fill_td (td, status, info,
+			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
 
 		data += pktsze;
 		len -= pktsze;
@@ -904,7 +924,7 @@
 		last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET)));
 
 		if (last)
-			td->hw.td.status |= TD_CTRL_IOC;	// last one generates INT
+			td->hw.td.status |= cpu_to_le32(TD_CTRL_IOC);	// last one generates INT
 
 		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);
 		if (!first_td)
@@ -925,9 +945,9 @@
 	queue_urb_unlocked (s, urb);
 	
 	if (urb->transfer_flags & USB_QUEUE_BULK)
-		qh->hw.qh.element = virt_to_bus (first_td);
+		qh->hw.qh.element = cpu_to_le32(first_td->dma_addr);
 	else
-		qh->hw.qh.element &= ~UHCI_PTR_TERM;    // arm QH
+		qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);    // arm QH
 
 	if (!bulk_urb) { 					// new bulk queue	
 		if (urb->transfer_flags & USB_QUEUE_BULK) {
@@ -964,7 +984,7 @@
 	while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
 				td = list_entry (p, uhci_desc_t, desc_list);
 				list_del (p);
-				delete_desc (td);
+				delete_desc (s, td);
 	}
 }
 /*-------------------------------------------------------------------*/
@@ -996,7 +1016,7 @@
 				spin_lock_irqsave (&s->qh_lock, flags);
 				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
 				prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical);
-				prevtd->hw.td.link = virt_to_bus(priv->bottom_qh) | UHCI_PTR_QH; // skip current qh
+				prevtd->hw.td.link = cpu_to_le32(priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh
 				mb();
 				queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd);
 				spin_unlock_irqrestore (&s->qh_lock, flags);
@@ -1039,7 +1059,7 @@
 			if (!priv->prev_queued_urb) { // top QH
 				
 				prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal);
-				prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH;
+				prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH);
 				list_del (&qh->horizontal);  // remove this qh form horizontal chain
 				list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain
 			}
@@ -1052,7 +1072,7 @@
 				ppriv->bottom_qh = bnqh;
 				ppriv->next_queued_urb = nurb;				
 				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
-				prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH;
+				prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH);
 			}
 
 			mb();
@@ -1083,6 +1103,38 @@
 		}
 	}	
 }
+
+_static void uhci_urb_dma_sync(uhci_t *s, urb_t *urb, urb_priv_t *urb_priv)
+{
+	if (urb_priv->setup_packet_dma)
+		pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma,
+				    sizeof(devrequest), PCI_DMA_TODEVICE);
+
+	if (urb_priv->transfer_buffer_dma)
+		pci_dma_sync_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
+				    urb->transfer_buffer_length,
+				    usb_pipein(urb->pipe) ?
+				    PCI_DMA_FROMDEVICE :
+				    PCI_DMA_TODEVICE);
+}
+
+_static void uhci_urb_dma_unmap(uhci_t *s, urb_t *urb, urb_priv_t *urb_priv)
+{
+	if (urb_priv->setup_packet_dma) {
+		pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma,
+				 sizeof(devrequest), PCI_DMA_TODEVICE);
+		urb_priv->setup_packet_dma = 0;
+	}
+	if (urb_priv->transfer_buffer_dma) {
+		pci_unmap_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
+				 urb->transfer_buffer_length,
+				 usb_pipein(urb->pipe) ?
+				 PCI_DMA_FROMDEVICE :
+				 PCI_DMA_TODEVICE);
+		urb_priv->transfer_buffer_dma = 0;
+	}
+}
+
 /*-------------------------------------------------------------------*/
 // unlinks an urb by dequeuing its qh, waits some frames and forgets it
 _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
@@ -1133,6 +1185,8 @@
 			uhci_wait_ms(1);
 		}
 		
+		uhci_urb_dma_unmap(s, urb, urb->hcpriv);
+
 #ifdef DEBUG_SLAB
 		kmem_cache_free (urb_priv_kmem, urb->hcpriv);
 #else
@@ -1210,6 +1264,7 @@
 			urb_priv = urb->hcpriv;
 			list_del (&urb->urb_list);
 			
+			uhci_urb_dma_sync(s, urb, urb_priv);
 			if (urb->complete) {
 				spin_unlock(&s->urb_list_lock);
 				urb->dev = NULL;
@@ -1226,6 +1281,8 @@
 				break;
 			}
 	
+			uhci_urb_dma_unmap(s, urb, urb_priv);
+
 			usb_dec_dev_use (dev);
 #ifdef DEBUG_SLAB
 			kmem_cache_free (urb_priv_kmem, urb_priv);
@@ -1452,7 +1509,7 @@
 	if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)))
 		return -EINVAL;
 
-	ret = alloc_td (&td, UHCI_PTR_DEPTH);
+	ret = alloc_td (s, &td, UHCI_PTR_DEPTH);
 
 	if (ret)
 		return -ENOMEM;
@@ -1466,7 +1523,7 @@
 
 	info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
 
-	fill_td (td, status, info, virt_to_bus (urb->transfer_buffer));
+	fill_td (td, status, info, urb_priv->transfer_buffer_dma);
 	list_add_tail (&td->desc_list, &urb_priv->desc_list);
 
 	urb->status = -EINPROGRESS;
@@ -1524,14 +1581,14 @@
 		}
 		else
 #endif
-		ret = alloc_td (&td, UHCI_PTR_DEPTH);
+		ret = alloc_td (s, &td, UHCI_PTR_DEPTH);
 
 		if (ret) {
 			int i;	// Cleanup allocated TDs
 
 			for (i = 0; i < n; n++)
 				if (tdm[i])
-					 delete_desc(tdm[i]);
+					 delete_desc(s, tdm[i]);
 			kfree (tdm);
 			goto err;
 		}
@@ -1554,7 +1611,7 @@
 			status |= TD_CTRL_IOC;
 
 		fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21),
-			 virt_to_bus (urb->transfer_buffer + urb->iso_frame_desc[n].offset));
+			 urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset);
 		list_add_tail (&td->desc_list, &urb_priv->desc_list);
 	
 		if (n == last) {
@@ -1663,6 +1720,22 @@
 	urb_priv->bottom_qh = NULL;
 	urb_priv->next_qh = NULL;
 	
+	if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
+		urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet,
+							    sizeof(devrequest), PCI_DMA_TODEVICE);
+	else
+		urb_priv->setup_packet_dma = 0;
+
+	if (urb->transfer_buffer_length)
+		urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci,
+							       urb->transfer_buffer,
+							       urb->transfer_buffer_length,
+							       usb_pipein(urb->pipe) ?
+							       PCI_DMA_FROMDEVICE :
+							       PCI_DMA_TODEVICE);
+	else
+		urb_priv->transfer_buffer_dma = 0;
+
 	if (usb_pipetype (urb->pipe) == PIPE_BULK) {
 	
 		if (queued_urb) {
@@ -1724,6 +1797,7 @@
 	dbg("submit_urb: scheduled with ret: %d", ret);
 	
 	if (ret != 0) {
+		uhci_urb_dma_unmap(s, urb, urb_priv);
 		usb_dec_dev_use (urb->dev);
 #ifdef DEBUG_SLAB
 		kmem_cache_free(urb_priv_kmem, urb_priv);
@@ -2277,7 +2351,7 @@
 	 */
 
 	if (urb_priv->flags && 
-		((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) 
+		((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) ||(!(last_desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE))))) 
 		goto transfer_finished;
 
 	urb->actual_length=0;
@@ -2285,15 +2359,15 @@
 	for (; p != &qh->vertical; p = p->next) {
 		desc = list_entry (p, uhci_desc_t, vertical);
 
-		if (desc->hw.td.status & TD_CTRL_ACTIVE) {	// do not process active TDs
+		if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) {	// do not process active TDs
 			if (mode==2) // if called from async_unlink
 				uhci_clean_transfer(s, urb, qh, mode);
 			return ret;
 		}
 	
-		actual_length = (desc->hw.td.status + 1) & 0x7ff;		// extract transfer parameters from TD
-		maxlength = (((desc->hw.td.info >> 21) & 0x7ff) + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff;		// extract transfer parameters from TD
+		maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff;
+		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
 
 		if (status == -EPIPE) { 		// see if EP is stalled
 			// set up stalled condition
@@ -2307,7 +2381,7 @@
 			urb->error_count++;
 			break;
 		}
-		else if ((desc->hw.td.info & 0xff) != USB_PID_SETUP)
+		else if ((le32_to_cpu(desc->hw.td.info) & 0xff) != USB_PID_SETUP)
 			urb->actual_length += actual_length;
 
 		// got less data than requested
@@ -2320,9 +2394,9 @@
 
 			// short read during control-IN: re-start status stage
 			if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) {
-				if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
+				if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) {
 			
-					qh->hw.qh.element = virt_to_bus (last_desc);  // re-trigger status stage
+					qh->hw.qh.element = cpu_to_le32(last_desc->dma_addr);  // re-trigger status stage
 					dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
 					//uhci_show_td (desc);
 					//uhci_show_td (last_desc);
@@ -2331,14 +2405,14 @@
 				}
 			}
 			// all other cases: short read is OK
-			data_toggle = uhci_toggle (desc->hw.td.info);
+			data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
 			break;
 		}
 		else if (status)
 			goto is_error;
 
-		data_toggle = uhci_toggle (desc->hw.td.info);
-		queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle);      
+		data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
+		queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, le32_to_cpu(desc->hw.td.status),status, data_toggle);      
 
 	}
 
@@ -2375,20 +2449,20 @@
 	{
 		desc = list_entry (p, uhci_desc_t, desc_list);
 
-		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
+		if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) {
 			// do not process active TDs
-			//dbg("TD ACT Status @%p %08x",desc,desc->hw.td.status);
+			//dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status));
 			break;
 		}
 
-		if (!desc->hw.td.status & TD_CTRL_IOC) {
+		if (!desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC)) {
 			// do not process one-shot TDs, no recycling
 			break;
 		}
 		// extract transfer parameters from TD
 
-		actual_length = (desc->hw.td.status + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff;
+		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
 
 		// see if EP is stalled
 		if (status == -EPIPE) {
@@ -2406,6 +2480,7 @@
 			urb->actual_length = actual_length;
 
 	recycle:
+		uhci_urb_dma_sync(s, urb, urb->hcpriv);
 		if (urb->complete) {
 			//dbg("process_interrupt: calling completion, status %i",status);
 			urb->status = status;
@@ -2428,23 +2503,23 @@
 			// Recycle INT-TD if interval!=0, else mark TD as one-shot
 			if (urb->interval) {
 				
-				desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
+				desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
 				if (status==0) {
 					((urb_priv_t*)urb->hcpriv)->started=jiffies;
-					desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+					desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
 					usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
 				} else {
-					desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+					desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
 				}
-				desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
-					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+				desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
 				mb();
 			}
 			else {
 				uhci_unlink_urb_async(s, urb);
-				desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
+				desc->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); // inactivate TD
 			}
 		}
 	}
@@ -2462,23 +2537,23 @@
 	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
 	dbg("urb contains iso request");
-	if ((desc->hw.td.status & TD_CTRL_ACTIVE) && !mode)
+	if ((desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) && !mode)
 		return -EXDEV;	// last TD not finished
 
 	urb->error_count = 0;
 	urb->actual_length = 0;
 	urb->status = 0;
 	dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s),
-	    urb->number_of_packets,mode,desc->hw.td.status);
+	    urb->number_of_packets,mode,le32_to_cpu(desc->hw.td.status));
 
 	for (i = 0; p != &urb_priv->desc_list;  i++) {
 		desc = list_entry (p, uhci_desc_t, desc_list);
 		
 		//uhci_show_td(desc);
-		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
+		if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) {
 			// means we have completed the last TD, but not the TDs before
-			desc->hw.td.status &= ~TD_CTRL_ACTIVE;
-			dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status);
+			desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE);
+			dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status));
 			ret = -EXDEV;
 			urb->iso_frame_desc[i].status = ret;
 			unlink_td (s, desc, 1);
@@ -2495,15 +2570,8 @@
 			goto err;
 		}
 
-		if (urb->iso_frame_desc[i].offset + urb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) {
-			// Hm, something really weird is going on
-			dbg("Pointer Paranoia: %p!=%p", urb->iso_frame_desc[i].offset + urb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
-			ret = -EINVAL;
-			urb->iso_frame_desc[i].status = ret;
-			goto err;
-		}
-		urb->iso_frame_desc[i].actual_length = (desc->hw.td.status + 1) & 0x7ff;
-		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		urb->iso_frame_desc[i].actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff;
+		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
 		urb->actual_length += urb->iso_frame_desc[i].actual_length;
 
 	      err:
@@ -2513,11 +2581,11 @@
 			urb->status = urb->iso_frame_desc[i].status;
 		}
 		dbg("process_iso: %i: len:%d %08x status:%x",
-		     i, urb->iso_frame_desc[i].actual_length, desc->hw.td.status,urb->iso_frame_desc[i].status);
+		     i, urb->iso_frame_desc[i].actual_length, le32_to_cpu(desc->hw.td.status),urb->iso_frame_desc[i].status);
 
 		list_del (p);
 		p = p->next;
-		delete_desc (desc);
+		delete_desc (s, desc);
 	}
 	
 	dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
@@ -2552,6 +2620,7 @@
 	}
 
 	if (urb->status != -EINPROGRESS) {
+		urb_priv_t *urb_priv;
 		struct usb_device *usb_dev;
 		
 		usb_dev=urb->dev;
@@ -2567,10 +2636,14 @@
 		dbg("dequeued urb: %p", urb);
 		dequeue_urb (s, urb);
 
+		urb_priv = urb->hcpriv;
+
+		uhci_urb_dma_unmap(s, urb, urb_priv);
+
 #ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, urb->hcpriv);
+		kmem_cache_free(urb_priv_kmem, urb_priv);
 #else
-		kfree (urb->hcpriv);
+		kfree (urb_priv);
 #endif
 
 		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {  // process_interrupt does completion on its own		
@@ -2769,7 +2842,7 @@
 
 	/* Start at frame 0 */
 	outw (0, io_addr + USBFRNUM);
-	outl (virt_to_bus (s->framelist), io_addr + USBFLBASEADD);
+	outl (s->framelist_dma, io_addr + USBFLBASEADD);
 
 	/* Run and mark it configured with a 64-byte max packet */
 	outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
@@ -2823,6 +2896,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 _static void
 uhci_pci_suspend (struct pci_dev *dev)
 {
@@ -2834,7 +2908,7 @@
 {
 	start_hc((uhci_t *) dev->driver_data);
 }
-
+#endif
 
 _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
 {
@@ -3012,19 +3086,10 @@
 	int retval;
 
 #ifdef DEBUG_SLAB
-
-	uhci_desc_kmem = kmem_cache_create("uhci_desc", sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	
-	if(!uhci_desc_kmem) {
-		err("kmem_cache_create for uhci_desc failed (out of memory)");
-		return -ENOMEM;
-	}
-
 	urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	
 	if(!urb_priv_kmem) {
 		err("kmem_cache_create for urb_priv_t failed (out of memory)");
-		kmem_cache_destroy(uhci_desc_kmem);
 		return -ENOMEM;
 	}
 #endif	
@@ -3040,11 +3105,12 @@
 	if (retval < 0 ) {
 		if (kmem_cache_destroy(urb_priv_kmem))
 			err("urb_priv_kmem remained");
-		if (kmem_cache_destroy(uhci_desc_kmem))
-			err("uhci_desc_kmem remained");
 	}
 #endif
 	
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
 	return retval;
 }
 
@@ -3053,9 +3119,6 @@
 	pci_unregister_driver (&uhci_pci_driver);
 	
 #ifdef DEBUG_SLAB
-	if(kmem_cache_destroy(uhci_desc_kmem))
-		err("uhci_desc_kmem remained");
-
 	if(kmem_cache_destroy(urb_priv_kmem))
 		err("urb_priv_kmem remained");
 #endif
@@ -3065,6 +3128,6 @@
 module_exit (uhci_hcd_cleanup);
 
 
-MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
-MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h
--- v2.4.4/linux/drivers/usb/usb-uhci.h	Mon May 15 12:05:15 2000
+++ linux/drivers/usb/usb-uhci.h	Wed May 16 10:31:27 2001
@@ -146,6 +146,7 @@
 		uhci_qh_t qh;
 	} hw;
 	uhci_desc_type_t type;
+	dma_addr_t dma_addr;
 	struct list_head horizontal;
 	struct list_head vertical;
 	struct list_head desc_list;
@@ -154,6 +155,8 @@
 
 typedef struct {
 	struct list_head desc_list;	// list pointer to all corresponding TDs/QHs associated with this request
+	dma_addr_t setup_packet_dma;
+	dma_addr_t transfer_buffer_dma;
 	unsigned long started;
 	urb_t *next_queued_urb;         // next queued urb for this EP
 	urb_t *prev_queued_urb;
@@ -195,6 +198,7 @@
 	struct usb_bus *bus;	// our bus
 
 	__u32 *framelist;
+	dma_addr_t framelist_dma;
 	uhci_desc_t **iso_td;
 	uhci_desc_t *int_chain[8];
 	uhci_desc_t *ls_control_chain;
@@ -213,11 +217,12 @@
 	long timeout_check;
 	int timeout_urbs;
 	struct pci_dev *uhci_pci;
+	struct pci_pool *desc_pool;
 } uhci_t, *puhci_t;
 
 
-#define MAKE_TD_ADDR(a) (virt_to_bus(a)&~UHCI_PTR_QH)
-#define MAKE_QH_ADDR(a) (virt_to_bus(a)|UHCI_PTR_QH)
+#define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH)
+#define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH)
 #define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM))
 
 /* ------------------------------------------------------------------------------------ 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.4.4/linux/drivers/usb/usb.c	Wed Apr 25 14:10:47 2001
+++ linux/drivers/usb/usb.c	Sat Apr 28 11:28:09 2001
@@ -569,7 +569,7 @@
  * The most specific match specifiers use device descriptor
  * data.  These are commonly used with product-specific matches;
  * the USB_DEVICE macro lets you provide vendor and product IDs,
- * and you can also matche against ranges of product revisions.
+ * and you can also match against ranges of product revisions.
  * These are widely used for devices with application or vendor
  * specific bDeviceClass values.
  *
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.4.4/linux/drivers/usb/usbkbd.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/usbkbd.c	Mon May 21 15:02:06 2001
@@ -35,8 +35,15 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB HID Boot Protocol keyboard driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION ""
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 static unsigned char usb_kbd_keycode[256] = {
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
@@ -273,6 +280,8 @@
 static int __init usb_kbd_init(void)
 {
 	usb_register(&usb_kbd_driver);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
--- v2.4.4/linux/drivers/usb/usbmouse.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/usbmouse.c	Mon May 21 15:02:06 2001
@@ -35,8 +35,15 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB HID Boot Protocol mouse driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.6"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 struct usb_mouse {
 	signed char data[8];
@@ -187,6 +194,8 @@
 static int __init usb_mouse_init(void)
 {
 	usb_register(&usb_mouse_driver);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c
--- v2.4.4/linux/drivers/usb/uss720.c	Sun Mar 25 18:14:21 2001
+++ linux/drivers/usb/uss720.c	Mon May 21 15:02:06 2001
@@ -33,6 +33,7 @@
  *   0.4  13.08.99  Added Vendor/Product ID of Brad Hard's cable
  *   0.5  20.09.99  usb_control_msg wrapper used
  *        Nov01.00  usb_device_table support by Adam J. Richter
+ *        08.04.01  Identify version on module load.  gb
  *
  */
 
@@ -44,6 +45,13 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5"
+#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
+
 /* --------------------------------------------------------------------- */
 
 struct parport_uss720_private {
@@ -643,16 +651,16 @@
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch");
-MODULE_DESCRIPTION("USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip");
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 static int __init uss720_init(void)
 {
 	if (usb_register(&uss720_driver) < 0)
 		return -1;
 
-	printk(KERN_INFO "uss720: USB<->IEEE1284 cable driver v0.4 registered.\n"
-	       KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c
--- v2.4.4/linux/drivers/usb/wacom.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/usb/wacom.c	Mon May 21 15:02:06 2001
@@ -28,6 +28,7 @@
  *	v1.12 (de) - Add support for two more inking pen IDs
  *	v1.14 (vp) - Use new USB device id probing scheme.
  *		     Fix Wacom Graphire mouse wheel
+ *	      (gb) - Identify version on module load.
  */
 
 /*
@@ -57,8 +58,15 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("USB Wacom Graphire and Wacom Intuos tablet driver");
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.14"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
 
 /*
  * Wacom Graphire packet:
@@ -407,6 +415,8 @@
 static int __init wacom_init(void)
 {
 	usb_register(&wacom_driver);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.4/linux/drivers/video/aty.h linux/drivers/video/aty.h
--- v2.4.4/linux/drivers/video/aty.h	Sun Sep 17 09:48:04 2000
+++ linux/drivers/video/aty.h	Wed May 16 10:31:23 2001
@@ -738,6 +738,7 @@
 #define LI_CHIP_ID	0x4c49	/* RAGE LT PRO */
 #define LP_CHIP_ID	0x4c50	/* RAGE LT PRO */
 #define LT_CHIP_ID	0x4c54	/* RAGE LT */
+#define XL_CHIP_ID	0x4752	/* RAGE (XL) */
 #define GT_CHIP_ID	0x4754	/* RAGE (GT) */
 #define GU_CHIP_ID	0x4755	/* RAGE II/II+ (GTB) */
 #define GV_CHIP_ID	0x4756	/* RAGE IIC, PCI */
diff -u --recursive --new-file v2.4.4/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.4.4/linux/drivers/video/atyfb.c	Thu Apr 12 12:10:25 2001
+++ linux/drivers/video/atyfb.c	Wed May 16 10:31:23 2001
@@ -561,6 +561,7 @@
     { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
     { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
     { 0x4c54, 0x4c54, "3D RAGE LT" },
+    { 0x4752, 0x4752, "3D RAGE (XL)" },
     { 0x4754, 0x4754, "3D RAGE (GT)" },
     { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
     { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
@@ -722,7 +723,7 @@
     if (Gx == LB_CHIP_ID || Gx == LD_CHIP_ID || Gx == LI_CHIP_ID ||
     	Gx == LP_CHIP_ID || Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
     	Gx == GI_CHIP_ID || Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID ||
-    	Gx == LM_CHIP_ID || Gx == LN_CHIP_ID)
+    	Gx == LM_CHIP_ID || Gx == LN_CHIP_ID || Gx == XL_CHIP_ID)
     	reset_GTC_3D_engine(info);
 
     /* Reset engine, enable, and clear any engine errors */
@@ -2209,10 +2210,14 @@
     if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
 	  Gx == ET_CHIP_ID ||
 	  ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
-	if (info->ram_type >= SDRAM)
-	    aty_st_pll(DLL_CNTL, 0xa6, info);
-	else
-	    aty_st_pll(DLL_CNTL, 0xa0, info);
+	if (Gx == XL_CHIP_ID) {
+	    aty_st_pll(DLL_CNTL, 0x80, info);
+	} else {
+	    if (info->ram_type >= SDRAM)
+		aty_st_pll(DLL_CNTL, 0xa6, info);
+	    else
+		aty_st_pll(DLL_CNTL, 0xa0, info);
+	}
 	aty_st_pll(VFC_CNTL, 0x1b, info);
 	aty_st_le32(DSP_CONFIG, pll->dsp_config, info);
 	aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info);
@@ -2334,6 +2339,7 @@
 	 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
 	 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
 	 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
+	 (Gx == XL_CHIP_ID) ||
 	 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
 	pll->pll_gen_cntl = 0x04;
     else
@@ -3214,7 +3220,7 @@
 		if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
 		    Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
 		    Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
-		    Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
+		    Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == XL_CHIP_ID)
 			tmp |= 0x2;
 		aty_st_8(DAC_CNTL, tmp, info);
 		aty_st_8(DAC_MASK, 0xff, info);
@@ -3367,6 +3373,9 @@
 		/* RAGE PRO or LT PRO */
 		pll = 230;
 		mclk = 100;
+	    } else if (Gx == XL_CHIP_ID) {
+		pll = 230;
+		mclk = 120;
 	    } else if (Gx == LG_CHIP_ID) {
 		/* Rage LT */
 		pll = 230;
@@ -3801,34 +3810,36 @@
 		j++;
 	    }
 
-	    /*
-	     * Fix PROMs idea of MEM_CNTL settings...
-	     */
-	    mem = aty_ld_le32(MEM_CNTL, info);
-	    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
-	    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
-		!((chip_id >> 24) & 1)) {
-		switch (mem & 0x0f) {
-		    case 3:
-			mem = (mem & ~(0x0f)) | 2;
-			break;
-		    case 7:
-			mem = (mem & ~(0x0f)) | 3;
-			break;
-		    case 9:
-			mem = (mem & ~(0x0f)) | 4;
-			break;
-		    case 11:
-			mem = (mem & ~(0x0f)) | 5;
-			break;
-		    default:
-			break;
-		}
-		if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
-			mem &= ~(0x00700000);
+	    if (pdev->device != XL_CHIP_ID) {
+		    /*
+		     * Fix PROMs idea of MEM_CNTL settings...
+		     */
+		    mem = aty_ld_le32(MEM_CNTL, info);
+		    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
+		    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
+			!((chip_id >> 24) & 1)) {
+			    switch (mem & 0x0f) {
+			    case 3:
+				    mem = (mem & ~(0x0f)) | 2;
+				    break;
+			    case 7:
+				    mem = (mem & ~(0x0f)) | 3;
+				    break;
+			    case 9:
+				    mem = (mem & ~(0x0f)) | 4;
+				    break;
+			    case 11:
+				    mem = (mem & ~(0x0f)) | 5;
+				    break;
+			    default:
+				    break;
+			    }
+			    if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
+				    mem &= ~(0x00700000);
+		    }
+		    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
+		    aty_st_le32(MEM_CNTL, mem, info);
 	    }
-	    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
-	    aty_st_le32(MEM_CNTL, mem, info);
 
 	    /*
 	     * If this is the console device, we will set default video
@@ -3850,7 +3861,7 @@
 	    if (node == pcp->prom_node) {
 
 		struct fb_var_screeninfo *var = &default_var;
-		unsigned int N, P, Q, M, T;
+		unsigned int N, P, Q, M, T, R;
 		u32 v_total, h_total;
 		struct crtc crtc;
 		u8 pll_regs[16];
@@ -3891,7 +3902,7 @@
 		N = pll_regs[7 + (clock_cntl & 3)];
 
 		/*
-		 * PLL Post Devider P (Dependant on CLOCK_CNTL):
+		 * PLL Post Divider P (Dependant on CLOCK_CNTL):
 		 */
 		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
 
@@ -3907,13 +3918,17 @@
 		 * Q = -------
 		 *      2 * R
 		 *
-		 * where R is XTALIN (= 14318 kHz).
+		 * where R is XTALIN (= 14318 or 29498 kHz).
 		 */
-		T = 2 * Q * 14318 / M;
+		if (pdev->device == XL_CHIP_ID)
+			R = 29498;
+		else
+			R = 14318;
+
+		T = 2 * Q * R / M;
 
 		default_var.pixclock = 1000000000 / T;
 	    }
-
 #else /* __sparc__ */
 
 	    info->ati_regbase_phys = 0x7ff000 + addr;
@@ -4297,7 +4312,8 @@
     if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
 	Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
 	Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
-	Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID)
+	Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID ||
+	Gx == XL_CHIP_ID)
 	i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt*/
     aty_st_8(DAC_CNTL, i, info);
     aty_st_8(DAC_MASK, 0xff, info);
diff -u --recursive --new-file v2.4.4/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.4.4/linux/drivers/video/chipsfb.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/video/chipsfb.c	Sat May 19 18:14:38 2001
@@ -29,17 +29,19 @@
 #include <linux/selection.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <asm/io.h>
+
 #ifdef CONFIG_FB_COMPAT_XPMAC
 #include <asm/vc_ioctl.h>
-#endif
-#include <asm/io.h>
-#include <asm/prom.h>
 #include <asm/pci-bridge.h>
+#endif
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
+#ifdef CONFIG_PMAC_PBOOK
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#endif
 
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -56,14 +58,13 @@
 	struct {
 		__u8 red, green, blue;
 	} palette[256];
+	struct pci_dev *pdev;
 	unsigned long frame_buffer_phys;
 	__u8 *frame_buffer;
 	unsigned long blitter_regs_phys;
 	__u32 *blitter_regs;
 	unsigned long blitter_data_phys;
 	__u8 *blitter_data;
-	unsigned long io_base_phys;
-	__u8 *io_base;
 	struct fb_info_chips *next;
 #ifdef CONFIG_PMAC_PBOOK
 	unsigned char *save_framebuffer;
@@ -74,10 +75,10 @@
 };
 
 #define write_ind(num, val, ap, dp)	do { \
-	out_8(p->io_base + (ap), (num)); out_8(p->io_base + (dp), (val)); \
+	outb((num), (ap)); outb((val), (dp)); \
 } while (0)
 #define read_ind(num, var, ap, dp)	do { \
-	out_8(p->io_base + (ap), (num)); var = in_8(p->io_base + (dp)); \
+	outb((num), (ap)); var = inb((dp)); \
 } while (0);
 
 /* extension registers */
@@ -97,10 +98,10 @@
 #define read_sr(num, var)	read_ind(num, var, 0x3c4, 0x3c5)
 /* attribute registers - slightly strange */
 #define write_ar(num, val)	do { \
-	in_8(p->io_base + 0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
+	inb(0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
 } while (0)
 #define read_ar(num, var)	do { \
-	in_8(p->io_base + 0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
+	inb(0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
 } while (0)
 
 static struct fb_info_chips *all_chips;
@@ -117,7 +118,7 @@
  */
 int chips_init(void);
 
-static void chips_of_init(struct device_node *dp);
+static void chips_pci_init(struct pci_dev *dp);
 static int chips_get_fix(struct fb_fix_screeninfo *fix, int con,
 			 struct fb_info *info);
 static int chips_get_var(struct fb_var_screeninfo *var, int con,
@@ -253,29 +254,29 @@
 #endif /* CONFIG_PMAC_BACKLIGHT */
 		/* get the palette from the chip */
 		for (i = 0; i < 256; ++i) {
-			out_8(p->io_base + 0x3c7, i);
+			outb(i, 0x3c7);
 			udelay(1);
-			p->palette[i].red = in_8(p->io_base + 0x3c9);
-			p->palette[i].green = in_8(p->io_base + 0x3c9);
-			p->palette[i].blue = in_8(p->io_base + 0x3c9);
+			p->palette[i].red = inb(0x3c9);
+			p->palette[i].green = inb(0x3c9);
+			p->palette[i].blue = inb(0x3c9);
 		}
 		for (i = 0; i < 256; ++i) {
-			out_8(p->io_base + 0x3c8, i);
+			outb(i, 0x3c8);
 			udelay(1);
-			out_8(p->io_base + 0x3c9, 0);
-			out_8(p->io_base + 0x3c9, 0);
-			out_8(p->io_base + 0x3c9, 0);
+			outb(0, 0x3c9);
+			outb(0, 0x3c9);
+			outb(0, 0x3c9);
 		}
 	} else {
 #ifdef CONFIG_PMAC_BACKLIGHT
 		set_backlight_enable(1);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 		for (i = 0; i < 256; ++i) {
-			out_8(p->io_base + 0x3c8, i);
+			outb(i, 0x3c8);
 			udelay(1);
-			out_8(p->io_base + 0x3c9, p->palette[i].red);
-			out_8(p->io_base + 0x3c9, p->palette[i].green);
-			out_8(p->io_base + 0x3c9, p->palette[i].blue);
+			outb(p->palette[i].red, 0x3c9);
+			outb(p->palette[i].green, 0x3c9);
+			outb(p->palette[i].blue, 0x3c9);
 		}
 	}
 }
@@ -307,11 +308,11 @@
 	p->palette[regno].red = red;
 	p->palette[regno].green = green;
 	p->palette[regno].blue = blue;
-	out_8(p->io_base + 0x3c8, regno);
+	outb(regno, 0x3c8);
 	udelay(1);
-	out_8(p->io_base + 0x3c9, red);
-	out_8(p->io_base + 0x3c9, green);
-	out_8(p->io_base + 0x3c9, blue);
+	outb(red, 0x3c9);
+	outb(green, 0x3c9);
+	outb(blue, 0x3c9);
 
 #ifdef FBCON_HAS_CFB16
 	if (regno < 16)
@@ -388,7 +389,7 @@
 	disp->visual = fix->visual;
 	disp->var = *var;
 
-#if (defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_FB_COMPAT_XPMAC))
+#ifdef CONFIG_FB_COMPAT_XPMAC
 	display_info.depth = bpp;
 	display_info.pitch = fix->line_length;
 #endif
@@ -517,7 +518,7 @@
 
 	for (i = 0; i < N_ELTS(chips_init_xr); ++i)
 		write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
-	out_8(p->io_base + 0x3c2, 0x29); /* set misc output reg */
+	outb(0x29, 0x3c2); /* set misc output reg */
 	for (i = 0; i < N_ELTS(chips_init_sr); ++i)
 		write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
 	for (i = 0; i < N_ELTS(chips_init_gr); ++i)
@@ -545,7 +546,6 @@
 // * 3400 has 1MB (I think).  Don't know if it's expandable.
 // -- Tim Seufert
 	p->fix.smem_len = 0x100000;	// 1MB
-	p->fix.mmio_start = p->io_base_phys;
 	p->fix.type = FB_TYPE_PACKED_PIXELS;
 	p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 	p->fix.line_length = 800;
@@ -607,6 +607,8 @@
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
 	if (!console_fb_info) {
+		unsigned long iobase;
+
 		display_info.height = p->var.yres;
 		display_info.width = p->var.xres;
 		display_info.depth = 8;
@@ -615,8 +617,9 @@
 		strncpy(display_info.name, "chips65550",
 			sizeof(display_info.name));
 		display_info.fb_address = p->frame_buffer_phys;
-		display_info.cmap_adr_address = p->io_base_phys + 0x3c8;
-		display_info.cmap_data_address = p->io_base_phys + 0x3c9;
+		iobase = pci_bus_io_base_phys(p->pdev->bus->number);
+		display_info.cmap_adr_address = iobase + 0x3c8;
+		display_info.cmap_data_address = iobase + 0x3c9;
 		display_info.disp_reg_address = p->blitter_regs_phys;
 		console_fb_info = &p->info;
 	}
@@ -632,35 +635,39 @@
 
 int __init chips_init(void)
 {
-	struct device_node *dp;
+	struct pci_dev *dp = NULL;
 
-	dp = find_devices("chips65550");
-	if (dp != 0)
-		chips_of_init(dp);
-	return 0;
+	while ((dp = pci_find_device(PCI_VENDOR_ID_CT,
+				     PCI_DEVICE_ID_CT_65550, dp)) != NULL)
+		if ((dp->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+			chips_pci_init(dp);
+	return all_chips? 0: -ENODEV;
 }
 
-static void __init chips_of_init(struct device_node *dp)
+static void __init chips_pci_init(struct pci_dev *dp)
 {
 	struct fb_info_chips *p;
-	unsigned long addr;
-	unsigned char bus, devfn;
+	unsigned long addr, size;
 	unsigned short cmd;
 
-	if (dp->n_addrs == 0)
+	if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
+		return;
+	addr = dp->resource[0].start;
+	size = dp->resource[0].end + 1 - addr;
+	if (addr == 0)
 		return;
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
 	if (p == 0)
 		return;
 	memset(p, 0, sizeof(*p));
-	addr = dp->addrs[0].address;
-	if (!request_mem_region(addr, dp->addrs[0].size, "chipsfb")) {
+	if (!request_mem_region(addr, size, "chipsfb")) {
 		kfree(p);
 		return;
 	}
 #ifdef __BIG_ENDIAN
 	addr += 0x800000;	// Use big-endian aperture
 #endif
+	p->pdev = dp;
 	p->frame_buffer_phys = addr;
 	p->frame_buffer = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
 	p->blitter_regs_phys = addr + 0x400000;
@@ -668,14 +675,12 @@
 	p->blitter_data_phys = addr + 0x410000;
 	p->blitter_data = ioremap(addr + 0x410000, 0x10000);
 
-	if (pci_device_loc(dp, &bus, &devfn) == 0) {
-		pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
-		cmd |= 3;	/* enable memory and IO space */
-		pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
-		p->io_base = (__u8 *) pci_io_base(bus);
-		/* XXX really want the physical address here */
-		p->io_base_phys = (unsigned long) pci_io_base(bus);
-	}
+	/* we should use pci_enable_device here, but,
+	   the device doesn't declare its I/O ports in its BARs
+	   so pci_enable_device won't turn on I/O responses */
+	pci_read_config_word(dp, PCI_COMMAND, &cmd);
+	cmd |= 3;	/* enable memory and IO space */
+	pci_write_config_word(dp, PCI_COMMAND, cmd);
 
 	/* Clear the entire framebuffer */
 	memset(p->frame_buffer, 0, 0x100000);
diff -u --recursive --new-file v2.4.4/linux/drivers/video/epson1355fb.c linux/drivers/video/epson1355fb.c
--- v2.4.4/linux/drivers/video/epson1355fb.c	Fri Apr 13 20:31:32 2001
+++ linux/drivers/video/epson1355fb.c	Sun May 20 12:11:39 2001
@@ -19,6 +19,7 @@
  */
 
 #include <asm/io.h>
+#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fb.h>
diff -u --recursive --new-file v2.4.4/linux/drivers/video/sis/sis_main.c linux/drivers/video/sis/sis_main.c
--- v2.4.4/linux/drivers/video/sis/sis_main.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/video/sis/sis_main.c	Fri May  4 15:10:17 2001
@@ -1029,6 +1029,8 @@
 
 	if (heap.pohFreeList == NULL) {
 		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+		if (!poha)
+			return NULL;
 
 		poha->pohaNext = heap.pohaChain;
 		heap.pohaChain = poha;
diff -u --recursive --new-file v2.4.4/linux/fs/Config.in linux/fs/Config.in
--- v2.4.4/linux/fs/Config.in	Thu Apr 12 12:25:53 2001
+++ linux/fs/Config.in	Sun May 20 12:11:38 2001
@@ -39,6 +39,7 @@
 
 tristate 'Minix fs support' CONFIG_MINIX_FS
 
+tristate 'FreeVxFS file system support (VERITAS VxFS(TM) compatible)' CONFIG_VXFS_FS
 tristate 'NTFS file system support (read only)' CONFIG_NTFS_FS
 dep_mbool '  NTFS write support (DANGEROUS)' CONFIG_NTFS_RW $CONFIG_NTFS_FS $CONFIG_EXPERIMENTAL
 
diff -u --recursive --new-file v2.4.4/linux/fs/Makefile linux/fs/Makefile
--- v2.4.4/linux/fs/Makefile	Fri Mar  2 15:16:59 2001
+++ linux/fs/Makefile	Tue May 22 09:35:42 2001
@@ -11,8 +11,8 @@
 mod-subdirs :=	nls
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
-		super.o  block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
-		ioctl.o readdir.o select.o fifo.o locks.o \
+		super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
+		fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
 		dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
 		filesystems.o
 
@@ -38,6 +38,7 @@
 subdir-$(CONFIG_ISO9660_FS)	+= isofs
 subdir-$(CONFIG_DEVFS_FS)	+= devfs
 subdir-$(CONFIG_HFS_FS)		+= hfs
+subdir-$(CONFIG_VXFS_FS)	+= freevxfs
 subdir-$(CONFIG_NFS_FS)		+= nfs
 subdir-$(CONFIG_NFSD)		+= nfsd
 subdir-$(CONFIG_LOCKD)		+= lockd
diff -u --recursive --new-file v2.4.4/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.4.4/linux/fs/binfmt_elf.c	Thu Apr  5 17:13:23 2001
+++ linux/fs/binfmt_elf.c	Sat May 19 18:09:15 2001
@@ -135,12 +135,13 @@
 
 	/*
 	 * Force 16 byte _final_ alignment here for generality.
-	 * Leave an extra 16 bytes free so that on the PowerPC we
-	 * can move the aux table up to start on a 16-byte boundary.
 	 */
-	sp = (elf_addr_t *)((~15UL & (unsigned long)(u_platform)) - 16UL);
+	sp = (elf_addr_t *)(~15UL & (unsigned long)(u_platform));
 	csp = sp;
-	csp -= DLINFO_ITEMS*2 + (k_platform ? 2 : 0);
+	csp -= (1+DLINFO_ITEMS)*2 + (k_platform ? 2 : 0);
+#ifdef DLINFO_ARCH_ITEMS
+	csp -= DLINFO_ARCH_ITEMS*2;
+#endif
 	csp -= envc+1;
 	csp -= argc+1;
 	csp -= (!ibcs ? 3 : 1);	/* argc itself */
@@ -174,6 +175,13 @@
 	NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
 	NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
 	NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
+#ifdef ARCH_DLINFO
+	/* 
+	 * ARCH_DLINFO must come last so platform specific code can enforce
+	 * special alignment requirements on the AUXV if necessary (eg. PPC).
+	 */
+	ARCH_DLINFO;
+#endif
 #undef NEW_AUX_ENT
 
 	sp -= envc+1;
diff -u --recursive --new-file v2.4.4/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.4.4/linux/fs/block_dev.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/block_dev.c	Tue May 22 09:35:42 2001
@@ -31,7 +31,7 @@
 	ssize_t block, blocks;
 	loff_t offset;
 	ssize_t chars;
-	ssize_t written;
+	ssize_t written, retval;
 	struct buffer_head * bhlist[NBUF];
 	size_t size;
 	kdev_t dev = inode->i_rdev;
@@ -41,7 +41,7 @@
 	if (is_read_only(dev))
 		return -EPERM;
 
-	written = write_error = buffercount = 0;
+	retval = written = write_error = buffercount = 0;
 	blocksize = BLOCK_SIZE;
 	if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
 		blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
@@ -61,8 +61,10 @@
 	else
 		size = INT_MAX;
 	while (count>0) {
-		if (block >= size)
-			return written ? written : -ENOSPC;
+		if (block >= size) {
+			retval = -ENOSPC;
+			goto cleanup;
+		}
 		chars = blocksize - offset;
 		if (chars > count)
 			chars=count;
@@ -74,15 +76,19 @@
 			if (chars != blocksize)
 				fn = bread;
 			bh = fn(dev, block, blocksize);
-			if (!bh)
-				return written ? written : -EIO;
+			if (!bh) {
+				retval = -EIO;
+				goto cleanup;
+			}
 			if (!buffer_uptodate(bh))
 				wait_on_buffer(bh);
 		}
 #else
 		bh = getblk(dev, block, blocksize);
-		if (!bh)
-			return written ? written : -EIO;
+		if (!bh) {
+			retval = -EIO;
+			goto cleanup;
+		}
 
 		if (!buffer_uptodate(bh))
 		{
@@ -106,7 +112,8 @@
 		        if (!bhlist[i])
 			{
 			  while(i >= 0) brelse(bhlist[i--]);
-			  return written ? written : -EIO;
+			  retval = -EIO;
+			  goto cleanup;
 		        }
 		      }
 		    }
@@ -115,7 +122,8 @@
 		    wait_on_buffer(bh);
 		    if (!buffer_uptodate(bh)) {
 			  brelse(bh);
-			  return written ? written : -EIO;
+			  retval = -EIO;
+			  goto cleanup;
 		    }
 		  };
 		};
@@ -149,6 +157,7 @@
 		if (write_error)
 			break;
 	}
+	cleanup:
 	if ( buffercount ){
 		ll_rw_block(WRITE, buffercount, bufferlist);
 		for(i=0; i<buffercount; i++){
@@ -158,10 +167,11 @@
 			brelse(bufferlist[i]);
 		}
 	}		
-	filp->f_reada = 1;
+	if(!retval)
+		filp->f_reada = 1;
 	if(write_error)
 		return -EIO;
-	return written;
+	return written ? written : retval;
 }
 
 ssize_t block_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
@@ -382,7 +392,7 @@
 	}
 }
 
-void __init bdev_init(void)
+void __init bdev_cache_init(void)
 {
 	int i;
 	struct list_head *head = bdev_hashtable;
@@ -554,7 +564,6 @@
 {
 	int i;
 	const struct block_device_operations * bdops = NULL;
-	struct super_block * sb;
 
 	i = MAJOR(dev);
 	if (i < MAX_BLKDEV)
@@ -576,11 +585,8 @@
 	printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
 		bdevname(dev));
 
-	sb = get_super(dev);
-	if (sb && invalidate_inodes(sb))
+	if (invalidate_device(dev, 0))
 		printk("VFS: busy inodes on changed media.\n");
-
-	destroy_buffers(dev);
 
 	if (bdops->revalidate)
 		bdops->revalidate(dev);
diff -u --recursive --new-file v2.4.4/linux/fs/buffer.c linux/fs/buffer.c
--- v2.4.4/linux/fs/buffer.c	Fri Apr 27 14:23:25 2001
+++ linux/fs/buffer.c	Tue May 15 00:36:38 2001
@@ -1034,7 +1034,6 @@
 int balance_dirty_state(kdev_t dev)
 {
 	unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit;
-	int shortage;
 
 	dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
 	tot = nr_free_buffer_pages();
@@ -1050,16 +1049,6 @@
 		return 0;
 	}
 
-	/*
-	 * If we are about to get low on free pages and
-	 * cleaning the inactive_dirty pages would help
-	 * fix this, wake up bdflush.
-	 */
-	shortage = free_shortage();
-	if (shortage && nr_inactive_dirty_pages > shortage &&
-			nr_inactive_dirty_pages > freepages.high)
-		return 0;
-
 	return -1;
 }
 
@@ -2578,16 +2567,15 @@
 	return flushed;
 }
 
-struct task_struct *bdflush_tsk = 0;
+DECLARE_WAIT_QUEUE_HEAD(bdflush_wait);
 
 void wakeup_bdflush(int block)
 {
-	if (current != bdflush_tsk) {
-		wake_up_process(bdflush_tsk);
+	if (waitqueue_active(&bdflush_wait))
+		wake_up_interruptible(&bdflush_wait);
 
-		if (block)
-			flush_dirty_buffers(0);
-	}
+	if (block)
+		flush_dirty_buffers(0);
 }
 
 /* 
@@ -2688,7 +2676,6 @@
 	tsk->session = 1;
 	tsk->pgrp = 1;
 	strcpy(tsk->comm, "bdflush");
-	bdflush_tsk = tsk;
 
 	/* avoid getting signals */
 	spin_lock_irq(&tsk->sigmask_lock);
@@ -2703,22 +2690,16 @@
 		CHECK_EMERGENCY_SYNC
 
 		flushed = flush_dirty_buffers(0);
-		if (free_shortage())
-			flushed += page_launder(GFP_KERNEL, 0);
 
 		/*
 		 * If there are still a lot of dirty buffers around,
 		 * skip the sleep and flush some more. Otherwise, we
 		 * go to sleep waiting a wakeup.
 		 */
-		set_current_state(TASK_INTERRUPTIBLE);
 		if (!flushed || balance_dirty_state(NODEV) < 0) {
 			run_task_queue(&tq_disk);
-			schedule();
+			interruptible_sleep_on(&bdflush_wait);
 		}
-		/* Remember to mark us as running otherwise
-		   the next schedule will block. */
-		__set_current_state(TASK_RUNNING);
 	}
 }
 
diff -u --recursive --new-file v2.4.4/linux/fs/char_dev.c linux/fs/char_dev.c
--- v2.4.4/linux/fs/char_dev.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/char_dev.c	Tue May 22 09:35:42 2001
@@ -0,0 +1,114 @@
+/*
+ *  linux/fs/block_dev.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#define HASH_BITS	6
+#define HASH_SIZE	(1UL << HASH_BITS)
+#define HASH_MASK	(HASH_SIZE-1)
+static struct list_head cdev_hashtable[HASH_SIZE];
+static spinlock_t cdev_lock = SPIN_LOCK_UNLOCKED;
+static kmem_cache_t * cdev_cachep;
+
+#define alloc_cdev() \
+	 ((struct char_device *) kmem_cache_alloc(cdev_cachep, SLAB_KERNEL))
+#define destroy_cdev(cdev) kmem_cache_free(cdev_cachep, (cdev))
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct char_device * cdev = (struct char_device *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+	{
+		memset(cdev, 0, sizeof(*cdev));
+		sema_init(&cdev->sem, 1);
+	}
+}
+
+void __init cdev_cache_init(void)
+{
+	int i;
+	struct list_head *head = cdev_hashtable;
+
+	i = HASH_SIZE;
+	do {
+		INIT_LIST_HEAD(head);
+		head++;
+		i--;
+	} while (i);
+
+	cdev_cachep = kmem_cache_create("cdev_cache",
+					 sizeof(struct char_device),
+					 0, SLAB_HWCACHE_ALIGN, init_once,
+					 NULL);
+	if (!cdev_cachep)
+		panic("Cannot create cdev_cache SLAB cache");
+}
+
+/*
+ * Most likely _very_ bad one - but then it's hardly critical for small
+ * /dev and can be fixed when somebody will need really large one.
+ */
+static inline unsigned long hash(dev_t dev)
+{
+	unsigned long tmp = dev;
+	tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2);
+	return tmp & HASH_MASK;
+}
+
+static struct char_device *cdfind(dev_t dev, struct list_head *head)
+{
+	struct list_head *p;
+	struct char_device *cdev;
+	for (p=head->next; p!=head; p=p->next) {
+		cdev = list_entry(p, struct char_device, hash);
+		if (cdev->dev != dev)
+			continue;
+		atomic_inc(&cdev->count);
+		return cdev;
+	}
+	return NULL;
+}
+
+struct char_device *cdget(dev_t dev)
+{
+	struct list_head * head = cdev_hashtable + hash(dev);
+	struct char_device *cdev, *new_cdev;
+	spin_lock(&cdev_lock);
+	cdev = cdfind(dev, head);
+	spin_unlock(&cdev_lock);
+	if (cdev)
+		return cdev;
+	new_cdev = alloc_cdev();
+	if (!new_cdev)
+		return NULL;
+	atomic_set(&new_cdev->count,1);
+	new_cdev->dev = dev;
+	spin_lock(&cdev_lock);
+	cdev = cdfind(dev, head);
+	if (!cdev) {
+		list_add(&new_cdev->hash, head);
+		spin_unlock(&cdev_lock);
+		return new_cdev;
+	}
+	spin_unlock(&cdev_lock);
+	destroy_cdev(new_cdev);
+	return cdev;
+}
+
+void cdput(struct char_device *cdev)
+{
+	if (atomic_dec_and_test(&cdev->count)) {
+		spin_lock(&cdev_lock);
+		list_del(&cdev->hash);
+		spin_unlock(&cdev_lock);
+		destroy_cdev(cdev);
+	}
+}
+
diff -u --recursive --new-file v2.4.4/linux/fs/dcache.c linux/fs/dcache.c
--- v2.4.4/linux/fs/dcache.c	Fri Apr 27 14:23:25 2001
+++ linux/fs/dcache.c	Tue May 22 09:35:42 2001
@@ -1250,6 +1250,9 @@
 kmem_cache_t *bh_cachep;
 EXPORT_SYMBOL(bh_cachep);
 
+extern void bdev_cache_init(void);
+extern void cdev_cache_init(void);
+
 void __init vfs_caches_init(unsigned long mempages)
 {
 	bh_cachep = kmem_cache_create("buffer_head",
@@ -1279,4 +1282,7 @@
 #endif
 
 	dcache_init(mempages);
+	inode_init(mempages);
+	bdev_cache_init();
+	cdev_cache_init();
 }
diff -u --recursive --new-file v2.4.4/linux/fs/devfs/base.c linux/fs/devfs/base.c
--- v2.4.4/linux/fs/devfs/base.c	Tue Apr 17 15:04:10 2001
+++ linux/fs/devfs/base.c	Tue May 22 09:35:42 2001
@@ -2156,7 +2156,6 @@
     int tmp;
     kdev_t dev = MKDEV (de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
     struct block_device_operations *bdops = de->u.fcb.ops;
-    struct super_block * sb;
     extern int warn_no_part;
 
     if ( !S_ISBLK (de->mode) ) return 0;
@@ -2165,10 +2164,8 @@
     if ( !bdops->check_media_change (dev) ) return 0;
     printk ( KERN_DEBUG "VFS: Disk change detected on device %s\n",
 	     kdevname (dev) );
-    sb = get_super (dev);
-    if ( sb && invalidate_inodes (sb) )
+    if (invalidate_device(dev, 0))
 	printk("VFS: busy inodes on changed media..\n");
-    invalidate_buffers (dev);
     /*  Ugly hack to disable messages about unable to read partition table  */
     tmp = warn_no_part;
     warn_no_part = 0;
@@ -2259,12 +2256,13 @@
     {
 	inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
 			       de->u.fcb.u.device.minor);
+	inode->i_cdev = cdget (kdev_t_to_nr(inode->i_rdev));
     }
     else if ( S_ISBLK (de->inode.mode) )
     {
 	inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
 			       de->u.fcb.u.device.minor);
-	inode->i_bdev = bdget (inode->i_rdev);
+	inode->i_bdev = bdget (kdev_t_to_nr(inode->i_rdev));
 	if (inode->i_bdev)
 	{
 	    if (!inode->i_bdev->bd_op && de->u.fcb.ops)
diff -u --recursive --new-file v2.4.4/linux/fs/devices.c linux/fs/devices.c
--- v2.4.4/linux/fs/devices.c	Sun Oct  1 20:35:16 2000
+++ linux/fs/devices.c	Tue May 22 09:35:42 2001
@@ -203,6 +203,7 @@
 	if (S_ISCHR(mode)) {
 		inode->i_fop = &def_chr_fops;
 		inode->i_rdev = to_kdev_t(rdev);
+		inode->i_cdev = cdget(rdev);
 	} else if (S_ISBLK(mode)) {
 		inode->i_fop = &def_blk_fops;
 		inode->i_rdev = to_kdev_t(rdev);
diff -u --recursive --new-file v2.4.4/linux/fs/dquot.c linux/fs/dquot.c
--- v2.4.4/linux/fs/dquot.c	Fri Feb 16 16:06:17 2001
+++ linux/fs/dquot.c	Sun May 20 11:32:11 2001
@@ -1343,13 +1343,12 @@
 }
 
 
-void __init dquot_init_hash(void)
+static int __init dquot_init(void)
 {
 	printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
-
-	memset(dquot_hash, 0, sizeof(dquot_hash));
-	memset((caddr_t)&dqstats, 0, sizeof(dqstats));
+	return 0;
 }
+__initcall(dquot_init);
 
 /*
  * Definitions of diskquota operations.
diff -u --recursive --new-file v2.4.4/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.4.4/linux/fs/ext2/super.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ext2/super.c	Wed May 16 10:31:27 2001
@@ -76,9 +76,6 @@
 	va_start (args, fmt);
 	vsprintf (error_buf, fmt, args);
 	va_end (args);
-	/* this is to prevent panic from syncing this filesystem */
-	if (sb->s_lock)
-		sb->s_lock=0;
 	sb->s_flags |= MS_RDONLY;
 	panic ("EXT2-fs panic (device %s): %s: %s\n",
 	       bdevname(sb->s_dev), function, error_buf);
diff -u --recursive --new-file v2.4.4/linux/fs/fat/buffer.c linux/fs/fat/buffer.c
--- v2.4.4/linux/fs/fat/buffer.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/fat/buffer.c	Thu May 24 15:36:33 2001
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/fs.h>
+#include <linux/blkdev.h>
 #include <linux/msdos_fs.h>
 #include <linux/fat_cvf.h>
 
@@ -58,22 +59,26 @@
 
 struct buffer_head *default_fat_bread(struct super_block *sb, int block)
 {
-	return bread (sb->s_dev,block,512);
+	return bread (sb->s_dev, block, sb->s_blocksize);
 }
+
 struct buffer_head *default_fat_getblk(struct super_block *sb, int block)
 {
-	return getblk (sb->s_dev,block,512);
+	return getblk (sb->s_dev, block, sb->s_blocksize);
 }
+
 void default_fat_brelse(struct super_block *sb, struct buffer_head *bh)
 {
 	brelse (bh);
 }
+
 void default_fat_mark_buffer_dirty (
 	struct super_block *sb,
 	struct buffer_head *bh)
 {
 	mark_buffer_dirty (bh);
 }
+
 void default_fat_set_uptodate (
 	struct super_block *sb,
 	struct buffer_head *bh,
@@ -81,10 +86,12 @@
 {
 	mark_buffer_uptodate(bh, val);
 }
+
 int default_fat_is_uptodate (struct super_block *sb, struct buffer_head *bh)
 {
 	return buffer_uptodate(bh);
 }
+
 void default_fat_ll_rw_block (
 	struct super_block *sb,
 	int opr,
@@ -94,109 +101,61 @@
 	ll_rw_block(opr,nbreq,bh);
 }
 
-struct buffer_head *bigblock_fat_bread (
-	struct super_block *sb,
-	int block)
+struct buffer_head *bigblock_fat_bread(struct super_block *sb, int block)
 {
-	struct buffer_head *ret = NULL;
-	struct buffer_head *real;
-	if (sb->s_blocksize == 1024){
-		real = bread (sb->s_dev,block>>1,1024);
-	} else {
-		real = bread (sb->s_dev,block>>2,2048);
-	}
-
+	unsigned int hardsect = get_hardsect_size(sb->s_dev);
+	int rblock, roffset;
+	struct buffer_head *real, *dummy;
+
+	if (hardsect <= sb->s_blocksize)
+		BUG();
+
+	dummy = NULL;
+	rblock = block / (hardsect / sb->s_blocksize);
+	roffset = (block % (hardsect / sb->s_blocksize)) * sb->s_blocksize;
+	real = bread(sb->s_dev, rblock, hardsect);
 	if (real != NULL) {
-		ret = (struct buffer_head *)
-			kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
-		if (ret != NULL) {
-			/* #Specification: msdos / strategy / special device / dummy blocks
-			 * Many special device (Scsi optical disk for one) use
-			 * larger hardware sector size. This allows for higher
-			 * capacity.
-
-			 * Most of the time, the MS-DOS filesystem that sits
-			 * on this device is totally unaligned. It use logically
-			 * 512 bytes sector size, with logical sector starting
-			 * in the middle of a hardware block. The bad news is
-			 * that a hardware sector may hold data own by two
-			 * different files. This means that the hardware sector
-			 * must be read, patch and written almost all the time.
-
-			 * Needless to say that it kills write performance
-			 * on all OS.
-
-			 * Internally the linux msdos fs is using 512 bytes
-			 * logical sector. When accessing such a device, we
-			 * allocate dummy buffer cache blocks, that we stuff
-			 * with the information of a real one (1k large).
-
-			 * This strategy is used to hide this difference to
-			 * the core of the msdos fs. The slowdown is not
-			 * hidden though!
-			 */
-			/*
-			 * The memset is there only to catch errors. The msdos
-			 * fs is only using b_data
-			 */
-			memset (ret,0,sizeof(*ret));
-			ret->b_data = real->b_data;
-			if (sb->s_blocksize == 2048) {
-				if (block & 3) ret->b_data += (block & 3) << 9;
-			}else{
-				if (block & 1) ret->b_data += 512;
-			}
-			ret->b_next = real;
-		}else{
-			brelse (real);
-		}
+		dummy = kmalloc(sizeof(struct buffer_head), GFP_KERNEL);
+		if (dummy != NULL) {
+			memset(dummy, 0, sizeof(*dummy));
+			dummy->b_data = real->b_data + roffset;
+			dummy->b_next = real;
+		} else
+			brelse(real);
 	}
-	return ret;
+
+	return dummy;
 }
 
-void bigblock_fat_brelse (
-	struct super_block *sb,
-	struct buffer_head *bh)
+void bigblock_fat_brelse(struct super_block *sb, struct buffer_head *bh)
 {
-	brelse (bh->b_next);
-	/*
-	 * We can free the dummy because a new one is allocated at
-	 * each fat_getblk() and fat_bread().
-	 */
-	kfree (bh);
+	brelse(bh->b_next);
+	kfree(bh);
 }
 
-void bigblock_fat_mark_buffer_dirty (
-	struct super_block *sb,
-	struct buffer_head *bh)
+void bigblock_fat_mark_buffer_dirty(struct super_block *sb, struct buffer_head *bh)
 {
-	mark_buffer_dirty (bh->b_next);
+	mark_buffer_dirty(bh->b_next);
 }
 
-void bigblock_fat_set_uptodate (
-	struct super_block *sb,
-	struct buffer_head *bh,
-	int val)
+void bigblock_fat_set_uptodate(struct super_block *sb, struct buffer_head *bh,
+			       int val)
 {
 	mark_buffer_uptodate(bh->b_next, val);
 }
 
-int bigblock_fat_is_uptodate (
-	struct super_block *sb,
-	struct buffer_head *bh)
+int bigblock_fat_is_uptodate(struct super_block *sb, struct buffer_head *bh)
 {
 	return buffer_uptodate(bh->b_next);
 }
 
-void bigblock_fat_ll_rw_block (
-	struct super_block *sb,
-	int opr,
-	int nbreq,
-	struct buffer_head *bh[32])
+void bigblock_fat_ll_rw_block (struct super_block *sb, int opr, int nbreq,
+			       struct buffer_head *bh[32])
 {
 	struct buffer_head *tmp[32];
 	int i;
-	for (i=0; i<nbreq; i++)
+
+	for (i = 0; i < nbreq; i++)
 		tmp[i] = bh[i]->b_next;
-	ll_rw_block(opr,nbreq,tmp);
+	ll_rw_block(opr, nbreq, tmp);
 }
diff -u --recursive --new-file v2.4.4/linux/fs/fat/cache.c linux/fs/fat/cache.c
--- v2.4.4/linux/fs/fat/cache.c	Mon Jan 15 18:58:04 2001
+++ linux/fs/fat/cache.c	Thu May 24 15:36:33 2001
@@ -41,9 +41,9 @@
 
 int default_fat_access(struct super_block *sb,int nr,int new_value)
 {
-	struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
-	unsigned char *p_first,*p_last;
-	int copy,first,last,next,b;
+	struct buffer_head *bh, *bh2, *c_bh, *c_bh2;
+	unsigned char *p_first, *p_last;
+	int copy, first, last, next, b;
 
 	if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
 		return 0;
@@ -55,12 +55,12 @@
 		first = nr*3/2;
 		last = first+1;
 	}
-	b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS);
+	b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits);
 	if (!(bh = fat_bread(sb, b))) {
 		printk("bread in fat_access failed\n");
 		return 0;
 	}
-	if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) {
+	if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) {
 		bh2 = bh;
 	} else {
 		if (!(bh2 = fat_bread(sb, b+1))) {
@@ -72,7 +72,7 @@
 	if (MSDOS_SB(sb)->fat_bits == 32) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
 		next = CF_LE_L(((__u32 *) bh->b_data)[(first &
-		    (SECTOR_SIZE-1)) >> 2]);
+		    (sb->s_blocksize - 1)) >> 2]);
 		/* Fscking Microsoft marketing department. Their "32" is 28. */
 		next &= 0xfffffff;
 		if (next >= 0xffffff7) next = -1;
@@ -81,23 +81,22 @@
 	} else if (MSDOS_SB(sb)->fat_bits == 16) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
 		next = CF_LE_W(((__u16 *) bh->b_data)[(first &
-		    (SECTOR_SIZE-1)) >> 1]);
+		    (sb->s_blocksize - 1)) >> 1]);
 		if (next >= 0xfff7) next = -1;
 	} else {
-		p_first = &((__u8 *) bh->b_data)[first & (SECTOR_SIZE-1)];
-		p_last = &((__u8 *) bh2->b_data)[(first+1) &
-		    (SECTOR_SIZE-1)];
+		p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
+		p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)];
 		if (nr & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
 		else next = (*p_first+(*p_last << 8)) & 0xfff;
 		if (next >= 0xff7) next = -1;
 	}
 	if (new_value != -1) {
 		if (MSDOS_SB(sb)->fat_bits == 32) {
-			((__u32 *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
-			    2] = CT_LE_L(new_value);
+			((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
+				= CT_LE_L(new_value);
 		} else if (MSDOS_SB(sb)->fat_bits == 16) {
-			((__u16 *) bh->b_data)[(first & (SECTOR_SIZE-1)) >>
-			    1] = CT_LE_W(new_value);
+			((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
+				= CT_LE_W(new_value);
 		} else {
 			if (nr & 1) {
 				*p_first = (*p_first & 0xf) | (new_value << 4);
@@ -111,20 +110,21 @@
 		}
 		fat_mark_buffer_dirty(sb, bh);
 		for (copy = 1; copy < MSDOS_SB(sb)->fats; copy++) {
-			b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS) +
-				MSDOS_SB(sb)->fat_length * copy;
+			b = MSDOS_SB(sb)->fat_start + (first >> sb->s_blocksize_bits)
+				+ MSDOS_SB(sb)->fat_length * copy;
 			if (!(c_bh = fat_bread(sb, b)))
 				break;
-			memcpy(c_bh->b_data,bh->b_data,SECTOR_SIZE);
-			fat_mark_buffer_dirty(sb, c_bh);
 			if (bh != bh2) {
 				if (!(c_bh2 = fat_bread(sb, b+1))) {
 					fat_brelse(sb, c_bh);
 					break;
 				}
-				memcpy(c_bh2->b_data,bh2->b_data,SECTOR_SIZE);
+				memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize);
+				fat_mark_buffer_dirty(sb, c_bh2);
 				fat_brelse(sb, c_bh2);
 			}
+			memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
+			fat_mark_buffer_dirty(sb, c_bh);
 			fat_brelse(sb, c_bh);
 		}
 	}
@@ -143,7 +143,7 @@
 	if (initialized) {
 		spin_unlock(&fat_cache_lock);
 		return;
-		}
+	}
 	fat_cache = &cache[0];
 	for (count = 0; count < FAT_CACHE; count++) {
 		cache[count].device = 0;
@@ -294,22 +294,28 @@
 
 int default_fat_bmap(struct inode *inode,int sector)
 {
-	struct msdos_sb_info *sb=MSDOS_SB(inode->i_sb);
-	int cluster,offset;
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	int cluster, offset, last_block;
 
-	if ((sb->fat_bits != 32) &&
+	if ((sbi->fat_bits != 32) &&
 	    (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
 	     !MSDOS_I(inode)->i_start))) {
-		if (sector >= sb->dir_entries >> MSDOS_DPS_BITS)
+		if (sector >= sbi->dir_entries >> sbi->dir_per_block_bits)
 			return 0;
-		return sector+sb->dir_start;
+		return sector + sbi->dir_start;
 	}
-	if (sector >= (MSDOS_I(inode)->mmu_private+511)>>9)
+	last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
+		>> sb->s_blocksize_bits;
+	if (sector >= last_block)
 		return 0;
-	cluster = sector/sb->cluster_size;
-	offset = sector % sb->cluster_size;
-	if (!(cluster = fat_get_cluster(inode,cluster))) return 0;
-	return (cluster-2)*sb->cluster_size+sb->data_start+offset;
+
+	cluster = sector / sbi->cluster_size;
+	offset  = sector % sbi->cluster_size;
+	if (!(cluster = fat_get_cluster(inode, cluster)))
+		return 0;
+
+	return (cluster - 2) * sbi->cluster_size + sbi->data_start + offset;
 }
 
 
@@ -351,7 +357,7 @@
 				fat_clusters_flush(inode->i_sb);
 			}
 		}
-		inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
+		inode->i_blocks -= (1 << MSDOS_SB(inode->i_sb)->cluster_bits) / 512;
 	}
 	unlock_fat(inode->i_sb);
 	return 0;
diff -u --recursive --new-file v2.4.4/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.4.4/linux/fs/fat/file.c	Wed Apr 12 09:47:29 2000
+++ linux/fs/fat/file.c	Thu May 24 15:36:33 2001
@@ -54,8 +54,11 @@
 }
 
 
-int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) {
+int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+{
+	struct super_block *sb = inode->i_sb;
 	unsigned long phys;
+
 	phys = fat_bmap(inode, iblock);
 	if (phys) {
 		bh_result->b_dev = inode->i_dev;
@@ -65,7 +68,7 @@
 	}
 	if (!create)
 		return 0;
-	if (iblock<<9 != MSDOS_I(inode)->mmu_private) {
+	if (iblock << sb->s_blocksize_bits != MSDOS_I(inode)->mmu_private) {
 		BUG();
 		return -EIO;
 	}
@@ -73,8 +76,8 @@
 		if (fat_add_cluster(inode))
 			return -ENOSPC;
 	}
-	MSDOS_I(inode)->mmu_private += 512;
-	phys=fat_bmap(inode, iblock);
+	MSDOS_I(inode)->mmu_private += sb->s_blocksize;
+	phys = fat_bmap(inode, iblock);
 	if (!phys)
 		BUG();
 	bh_result->b_dev = inode->i_dev;
@@ -124,7 +127,7 @@
 		return /* -EPERM */;
 	if (IS_IMMUTABLE(inode))
 		return /* -EPERM */;
-	cluster = SECTOR_SIZE*sbi->cluster_size;
+	cluster = 1 << sbi->cluster_bits;
 	/* 
 	 * This protects against truncating a file bigger than it was then
 	 * trying to write into the hole.
@@ -132,7 +135,7 @@
 	if (MSDOS_I(inode)->mmu_private > inode->i_size)
 		MSDOS_I(inode)->mmu_private = inode->i_size;
 
-	fat_free(inode,(inode->i_size+(cluster-1))>>sbi->cluster_bits);
+	fat_free(inode, (inode->i_size + (cluster - 1)) >> sbi->cluster_bits);
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.4.4/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.4.4/linux/fs/fat/inode.c	Wed Apr 18 11:49:12 2001
+++ linux/fs/fat/inode.c	Thu May 24 15:36:34 2001
@@ -201,7 +201,7 @@
 }
 
 
-static int parse_options(char *options,int *fat, int *blksize, int *debug,
+static int parse_options(char *options,int *fat, int *debug,
 			 struct fat_mount_options *opts,
 			 char *cvf_format, char *cvf_options)
 {
@@ -310,13 +310,8 @@
 			else opts->quiet = 1;
 		}
 		else if (!strcmp(this_char,"blocksize")) {
-			if (!value || !*value) ret = 0;
-			else {
-				*blksize = simple_strtoul(value,&value,0);
-				if (*value || (*blksize != 512 &&
-					*blksize != 1024 && *blksize != 2048))
-					ret = 0;
-			}
+			printk("FAT: blocksize option is obsolete, "
+			       "not supported now\n");
 		}
 		else if (!strcmp(this_char,"sys_immutable")) {
 			if (value) ret = 0;
@@ -383,8 +378,8 @@
 		MSDOS_I(inode)->i_start = sbi->root_cluster;
 		if ((nr = MSDOS_I(inode)->i_start) != 0) {
 			while (nr != -1) {
-				inode->i_size += SECTOR_SIZE*sbi->cluster_size;
-				if (!(nr = fat_access(sb,nr,-1))) {
+				inode->i_size += 1 << sbi->cluster_bits;
+				if (!(nr = fat_access(sb, nr, -1))) {
 					printk("Directory %ld: bad FAT\n",
 					       inode->i_ino);
 					break;
@@ -393,13 +388,11 @@
 		}
 	} else {
 		MSDOS_I(inode)->i_start = 0;
-		inode->i_size = sbi->dir_entries*
-			sizeof(struct msdos_dir_entry);
+		inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
 	}
-	inode->i_blksize = sbi->cluster_size* SECTOR_SIZE;
-	inode->i_blocks =
-		((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *
-		    sbi->cluster_size;
+	inode->i_blksize = 1 << sbi->cluster_bits;
+	inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
+			   & ~(inode->i_blksize - 1)) / 512;
 	MSDOS_I(inode)->i_logstart = 0;
 	MSDOS_I(inode)->mmu_private = inode->i_size;
 
@@ -432,10 +425,9 @@
 	struct fat_boot_sector *b;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	char *p;
-	int data_sectors,logical_sector_size,sector_mult,fat_clusters=0;
-	int debug,error,fat,cp;
-	int blksize;
-	int fat32;
+	int logical_sector_size, hard_blksize, fat_clusters = 0;
+	unsigned int total_sectors, rootdir_sectors;
+	int fat32, debug, error, fat, cp;
 	struct fat_mount_options opts;
 	char buf[50];
 	int i;
@@ -451,35 +443,26 @@
 
 	sb->s_maxbytes = MAX_NON_LFS;
 	sb->s_op = &fat_sops;
-	blksize = get_hardsect_size(sb->s_dev);
-	if (!blksize)
-		blksize = 512;
-	if (blksize != 512)
-		printk ("MSDOS: Hardware sector size is %d\n",blksize);
+
+	hard_blksize = get_hardsect_size(sb->s_dev);
+	if (!hard_blksize)
+		hard_blksize = 512;
+	if (hard_blksize != 512)
+		printk("MSDOS: Hardware sector size is %d\n", hard_blksize);
 
 	opts.isvfat = sbi->options.isvfat;
-	if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, 
-			   cvf_format, cvf_options)
-	    || (blksize != 512 && blksize != 1024 && blksize != 2048))
+	if (!parse_options((char *) data, &fat, &debug, &opts,
+			   cvf_format, cvf_options))
 		goto out_fail;
 	/* N.B. we should parse directly into the sb structure */
 	memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options));
 
 	fat_cache_init();
-	if( blksize > 1024 )
-	  {
-	    /* Force the superblock to a larger size here. */
-	    sb->s_blocksize = blksize;
-	    set_blocksize(sb->s_dev, blksize);
-	  }
-	else
-	  {
-	    /* The first read is always 1024 bytes */
-	    sb->s_blocksize = 1024;
-	    set_blocksize(sb->s_dev, 1024);
-	  }
+
+	sb->s_blocksize = hard_blksize;
+	set_blocksize(sb->s_dev, hard_blksize);
 	bh = bread(sb->s_dev, 0, sb->s_blocksize);
-	if (bh == NULL || !buffer_uptodate(bh)) {
+	if (bh == NULL) {
 		brelse (bh);
 		goto out_no_bread;
 	}
@@ -499,110 +482,122 @@
  * (by Drew Eckhardt)
  */
 
-#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
-    /* don't divide by zero */
 
 	b = (struct fat_boot_sector *) bh->b_data;
 	logical_sector_size =
 		CF_LE_W(get_unaligned((unsigned short *) &b->sector_size));
-	sector_mult = logical_sector_size >> SECTOR_BITS;
-	sbi->cluster_size = b->cluster_size*sector_mult;
-	if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size-1))) {
-		printk("fatfs: bogus cluster size\n");
+	if (!logical_sector_size
+	    || (logical_sector_size & (logical_sector_size - 1))) {
+		printk("fatfs: bogus logical sector size %d\n",
+		       logical_sector_size);
+		brelse(bh);
+		goto out_invalid;
+	}
+
+	sbi->cluster_size = b->cluster_size;
+	if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size - 1))) {
+		printk("fatfs: bogus cluster size %d\n", sbi->cluster_size);
 		brelse(bh);
 		goto out_invalid;
 	}
-	for (sbi->cluster_bits=0;
-	     1<<sbi->cluster_bits<sbi->cluster_size;
-	     sbi->cluster_bits++)
-		;
-	sbi->cluster_bits += SECTOR_BITS;
+
+	sbi->cluster_bits = ffs(logical_sector_size * sbi->cluster_size) - 1;
 	sbi->fats = b->fats;
-	sbi->fat_start = CF_LE_W(b->reserved)*sector_mult;
+	sbi->fat_start = CF_LE_W(b->reserved);
 	if (!b->fat_length && b->fat32_length) {
 		struct fat_boot_fsinfo *fsinfo;
+		struct buffer_head *fsinfo_bh;
+		int fsinfo_block, fsinfo_offset;
 
 		/* Must be FAT32 */
 		fat32 = 1;
-		sbi->fat_length= CF_LE_L(b->fat32_length)*sector_mult;
+		sbi->fat_length = CF_LE_L(b->fat32_length);
 		sbi->root_cluster = CF_LE_L(b->root_cluster);
 
+		sbi->fsinfo_sector = CF_LE_W(b->info_sector);
 		/* MC - if info_sector is 0, don't multiply by 0 */
-		if(CF_LE_W(b->info_sector) == 0) {
-			sbi->fsinfo_offset =
-	 			logical_sector_size + 0x1e0;
-		} else {
-			sbi->fsinfo_offset =
-				(CF_LE_W(b->info_sector) * logical_sector_size)
-				+ 0x1e0;
-		}
-		if (sbi->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) {
-			printk("fat_read_super: Bad fsinfo_offset\n");
-			brelse(bh);
-			goto out_invalid;
-		}
-		fsinfo = (struct fat_boot_fsinfo *)
-			&bh->b_data[sbi->fsinfo_offset];
-		if (CF_LE_L(fsinfo->signature) != 0x61417272) {
-			printk("fat_read_super: Did not find valid FSINFO "
-				"signature. Found 0x%x\n",
-				CF_LE_L(fsinfo->signature));
+		if (sbi->fsinfo_sector == 0)
+			sbi->fsinfo_sector = 1;
+
+		fsinfo_block =
+			(sbi->fsinfo_sector * logical_sector_size) / hard_blksize;
+		fsinfo_offset =
+			(sbi->fsinfo_sector * logical_sector_size) % hard_blksize;
+		fsinfo_bh = bh;
+		if (bh->b_blocknr != fsinfo_block) {
+			fsinfo_bh = bread(sb->s_dev, fsinfo_block, hard_blksize);
+			if (fsinfo_bh == NULL) {
+				printk("FAT: bread failed, fsinfo block %d\n",
+				       fsinfo_block);
+				brelse(bh);
+				goto out_invalid;
+			}
+		}
+		fsinfo = (struct fat_boot_fsinfo *)&fsinfo_bh->b_data[fsinfo_offset];
+		if (!IS_FSINFO(fsinfo)) {
+			printk("FAT: Did not find valid FSINFO signature.\n"
+			       "Found signature1 0x%x signature2 0x%x sector=%ld.\n",
+			       CF_LE_L(fsinfo->signature1),
+			       CF_LE_L(fsinfo->signature2),
+			       sbi->fsinfo_sector);
 		} else {
 			sbi->free_clusters = CF_LE_L(fsinfo->free_clusters);
 		}
+
+		if (bh->b_blocknr != fsinfo_block)
+			brelse(fsinfo_bh);
 	} else {
 		fat32 = 0;
-		sbi->fat_length = CF_LE_W(b->fat_length)*sector_mult;
+		sbi->fat_length = CF_LE_W(b->fat_length);
 		sbi->root_cluster = 0;
 		sbi->free_clusters = -1; /* Don't know yet */
 	}
-	sbi->dir_start= CF_LE_W(b->reserved)*sector_mult+
-	    b->fats*sbi->fat_length;
+
+	sbi->dir_per_block = logical_sector_size / sizeof(struct msdos_dir_entry);
+	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
+
+	sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
 	sbi->dir_entries =
-		CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries));
-	sbi->data_start = sbi->dir_start+ROUND_TO_MULTIPLE((
-	    sbi->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
-	    sector_mult);
-	data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors));
-	if (!data_sectors) {
-		data_sectors = CF_LE_L(b->total_sect);
-	}
-	data_sectors = data_sectors * sector_mult - sbi->data_start;
-	error = !b->cluster_size || !sector_mult;
+		CF_LE_W(get_unaligned((unsigned short *)&b->dir_entries));
+	rootdir_sectors = sbi->dir_entries
+		* sizeof(struct msdos_dir_entry) / logical_sector_size;
+	sbi->data_start = sbi->dir_start + rootdir_sectors;
+	total_sectors = CF_LE_W(get_unaligned((unsigned short *)&b->sectors));
+	if (total_sectors == 0)
+		total_sectors = CF_LE_L(b->total_sect);
+	sbi->clusters = (total_sectors - sbi->data_start) / sbi->cluster_size;
+
+	error = 0;
 	if (!error) {
-		sbi->clusters = b->cluster_size ? data_sectors/
-		    b->cluster_size/sector_mult : 0;
 		sbi->fat_bits = fat32 ? 32 :
 			(fat ? fat :
 			 (sbi->clusters > MSDOS_FAT12 ? 16 : 12));
-		fat_clusters = sbi->fat_length*SECTOR_SIZE*8/
-		    sbi->fat_bits;
-		error = !sbi->fats || (sbi->dir_entries &
-		    (MSDOS_DPS-1)) || sbi->clusters+2 > fat_clusters+
-		    MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1))
-		    || !b->secs_track || !b->heads;
+		fat_clusters =
+			sbi->fat_length * logical_sector_size * 8 / sbi->fat_bits;
+		error = !sbi->fats || (sbi->dir_entries & (sbi->dir_per_block - 1))
+			|| sbi->clusters + 2 > fat_clusters + MSDOS_MAX_EXTRA
+			|| logical_sector_size < 512
+			|| PAGE_CACHE_SIZE < logical_sector_size
+			|| !b->secs_track || !b->heads;
 	}
 	brelse(bh);
-	set_blocksize(sb->s_dev, blksize);
-	/*
-		This must be done after the brelse because the bh is a dummy
-		allocated by fat_bread (see buffer.c)
-	*/
-	sb->s_blocksize = blksize;    /* Using this small block size solves */
-				/* the misfit with buffer cache and cluster */
-				/* because clusters (DOS) are often aligned */
-				/* on odd sectors. */
-	sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11);
+
+	sb->s_blocksize = logical_sector_size;
+	sb->s_blocksize_bits = ffs(logical_sector_size) - 1;
+	if (sb->s_blocksize >= hard_blksize) {
+		set_blocksize(sb->s_dev, sb->s_blocksize);
+		sbi->cvf_format = &default_cvf;
+	} else {
+		set_blocksize(sb->s_dev, hard_blksize);
+		sbi->cvf_format = &bigblock_cvf;
+	}
+
 	if (!strcmp(cvf_format,"none"))
 		i = -1;
 	else
 		i = detect_cvf(sb,cvf_format);
 	if (i >= 0)
 		error = cvf_formats[i]->mount_cvf(sb,cvf_options);
-	else if (sb->s_blocksize == 512)
-		sbi->cvf_format = &default_cvf;
-	else
-		sbi->cvf_format = &bigblock_cvf;
 	if (error || debug) {
 		/* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
 		printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
@@ -612,18 +607,19 @@
 		       MSDOS_CAN_BMAP(sbi) ? ",bmap" : "");
 		printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%ld,ds=%ld,de=%d,data=%ld,"
 		       "se=%d,ts=%ld,ls=%d,rc=%ld,fc=%u]\n",
-			b->media,sbi->cluster_size,
-			sbi->fats,sbi->fat_start,
-			sbi->fat_length,
+		       b->media,sbi->cluster_size,
+		       sbi->fats,sbi->fat_start,
+		       sbi->fat_length,
 		       sbi->dir_start,sbi->dir_entries,
 		       sbi->data_start,
 		       CF_LE_W(*(unsigned short *) &b->sectors),
 		       (unsigned long)b->total_sect,logical_sector_size,
 		       sbi->root_cluster,sbi->free_clusters);
-		printk ("Transaction block size = %d\n",blksize);
+		printk ("Transaction block size = %d\n", hard_blksize);
 	}
-	if (i<0) if (sbi->clusters+2 > fat_clusters)
-		sbi->clusters = fat_clusters-2;
+	if (i < 0)
+		if (sbi->clusters + 2 > fat_clusters)
+			sbi->clusters = fat_clusters - 2;
 	if (error)
 		goto out_invalid;
 
@@ -692,7 +688,7 @@
 	}
 	if(sbi->private_data)
 		kfree(sbi->private_data);
-	sbi->private_data=NULL;
+	sbi->private_data = NULL;
  
 	return NULL;
 }
@@ -717,7 +713,7 @@
 	}
 	unlock_fat(sb);
 	buf->f_type = sb->s_magic;
-	buf->f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
+	buf->f_bsize = 1 << MSDOS_SB(sb)->cluster_bits;
 	buf->f_blocks = MSDOS_SB(sb)->clusters;
 	buf->f_bfree = free;
 	buf->f_bavail = free;
@@ -796,8 +792,8 @@
 #endif
 		if ((nr = MSDOS_I(inode)->i_start) != 0)
 			while (nr != -1) {
-				inode->i_size += SECTOR_SIZE*sbi->cluster_size;
-				if (!(nr = fat_access(sb,nr,-1))) {
+				inode->i_size += 1 << sbi->cluster_bits;
+				if (!(nr = fat_access(sb, nr, -1))) {
 					printk("Directory %ld: bad FAT\n",
 					    inode->i_ino);
 					break;
@@ -828,12 +824,11 @@
 			inode->i_flags |= S_IMMUTABLE;
 	MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
 	/* this is as close to the truth as we can get ... */
-	inode->i_blksize = sbi->cluster_size*SECTOR_SIZE;
-	inode->i_blocks =
-		((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *
-		sbi->cluster_size;
+	inode->i_blksize = 1 << sbi->cluster_bits;
+	inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
+			   & ~(inode->i_blksize - 1)) / 512;
 	inode->i_mtime = inode->i_atime =
-	    date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
+		date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
 	inode->i_ctime =
 		MSDOS_SB(sb)->options.isvfat
 		? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate))
@@ -854,7 +849,7 @@
 		return;
 	}
 	lock_kernel();
-	if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) {
+	if (!(bh = fat_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {
 		printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
 		fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
 		unlock_kernel();
@@ -869,7 +864,7 @@
 	}
 
 	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
-	    [i_pos & (MSDOS_DPB-1)];
+	    [i_pos & (MSDOS_SB(sb)->dir_per_block - 1)];
 	if (S_ISDIR(inode->i_mode)) {
 		raw_entry->attr = ATTR_DIR;
 		raw_entry->size = 0;
diff -u --recursive --new-file v2.4.4/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v2.4.4/linux/fs/fat/misc.c	Tue Sep  5 14:07:29 2000
+++ linux/fs/fat/misc.c	Thu May 24 15:36:34 2001
@@ -108,24 +108,22 @@
 /* XXX: Need to write one per FSINFO block.  Currently only writes 1 */
 void fat_clusters_flush(struct super_block *sb)
 {
-	int offset;
 	struct buffer_head *bh;
 	struct fat_boot_fsinfo *fsinfo;
 
-	/* The fat32 boot fs info is at offset 0x3e0 by observation */
-	offset = MSDOS_SB(sb)->fsinfo_offset;
-	bh = fat_bread(sb, (offset >> SECTOR_BITS));
+	bh = fat_bread(sb, MSDOS_SB(sb)->fsinfo_sector);
 	if (bh == NULL) {
 		printk("FAT bread failed in fat_clusters_flush\n");
 		return;
 	}
-	fsinfo = (struct fat_boot_fsinfo *)
-		&bh->b_data[offset & (SECTOR_SIZE-1)];
 
+	fsinfo = (struct fat_boot_fsinfo *)bh->b_data;
 	/* Sanity check */
-	if (CF_LE_L(fsinfo->signature) != 0x61417272) {
-		printk("fat_clusters_flush: Did not find valid FSINFO signature. Found 0x%x.  offset=0x%x\n", CF_LE_L(fsinfo->signature), offset);
-		fat_brelse(sb, bh);
+	if (!IS_FSINFO(fsinfo)) {
+		printk("FAT: Did not find valid FSINFO signature.\n"
+		       "Found signature1 0x%x signature2 0x%x sector=%ld.\n",
+		       CF_LE_L(fsinfo->signature1), CF_LE_L(fsinfo->signature2),
+		       MSDOS_SB(sb)->fsinfo_sector);
 		return;
 	}
 	fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters);
@@ -145,7 +143,6 @@
 	struct super_block *sb = inode->i_sb;
 	int count,nr,limit,last,curr,file_cluster;
 	int res = -ENOSPC;
-	int cluster_size = MSDOS_SB(sb)->cluster_size;
 
 	if (!MSDOS_SB(sb)->free_clusters) return res;
 	lock_fat(sb);
@@ -167,7 +164,7 @@
 	if (MSDOS_SB(sb)->fat_bits == 32)
 		fat_clusters_flush(sb);
 	unlock_fat(sb);
-	last = 0;
+
 	/* We must locate the last cluster of the file to add this
 	   new one (nr) to the end of the link list (the FAT).
 	   
@@ -178,7 +175,7 @@
 	   use last to plug the nr cluster. We will use file_cluster to
 	   update the cache.
 	*/
-	file_cluster = 0;
+	last = file_cluster = 0;
 	if ((curr = MSDOS_I(inode)->i_start) != 0) {
 		fat_cache_lookup(inode,INT_MAX,&last,&curr);
 		file_cluster = last;
@@ -190,14 +187,15 @@
 			}
 		}
 	}
-	if (last) fat_access(sb,last,nr);
-	else {
+	if (last) {
+		fat_access(sb, last, nr);
+		fat_cache_add(inode, file_cluster, nr);
+	} else {
 		MSDOS_I(inode)->i_start = nr;
 		MSDOS_I(inode)->i_logstart = nr;
 		mark_inode_dirty(inode);
 	}
-	fat_cache_add(inode,file_cluster,nr);
-	inode->i_blocks += cluster_size;
+	inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
 	return 0;
 }
 
@@ -209,36 +207,44 @@
 	int cluster_size = MSDOS_SB(sb)->cluster_size;
 
 	if (MSDOS_SB(sb)->fat_bits != 32) {
-		if (inode->i_ino == MSDOS_ROOT_INO) return res;
+		if (inode->i_ino == MSDOS_ROOT_INO)
+			return res;
 	}
-	if (!MSDOS_SB(sb)->free_clusters) return res;
+	if (!MSDOS_SB(sb)->free_clusters)
+		return res;
+
 	lock_fat(sb);
+
 	limit = MSDOS_SB(sb)->clusters;
 	nr = limit; /* to keep GCC happy */
 	for (count = 0; count < limit; count++) {
-		nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2;
-		if (fat_access(sb,nr,-1) == 0) break;
+		nr = ((count + MSDOS_SB(sb)->prev_free) % limit) + 2;
+		if (fat_access(sb, nr, -1) == 0)
+			break;
 	}
-	PRINTK (("cnt = %d --",count));
+	PRINTK (("cnt = %d --", count));
 #ifdef DEBUG
-printk("free cluster: %d\n",nr);
+	printk("free cluster: %d\n", nr);
 #endif
-	MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit;
 	if (count >= limit) {
 		MSDOS_SB(sb)->free_clusters = 0;
 		unlock_fat(sb);
 		return res;
 	}
-	fat_access(sb,nr,EOF_FAT(sb));
+
+	MSDOS_SB(sb)->prev_free = (count + MSDOS_SB(sb)->prev_free + 1) % limit;
+	fat_access(sb, nr, EOF_FAT(sb));
 	if (MSDOS_SB(sb)->free_clusters != -1)
 		MSDOS_SB(sb)->free_clusters--;
 	if (MSDOS_SB(sb)->fat_bits == 32)
 		fat_clusters_flush(sb);
+
 	unlock_fat(sb);
+
 #ifdef DEBUG
-printk("set to %x\n",fat_access(sb,nr,-1));
+	printk("set to %x\n", fat_access(sb, nr, -1));
 #endif
-	last = 0;
+
 	/* We must locate the last cluster of the file to add this
 	   new one (nr) to the end of the link list (the FAT).
 	   
@@ -249,15 +255,14 @@
 	   use last to plug the nr cluster. We will use file_cluster to
 	   update the cache.
 	*/
-	file_cluster = 0;
+	last = file_cluster = 0;
 	if ((curr = MSDOS_I(inode)->i_start) != 0) {
-		fat_cache_lookup(inode,INT_MAX,&last,&curr);
+		fat_cache_lookup(inode, INT_MAX, &last, &curr);
 		file_cluster = last;
 		while (curr && curr != -1){
 			PRINTK (("."));
 			file_cluster++;
-			if (!(curr = fat_access(sb,
-			    last = curr,-1))) {
+			if (!(curr = fat_access(sb, last = curr, -1))) {
 				fat_fs_panic(sb,"File without EOF");
 				return res;
 			}
@@ -265,53 +270,57 @@
 		PRINTK ((" --  "));
 	}
 #ifdef DEBUG
-printk("last = %d\n",last);
+	printk("last = %d\n", last);
 #endif
-	if (last) fat_access(sb,last,nr);
+	if (last)
+		fat_access(sb, last, nr);
 	else {
 		MSDOS_I(inode)->i_start = nr;
 		MSDOS_I(inode)->i_logstart = nr;
 		mark_inode_dirty(inode);
 	}
 #ifdef DEBUG
-if (last) printk("next set to %d\n",fat_access(sb,last,-1));
+	if (last)
+		printk("next set to %d\n",fat_access(sb, last, -1));
 #endif
-	sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
+	sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size;
 	last_sector = sector + cluster_size;
-	if (MSDOS_SB(sb)->cvf_format &&
-	    MSDOS_SB(sb)->cvf_format->zero_out_cluster)
-		MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
-	else
-	for ( ; sector < last_sector; sector++) {
-		#ifdef DEBUG
-			printk("zeroing sector %d\n",sector);
-		#endif
-		if (!(bh = fat_getblk(sb, sector)))
-			printk("getblk failed\n");
-		else {
-			memset(bh->b_data,0,SECTOR_SIZE);
-			fat_set_uptodate(sb, bh, 1);
-			fat_mark_buffer_dirty(sb, bh);
-			if (!res)
-				res=bh;
-			else
-				fat_brelse(sb, bh);
+	if (MSDOS_SB(sb)->cvf_format && MSDOS_SB(sb)->cvf_format->zero_out_cluster)
+		MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode, nr);
+	else {
+		for ( ; sector < last_sector; sector++) {
+#ifdef DEBUG
+			printk("zeroing sector %d\n", sector);
+#endif
+			if (!(bh = fat_getblk(sb, sector)))
+				printk("getblk failed\n");
+			else {
+				memset(bh->b_data, 0, sb->s_blocksize);
+				fat_set_uptodate(sb, bh, 1);
+				fat_mark_buffer_dirty(sb, bh);
+				if (!res)
+					res = bh;
+				else
+					fat_brelse(sb, bh);
+			}
 		}
 	}
-	if (file_cluster != inode->i_blocks/cluster_size){
-		printk ("file_cluster badly computed!!! %d <> %ld\n"
-			,file_cluster,inode->i_blocks/cluster_size);
+	if (file_cluster
+	    != inode->i_blocks / cluster_size / (sb->s_blocksize / 512)) {
+		printk ("file_cluster badly computed!!! %d <> %ld\n",
+			file_cluster,
+			inode->i_blocks / cluster_size / (sb->s_blocksize / 512));
 	}else{
-		fat_cache_add(inode,file_cluster,nr);
+		fat_cache_add(inode, file_cluster, nr);
 	}
-	inode->i_blocks += cluster_size;
-	if (inode->i_size & (SECTOR_SIZE-1)) {
-		fat_fs_panic(sb,"Odd directory size");
-		inode->i_size = (inode->i_size+SECTOR_SIZE) &
-		    ~(SECTOR_SIZE-1);
+	inode->i_blocks += (1 << MSDOS_SB(sb)->cluster_bits) / 512;
+	if (inode->i_size & (sb->s_blocksize - 1)) {
+		fat_fs_panic(sb, "Odd directory size");
+		inode->i_size = (inode->i_size + sb->s_blocksize) &
+			~(sb->s_blocksize - 1);
 	}
-	inode->i_size += SECTOR_SIZE*cluster_size;
-	MSDOS_I(inode)->mmu_private += SECTOR_SIZE*cluster_size;
+	inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits;
+	MSDOS_I(inode)->mmu_private += 1 << MSDOS_SB(sb)->cluster_bits;
 	mark_inode_dirty(inode);
 	return res;
 }
@@ -386,6 +395,7 @@
     struct msdos_dir_entry **de, int *ino)
 {
 	struct super_block *sb = dir->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	int sector, offset;
 
 	while (1) {
@@ -394,7 +404,7 @@
 		if (*bh)
 			fat_brelse(sb, *bh);
 		*bh = NULL;
-		if ((sector = fat_bmap(dir,offset >> SECTOR_BITS)) == -1)
+		if ((sector = fat_bmap(dir,offset >> sb->s_blocksize_bits)) == -1)
 			return -1;
 		PRINTK (("get_entry sector %d %p\n",sector,*bh));
 		PRINTK (("get_entry sector apres brelse\n"));
@@ -406,10 +416,11 @@
 			continue;
 		}
 		PRINTK (("get_entry apres sread\n"));
-		*de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset &
-		    (SECTOR_SIZE-1)));
-		*ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
-		    MSDOS_DIR_BITS);
+
+		offset &= sb->s_blocksize - 1;
+		*de = (struct msdos_dir_entry *) ((*bh)->b_data + offset);
+		*ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
+
 		return 0;
 	}
 }
@@ -476,7 +487,7 @@
 	if (!(bh = fat_bread(sb,sector)))
 		return -EIO;
 	data = (struct msdos_dir_entry *) bh->b_data;
-	for (entry = 0; entry < MSDOS_DPS; entry++) {
+	for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) {
 /* RSS_COUNT:  if (data[entry].name == name) done=true else done=false. */
 		if (name) {
 			RSS_NAME
@@ -488,7 +499,8 @@
 			}
 		}
 		if (done) {
-			if (ino) *ino = sector*MSDOS_DPS+entry;
+			if (ino)
+				*ino = sector * MSDOS_SB(sb)->dir_per_block + entry;
 			start = CF_LE_W(data[entry].start);
 			if (MSDOS_SB(sb)->fat_bits == 32) {
 				start |= (CF_LE_W(data[entry].starthi) << 16);
@@ -517,9 +529,12 @@
 {
 	int count,cluster;
 
-	for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
+	for (count = 0;
+	     count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block;
+	     count++) {
 		if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
-		    name,number,ino,res_bh,res_de)) >= 0) return cluster;
+					       name,number,ino,res_bh,res_de)) >= 0)
+			return cluster;
 	}
 	return -ENOENT;
 }
@@ -570,13 +585,12 @@
     int *number, int *ino, struct buffer_head **res_bh,
     struct msdos_dir_entry **res_de)
 {
-	if (start) return raw_scan_nonroot
-		(sb,start,name,number,ino,res_bh,res_de);
-	else return raw_scan_root
-		(sb,name,number,ino,res_bh,res_de);
+	if (start)
+		return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de);
+	else
+		return raw_scan_root(sb,name,number,ino,res_bh,res_de);
 }
 
-
 /*
  * fat_parent_ino returns the inode number of the parent directory of dir.
  * File creation has to be deferred while fat_parent_ino is running to
@@ -627,7 +641,6 @@
 	if (!locked) fat_unlock_creation();
 	return nr;
 }
-
 
 /*
  * fat_subdirs counts the number of sub-directories of dir. It can be run
diff -u --recursive --new-file v2.4.4/linux/fs/fcntl.c linux/fs/fcntl.c
--- v2.4.4/linux/fs/fcntl.c	Wed Nov 15 22:50:25 2000
+++ linux/fs/fcntl.c	Tue May 22 09:26:06 2001
@@ -338,7 +338,6 @@
 	if (!filp)
 		goto out;
 
-	lock_kernel();
 	switch (cmd) {
 		case F_GETLK64:
 			err = fcntl_getlk64(fd, (struct flock64 *) arg);
@@ -353,7 +352,6 @@
 			err = do_fcntl(fd, cmd, arg, filp);
 			break;
 	}
-	unlock_kernel();
 	fput(filp);
 out:
 	return err;
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/Makefile linux/fs/freevxfs/Makefile
--- v2.4.4/linux/fs/freevxfs/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/Makefile	Sat May 19 17:47:55 2001
@@ -0,0 +1,11 @@
+#
+# VxFS Makefile
+#
+
+O_TARGET :=	freevxfs.o
+
+obj-y :=	vxfs_bmap.o vxfs_fshead.o vxfs_immed.o vxfs_inode.o \
+		vxfs_lookup.o vxfs_olt.o vxfs_subr.o vxfs_super.o
+obj-m :=	$(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs.h linux/fs/freevxfs/vxfs.h
--- v2.4.4/linux/fs/freevxfs/vxfs.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs.h	Mon May 21 12:31:06 2001
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+#ifndef _VXFS_SUPER_H_
+#define _VXFS_SUPER_H_
+
+#ident "$Id: vxfs.h 1.11 2001/05/21 15:40:28 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - superblock structure.
+ *
+ * This file contains the definition of the disk and core
+ * superblocks of the Veritas Filesystem.
+ */
+#include <linux/types.h>
+
+
+/*
+ * Data types for use with the VxFS ondisk format.
+ */
+typedef	int32_t		vx_daddr_t;
+typedef int32_t		vx_ino_t;
+
+/*
+ * Superblock magic number (vxfs_super->vs_magic).
+ */
+#define VXFS_SUPER_MAGIC	0xa501FCF5
+
+/*
+ * The root inode.
+ */
+#define VXFS_ROOT_INO		2
+
+/*
+ * Num of entries in free extent array
+ */
+#define VXFS_NEFREE		32
+
+
+/*
+ * VxFS superblock (disk).
+ */
+struct vxfs_sb {
+	/*
+	 * Readonly fields for the version 1 superblock.
+	 *
+	 * Lots of this fields are no more used by version 2
+	 * and never filesystems.
+	 */
+	u_int32_t	vs_magic;		/* Magic number */
+	int32_t		vs_version;		/* VxFS version */
+	u_int32_t	vs_ctime;		/* create time - secs */
+	u_int32_t	vs_cutime;		/* create time - usecs */
+	int32_t		__unused1;		/* unused */
+	int32_t		__unused2;		/* unused */
+	vx_daddr_t	vs_old_logstart;	/* obsolete */
+	vx_daddr_t	vs_old_logend;		/* obsolete */
+	int32_t		vs_bsize;		/* block size */
+	int32_t		vs_size;		/* number of blocks */
+	int32_t		vs_dsize;		/* number of data blocks */
+	u_int32_t	vs_old_ninode;		/* obsolete */
+	int32_t		vs_old_nau;		/* obsolete */
+	int32_t		__unused3;		/* unused */
+	int32_t		vs_old_defiextsize;	/* obsolete */
+	int32_t		vs_old_ilbsize;		/* obsolete */
+	int32_t		vs_immedlen;		/* size of immediate data area */
+	int32_t		vs_ndaddr;		/* number of direct extentes */
+	vx_daddr_t	vs_firstau;		/* address of first AU */
+	vx_daddr_t	vs_emap;		/* offset of extent map in AU */
+	vx_daddr_t	vs_imap;		/* offset of inode map in AU */
+	vx_daddr_t	vs_iextop;		/* offset of ExtOp. map in AU */
+	vx_daddr_t	vs_istart;		/* offset of inode list in AU */
+	vx_daddr_t	vs_bstart;		/* offset of fdblock in AU */
+	vx_daddr_t	vs_femap;		/* aufirst + emap */
+	vx_daddr_t	vs_fimap;		/* aufirst + imap */
+	vx_daddr_t	vs_fiextop;		/* aufirst + iextop */
+	vx_daddr_t	vs_fistart;		/* aufirst + istart */
+	vx_daddr_t	vs_fbstart;		/* aufirst + bstart */
+	int32_t		vs_nindir;		/* number of entries in indir */
+	int32_t		vs_aulen;		/* length of AU in blocks */
+	int32_t		vs_auimlen;		/* length of imap in blocks */
+	int32_t		vs_auemlen;		/* length of emap in blocks */
+	int32_t		vs_auilen;		/* length of ilist in blocks */
+	int32_t		vs_aupad;		/* length of pad in blocks */
+	int32_t		vs_aublocks;		/* data blocks in AU */
+	int32_t		vs_maxtier;		/* log base 2 of aublocks */
+	int32_t		vs_inopb;		/* number of inodes per blk */
+	int32_t		vs_old_inopau;		/* obsolete */
+	int32_t		vs_old_inopilb;		/* obsolete */
+	int32_t		vs_old_ndiripau;	/* obsolete */
+	int32_t		vs_iaddrlen;		/* size of indirect addr ext. */
+	int32_t		vs_bshift;		/* log base 2 of bsize */
+	int32_t		vs_inoshift;		/* log base 2 of inobp */
+	int32_t		vs_bmask;		/* ~( bsize - 1 ) */
+	int32_t		vs_boffmask;		/* bsize - 1 */
+	int32_t		vs_old_inomask;		/* old_inopilb - 1 */
+	int32_t		vs_checksum;		/* checksum of V1 data */
+	
+	/*
+	 * Version 1, writable
+	 */
+	int32_t		vs_free;		/* number of free blocks */
+	int32_t		vs_ifree;		/* number of free inodes */
+	int32_t		vs_efree[VXFS_NEFREE];	/* number of free extents by size */
+	int32_t		vs_flags;		/* flags ?!? */
+	u_int8_t	vs_mod;			/* filesystem has been changed */
+	u_int8_t	vs_clean;		/* clean FS */
+	u_int16_t	__unused4;		/* unused */
+	u_int32_t	vs_firstlogid;		/* mount time log ID */
+	u_int32_t	vs_wtime;		/* last time written - sec */
+	u_int32_t	vs_wutime;		/* last time written - usec */
+	u_int8_t	vs_fname[6];		/* FS name */
+	u_int8_t	vs_fpack[6];		/* FS pack name */
+	int32_t		vs_logversion;		/* log format version */
+	int32_t		__unused5;		/* unused */
+	
+	/*
+	 * Version 2, Read-only
+	 */
+	vx_daddr_t	vs_oltext[2];		/* OLT extent and replica */
+	int32_t		vs_oltsize;		/* OLT extent size */
+	int32_t		vs_iauimlen;		/* size of inode map */
+	int32_t		vs_iausize;		/* size of IAU in blocks */
+	int32_t		vs_dinosize;		/* size of inode in bytes */
+	int32_t		vs_old_dniaddr;		/* indir levels per inode */
+	int32_t		vs_checksum2;		/* checksum of V2 RO */
+
+	/*
+	 * Actually much more...
+	 */
+};
+
+
+/*
+ * In core superblock filesystem private data for VxFS.
+ */
+struct vxfs_sb_info {
+	struct vxfs_sb		*vsi_raw;	/* raw (on disk) supeblock */
+	struct buffer_head	*vsi_bp;	/* buffer for raw superblock*/
+	struct inode		*vsi_fship;	/* fileset header inode */
+	struct inode		*vsi_ilist;	/* inode list inode */
+	struct inode		*vsi_stilist;	/* structual inode list inode */
+	u_long			vsi_iext;	/* initial inode list */
+	ino_t			vsi_fshino;	/* fileset header inode */
+	daddr_t			vsi_oltext;	/* OLT extent */
+	daddr_t			vsi_oltsize;	/* OLT size */
+};
+
+
+/*
+ * File modes.  File types above 0xf000 are vxfs internal only, they should
+ * not be passed back to higher levels of the system.  vxfs file types must
+ * never have one of the regular file type bits set.
+ */
+enum vxfs_mode {
+	VXFS_ISUID = 0x00000800,	/* setuid */
+	VXFS_ISGID = 0x00000400,	/* setgid */
+	VXFS_ISVTX = 0x00000200,	/* sticky bit */
+	VXFS_IREAD = 0x00000100,	/* read */
+	VXFS_IWRITE = 0x00000080,	/* write */
+	VXFS_IEXEC = 0x00000040,	/* exec */
+
+	VXFS_IFIFO = 0x00001000,	/* Named pipe */
+	VXFS_IFCHR = 0x00002000,	/* Character device */
+	VXFS_IFDIR = 0x00004000,	/* Directory */
+	VXFS_IFNAM = 0x00005000,	/* Xenix device ?? */
+	VXFS_IFBLK = 0x00006000,	/* Block device */
+	VXFS_IFREG = 0x00008000,	/* Regular file */
+	VXFS_IFCMP = 0x00009000,	/* Compressed file ?!? */
+	VXFS_IFLNK = 0x0000a000,	/* Symlink */
+	VXFS_IFSOC = 0x0000c000,	/* Socket */
+
+	/* VxFS internal */
+	VXFS_IFFSH = 0x10000000,	/* Fileset header */
+	VXFS_IFILT = 0x20000000,	/* Inode list */
+	VXFS_IFIAU = 0x30000000,	/* Inode allocation unit */
+	VXFS_IFCUT = 0x40000000,	/* Current usage table */
+	VXFS_IFATT = 0x50000000,	/* Attr. inode */
+	VXFS_IFLCT = 0x60000000,	/* Link count table */
+	VXFS_IFIAT = 0x70000000,	/* Indirect attribute file */
+	VXFS_IFEMR = 0x80000000,	/* Extent map reorg file */
+	VXFS_IFQUO = 0x90000000,	/* BSD quota file */
+	VXFS_IFPTI = 0xa0000000,	/* "Pass through" inode */
+	VXFS_IFLAB = 0x11000000,	/* Device label file */
+	VXFS_IFOLT = 0x12000000,	/* OLT file */
+	VXFS_IFLOG = 0x13000000,	/* Log file */
+	VXFS_IFEMP = 0x14000000,	/* Extent map file */
+	VXFS_IFEAU = 0x15000000,	/* Extent AU file */
+	VXFS_IFAUS = 0x16000000,	/* Extent AU summary file */
+	VXFS_IFDEV = 0x17000000,	/* Device config file */
+
+};
+
+#define	VXFS_TYPE_MASK		0xfffff000
+
+#define VXFS_IS_TYPE(ip,type)	(((ip)->vii_mode & VXFS_TYPE_MASK) == (type))
+#define VXFS_ISFIFO(x)		VXFS_IS_TYPE((x),VXFS_IFIFO)
+#define VXFS_ISCHR(x)		VXFS_IS_TYPE((x),VXFS_IFCHR)
+#define VXFS_ISDIR(x)		VXFS_IS_TYPE((x),VXFS_IFDIR)
+#define VXFS_ISNAM(x)		VXFS_IS_TYPE((x),VXFS_IFNAM)
+#define VXFS_ISBLK(x)		VXFS_IS_TYPE((x),VXFS_IFBLK)
+#define VXFS_ISLNK(x)		VXFS_IS_TYPE((x),VXFS_IFLNK)
+#define VXFS_ISREG(x)		VXFS_IS_TYPE((x),VXFS_IFREG)
+#define VXFS_ISCMP(x)		VXFS_IS_TYPE((x),VXFS_IFCMP)
+#define VXFS_ISSOC(x)		VXFS_IS_TYPE((x),VXFS_IFSOC)
+
+#define VXFS_ISFSH(x)		VXFS_IS_TYPE((x),VXFS_IFFSH)
+#define VXFS_ISILT(x)		VXFS_IS_TYPE((x),VXFS_IFILT)
+
+/*
+ * Inmode organisation types.
+ */
+enum {
+	VXFS_ORG_NONE	= 0,	/* Inode has *no* format ?!? */
+	VXFS_ORG_EXT4	= 1,	/* Ext4 */
+	VXFS_ORG_IMMED	= 2,	/* All data stored in inode */
+	VXFS_ORG_TYPED	= 3,	/* Typed extents */
+};
+
+#define VXFS_IS_ORG(ip,org)	((ip)->vii_orgtype == (org))
+#define VXFS_ISNONE(ip)		VXFS_IS_ORG((ip), VXFS_ORG_NONE)
+#define VXFS_ISEXT4(ip)		VXFS_IS_ORG((ip), VXFS_ORG_EXT4)
+#define VXFS_ISIMMED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
+#define VXFS_ISTYPED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
+
+
+/*
+ * Get filesystem private data from VFS inode.
+ */
+#define VXFS_INO(ip) \
+	((struct vxfs_inode_info *)(ip)->u.generic_ip)
+
+/*
+ * Get filesystem private data from VFS superblock.
+ */
+#define VXFS_SBI(sbp) \
+	((struct vxfs_sb_info *)(sbp)->u.generic_sbp)
+
+#endif /* _VXFS_SUPER_H_ */
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_bmap.c linux/fs/freevxfs/vxfs_bmap.c
--- v2.4.4/linux/fs/freevxfs/vxfs_bmap.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_bmap.c	Thu May 24 15:00:59 2001
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_bmap.c,v 1.20 2001/04/25 18:11:23 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - filesystem to disk block mapping.
+ */
+#include <linux/fs.h>
+#include <linux/kernel.h>
+
+#include "vxfs.h"
+#include "vxfs_inode.h"
+
+
+#ifdef DIAGNOSTIC
+static void
+vxfs_typdump(struct vxfs_typed *typ)
+{
+	printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
+	printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+	printk("block=%x ", typ->vt_block);
+	printk("size=%x\n", typ->vt_size);
+}
+#endif
+
+/**
+ * vxfs_bmap_ext4 - do bmap for ext4 extents
+ * @ip:		pointer to the inode we do bmap for
+ * @iblock:	logical block.
+ *
+ * Description:
+ *   vxfs_bmap_ext4 performs the bmap operation for inodes with
+ *   ext4-style extents (which are much like the traditional UNIX
+ *   inode organisation).
+ *
+ * Returns:
+ *   The physical block number on success, else Zero.
+ */
+static daddr_t
+vxfs_bmap_ext4(struct inode *ip, long iblock)
+{
+	struct vxfs_inode_info		*vip = VXFS_INO(ip);
+	struct super_block		*sbp = ip->i_sb;
+	kdev_t				dev = ip->i_dev;
+	u_long				bsize = sbp->s_blocksize;
+	u_long				size = 0;
+	int				i;
+
+	for (i = 0; i < VXFS_NDADDR; i++) {
+		struct direct		*dp = vip->vii_ext4.ve4_direct + i;
+
+#ifdef DIAGNOSTIC
+		printk(KERN_DEBUG "iblock: %ld, %d (size: %lu)\n", iblock, i, size);
+		printk(KERN_DEBUG "dp->extent: %d, dp->size: %d\n", dp->extent, dp->size);
+#endif
+
+		if (iblock >= size && iblock < (size + dp->size))
+			return ((iblock - size) + dp->extent);
+		size += dp->size;
+	}
+
+	iblock -= size;
+
+	if (!(iblock / (vip->vii_ext4.ve4_indsize * vip->vii_ext4.ve4_indsize * bsize >> 2))) {
+		struct buffer_head	*bp;
+		daddr_t			pblock;
+
+		/*
+		 * XXX: is the second indir only used for
+		 *	double indirect extents?
+		 */
+		bp = bread(dev, vip->vii_ext4.ve4_indir[0],
+				bsize * ((vip->vii_ext4.ve4_indsize) / bsize) + 1);
+		pblock = *(bp->b_data + ((iblock / vip->vii_ext4.ve4_indsize) %
+					(vip->vii_ext4.ve4_indsize * bsize)));
+
+		brelse(bp);
+		return (pblock + (iblock % vip->vii_ext4.ve4_indsize));
+	} else
+		printk(KERN_WARNING "no matching indir?");
+
+	return 0;
+}
+
+/**
+ * vxfs_bmap_indir - recursion for vxfs_bmap_typed
+ * @ip:		pointer to the inode we do bmap for
+ * @indir:	indirect block we start reading at
+ * @size:	size of the typed area to search
+ * @block:	partially result from further searches
+ *
+ * Description:
+ *   vxfs_bmap_indir reads a &struct vxfs_typed at @indir
+ *   and performs the type-defined action.
+ *
+ * Return Value:
+ *   The physical block number on success, else Zero.
+ *
+ * Note:
+ *   Kernelstack is rare.  Unrecurse?
+ */
+static daddr_t
+vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
+{
+	struct buffer_head		*bp = NULL;
+	daddr_t				pblock = 0;
+	int				i;
+
+	for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
+		struct vxfs_typed	*typ;
+		u_int64_t		off;
+
+		bp = bread(ip->i_dev,
+				indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)),
+				ip->i_sb->s_blocksize);
+		if (!buffer_mapped(bp))
+			return 0;
+
+		typ = ((struct vxfs_typed *)bp->b_data) +
+			(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
+		off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+
+		if (block < off) {
+			brelse(bp);
+			continue;
+		}
+
+		switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+		case VXFS_TYPED_INDIRECT:
+			pblock = vxfs_bmap_indir(ip, typ->vt_block,
+					typ->vt_size, block - off);
+			if (pblock == -2)
+				break;
+			goto out;
+		case VXFS_TYPED_DATA:
+			if ((block - off) >= typ->vt_size)
+				break;
+			pblock = (typ->vt_block + block - off);
+			goto out;
+		case VXFS_TYPED_INDIRECT_DEV4:
+		case VXFS_TYPED_DATA_DEV4: {
+			struct vxfs_typed_dev4	*typ4 = (struct vxfs_typed_dev4 *)typ;
+			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
+			printk(KERN_INFO "block: %Ld\tsize: %Ld\tdev: %d\n",
+			       (long long)typ4->vd4_block, (long long)typ4->vd4_size, typ4->vd4_dev);
+			goto fail;
+		}
+		default:
+			BUG();
+		}
+		brelse(bp);
+	}
+
+fail:
+	pblock = 0;
+out:
+	brelse(bp);
+	return (pblock);
+}
+
+/**
+ * vxfs_bmap_typed - bmap for typed extents
+ * @ip:		pointer to the inode we do bmap for
+ * @iblock:	logical block
+ *
+ * Description:
+ *   Performs the bmap operation for typed extents.
+ *
+ * Return Value:
+ *   The physical block number on success, else Zero.
+ */
+static daddr_t
+vxfs_bmap_typed(struct inode *ip, long iblock)
+{
+	struct vxfs_inode_info		*vip = VXFS_INO(ip);
+	daddr_t				pblock = 0;
+	int				i;
+
+	for (i = 0; i < VXFS_NTYPED; i++) {
+		struct vxfs_typed	*typ = vip->vii_org.typed + i;
+		u_int64_t		off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+
+#ifdef DIAGNOSTIC
+		vxfs_typdump(typ);
+#endif
+		if (iblock < off)
+			continue;
+		switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+		case VXFS_TYPED_INDIRECT:
+			pblock = vxfs_bmap_indir(ip, typ->vt_block,
+					typ->vt_size, iblock - off);
+			if (pblock == -2)
+				break;
+			return (pblock);
+		case VXFS_TYPED_DATA:
+			if ((iblock - off) < typ->vt_size)
+				return (typ->vt_block + iblock - off);
+			break;
+		case VXFS_TYPED_INDIRECT_DEV4:
+		case VXFS_TYPED_DATA_DEV4: {
+			struct vxfs_typed_dev4	*typ4 = (struct vxfs_typed_dev4 *)typ;
+			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
+			printk(KERN_INFO "block: %Ld\tsize: %Ld\tdev: %d\n",
+			       (long long)typ4->vd4_block, (long long)typ4->vd4_size, typ4->vd4_dev);
+			return 0;
+		}
+		default:
+			BUG();
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * vxfs_bmap1 - vxfs-internal bmap operation
+ * @ip:			pointer to the inode we do bmap for
+ * @iblock:		logical block
+ *
+ * Description:
+ *   vxfs_bmap1 perfoms a logical to physical block mapping
+ *   for vxfs-internal purposes.
+ *
+ * Return Value:
+ *   The physical block number on success, else Zero.
+ */
+daddr_t
+vxfs_bmap1(struct inode *ip, long iblock)
+{
+	struct vxfs_inode_info		*vip = VXFS_INO(ip);
+
+	if (VXFS_ISEXT4(vip))
+		return vxfs_bmap_ext4(ip, iblock);
+	if (VXFS_ISTYPED(vip))
+		return vxfs_bmap_typed(ip, iblock);
+	if (VXFS_ISNONE(vip))
+		goto unsupp;
+	if (VXFS_ISIMMED(vip))
+		goto unsupp;
+
+	printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
+			ip->i_ino, vip->vii_orgtype);
+	BUG();
+
+unsupp:
+	printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
+			ip->i_ino, vip->vii_orgtype);
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_dir.h linux/fs/freevxfs/vxfs_dir.h
--- v2.4.4/linux/fs/freevxfs/vxfs_dir.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_dir.h	Mon May 21 12:31:06 2001
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+#ifndef _VXFS_DIR_H_
+#define _VXFS_DIR_H_
+
+#ident "$Id: vxfs_dir.h,v 1.7 2001/05/21 15:48:26 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - directory structure.
+ *
+ * This file contains the definition of the vxfs directory format.
+ */
+
+
+/*
+ * VxFS directory block header.
+ *
+ * This entry is the head of every filesystem block in a directory.
+ * It is used for free space managment and additionally includes
+ * a hash for speeding up directory search (lookup).
+ *
+ * The hash may be empty and in fact we do not use it all in the
+ * Linux driver for now.
+ */
+struct vxfs_dirblk {
+	u_int16_t	d_free;		/* free space in dirblock */
+	u_int16_t	d_nhash;	/* no of hash chains */
+	u_int16_t	d_hash[1];	/* hash chain */
+};
+
+/*
+ * VXFS_NAMELEN is the maximum length of the d_name field
+ *	of an VxFS directory entry.
+ */
+#define VXFS_NAMELEN	256
+
+/*
+ * VxFS directory entry.
+ */
+struct vxfs_direct {
+	vx_ino_t	d_ino;			/* inode number */
+	u_int16_t	d_reclen;		/* record length */
+	u_int16_t	d_namelen;		/* d_name length */
+	u_int16_t	d_hashnext;		/* next hash entry */
+	char		d_name[VXFS_NAMELEN];	/* name */
+};
+
+/*
+ * VXFS_DIRPAD defines the directory entry boundaries, is _must_ be
+ *	a multiple of four.
+ * VXFS_NAMEMIN is the length of a directory entry with a NULL d_name.
+ * VXFS_DIRROUND is an internal macros that rounds a length to a value
+ *	usable for directory sizes.
+ * VXFS_DIRLEN calculates the directory entry size for an entry with
+ *	a d_name with size len.
+ */
+#define VXFS_DIRPAD		4
+#define VXFS_NAMEMIN		((int)((struct vxfs_direct *)0)->d_name)
+#define VXFS_DIRROUND(len)	((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
+#define VXFS_DIRLEN(len)	(VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
+
+/*
+ * VXFS_DIRBLKOV is the overhead of a specific dirblock.
+ */
+#define VXFS_DIRBLKOV(dbp)	((sizeof(short) * dbp->d_nhash) + 4)
+
+#endif /* _VXFS_DIR_H_ */
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_extern.h linux/fs/freevxfs/vxfs_extern.h
--- v2.4.4/linux/fs/freevxfs/vxfs_extern.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_extern.h	Mon May 21 12:31:06 2001
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+#ifndef _VXFS_EXTERN_H_
+#define _VXFS_EXTERN_H_
+
+#ident "$Id: vxfs_extern.h,v 1.20 2001/04/26 22:48:44 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - external prototypes.
+ *
+ * This file contains prototypes for all vxfs functions used
+ * outside their respective source files.
+ */
+
+
+struct kmem_cache_s;
+struct super_block;
+struct vxfs_inode_info;
+struct inode;
+
+
+/* vxfs_bmap.c */
+extern daddr_t			vxfs_bmap1(struct inode *, long);
+
+/* vxfs_fshead.c */
+extern int			vxfs_read_fshead(struct super_block *);
+
+/* vxfs_inode.c */
+extern struct kmem_cache_s	*vxfs_inode_cachep;
+extern void			vxfs_dumpi(struct vxfs_inode_info *, ino_t);
+extern struct inode *		vxfs_fake_inode(struct super_block *,
+					struct vxfs_inode_info *);
+extern struct vxfs_inode_info *	vxfs_blkiget(struct super_block *, u_long, ino_t);
+extern struct vxfs_inode_info *	vxfs_stiget(struct super_block *, ino_t);
+extern void			vxfs_read_inode(struct inode *);
+extern void			vxfs_put_inode(struct inode *);
+
+/* vxfs_lookup.c */
+extern struct inode_operations	vxfs_dir_inode_ops;
+extern struct file_operations	vxfs_dir_operations;
+
+/* vxfs_olt.c */
+extern int			vxfs_read_olt(struct super_block *, u_long);
+
+/* vxfs_subr.c */
+extern struct page *		vxfs_get_page(struct inode *, u_long);
+extern __inline__ void		vxfs_put_page(struct page *);
+extern struct buffer_head *	vxfs_bread(struct inode *, int);
+
+#endif /* _VXFS_EXTERN_H_ */
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_fshead.c linux/fs/freevxfs/vxfs_fshead.c
--- v2.4.4/linux/fs/freevxfs/vxfs_fshead.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_fshead.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_fshead.c,v 1.18 2001/04/25 18:11:23 hch Exp $"
+
+/*
+ * Veritas filesystem driver - fileset header routines.
+ */
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "vxfs.h"
+#include "vxfs_inode.h"
+#include "vxfs_extern.h"
+#include "vxfs_fshead.h"
+
+
+#ifdef DIAGNOSTIC
+static void
+vxfs_dumpfsh(struct vxfs_fsh *fhp)
+{
+	printk("\n\ndumping fileset header:\n");
+	printk("----------------------------\n");
+	printk("version: %u\n", fhp->fsh_version);
+	printk("fsindex: %u\n", fhp->fsh_fsindex);
+	printk("iauino: %u\tninodes:%u\n",
+			fhp->fsh_iauino, fhp->fsh_ninodes);
+	printk("maxinode: %u\tlctino: %u\n",
+			fhp->fsh_maxinode, fhp->fsh_lctino);
+	printk("nau: %u\n", fhp->fsh_nau);
+	printk("ilistino[0]: %u\tilistino[1]: %u\n",
+			fhp->fsh_ilistino[0], fhp->fsh_ilistino[1]);
+}
+#endif
+
+/**
+ * vxfs_getfsh - read fileset header into memory
+ * @ip:		the (fake) fileset header inode
+ * @which:	0 for the structural, 1 for the primary fsh.
+ *
+ * Description:
+ *   vxfs_getfsh reads either the structural or primary fileset header
+ *   described by @ip into memory.
+ *
+ * Returns:
+ *   The fileset header structure on success, else Zero.
+ */
+static struct vxfs_fsh *
+vxfs_getfsh(struct inode *ip, int which)
+{
+	struct buffer_head		*bp;
+
+	bp = vxfs_bread(ip, which);
+	if (buffer_mapped(bp)) {
+		struct vxfs_fsh		*fhp;
+
+		if (!(fhp = kmalloc(sizeof(struct vxfs_fsh), SLAB_KERNEL)))
+			return NULL;
+		memcpy(fhp, bp->b_data, sizeof(struct vxfs_fsh));
+
+		brelse(bp);
+		return (fhp);
+	}
+
+	return NULL;
+}
+
+/**
+ * vxfs_read_fshead - read the fileset headers
+ * @sbp:	superblock to which the fileset belongs
+ *
+ * Description:
+ *   vxfs_read_fshead will fill the inode and structural inode list in @sb.
+ *
+ * Returns:
+ *   Zero on success, else a negative error code (-EINVAL).
+ */
+int
+vxfs_read_fshead(struct super_block *sbp)
+{
+	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
+	struct vxfs_fsh			*pfp, *sfp;
+	struct vxfs_inode_info		*vip, *tip;
+
+	if (!(vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino))) {
+		printk(KERN_ERR "vxfs: unabled to read fsh inode\n");
+		return -EINVAL;
+	} else if (!VXFS_ISFSH(vip)) {
+		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
+				vip->vii_mode & VXFS_TYPE_MASK); 
+		return -EINVAL;
+	}
+
+
+#ifdef DIAGNOSTIC
+	printk("vxfs: fsh inode dump:\n");
+	vxfs_dumpi(vip, infp->vsi_fshino);
+#endif
+
+	if (!(infp->vsi_fship = vxfs_fake_inode(sbp, vip))) {
+		printk(KERN_ERR "vxfs: unabled to get fsh inode\n");
+		return -EINVAL;
+	}
+
+	if (!(sfp = vxfs_getfsh(infp->vsi_fship, 0))) {
+		printk(KERN_ERR "vxfs: unabled to get structural fsh\n");
+		return -EINVAL;
+	} 
+
+#ifdef DIAGNOSTIC
+	vxfs_dumpfsh(sfp);
+#endif
+
+	if (!(pfp = vxfs_getfsh(infp->vsi_fship, 1))) {
+		printk(KERN_ERR "vxfs: unabled to get primary fsh\n");
+		return -EINVAL;
+	}
+
+#ifdef DIAGNOSTIC
+	vxfs_dumpfsh(pfp);
+#endif
+
+	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
+	if (!tip || ((infp->vsi_stilist = vxfs_fake_inode(sbp, tip)) == NULL)) {
+		printk(KERN_ERR "vxfs: unabled to get structual list inode\n");
+		return -EINVAL;
+	} else if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
+		printk(KERN_ERR "vxfs: structual list inode is of wrong type (%x)\n",
+				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
+		return -EINVAL;
+	}
+
+	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
+	if (!tip || ((infp->vsi_ilist = vxfs_fake_inode(sbp, tip)) == NULL)) {
+		printk(KERN_ERR "vxfs: unabled to get inode list inode\n");
+		return -EINVAL;
+	} else if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
+		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
+				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_fshead.h linux/fs/freevxfs/vxfs_fshead.h
--- v2.4.4/linux/fs/freevxfs/vxfs_fshead.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_fshead.h	Mon May 21 12:31:06 2001
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+#ifndef _VXFS_FSHEAD_H_
+#define _VXFS_FSHEAD_H_
+
+#ident "$Id: vxfs_fshead.h,v 1.6 2001/04/25 18:11:23 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - fileset header structures.
+ *
+ * This file contains the physical structure of the VxFS
+ * fileset header.
+ */
+
+
+/*
+ * Fileset header 
+ */
+struct vxfs_fsh {
+	u_int32_t	fsh_version;		/* fileset header version */
+	u_int32_t	fsh_fsindex;		/* fileset index */
+	u_int32_t	fsh_time;		/* modification time - sec */
+	u_int32_t	fsh_utime;		/* modification time - usec */
+	u_int32_t	fsh_extop;		/* extop flags */
+	vx_ino_t	fsh_ninodes;		/* allocated inodes */
+	u_int32_t	fsh_nau;		/* number of IAUs */
+	u_int32_t	fsh_old_ilesize;	/* old size of ilist */
+	u_int32_t	fsh_dflags;		/* flags */
+	u_int32_t	fsh_quota;		/* quota limit */
+	vx_ino_t	fsh_maxinode;		/* maximum inode number */
+	vx_ino_t	fsh_iauino;		/* IAU inode */
+	vx_ino_t	fsh_ilistino[2];	/* ilist inodes */
+	vx_ino_t	fsh_lctino;		/* link count table inode */
+
+	/*
+	 * Slightly more fields follow, but they
+	 *  a) are not of any interested for us, and
+	 *  b) differ much in different vxfs versions/ports
+	 */
+};
+
+#endif /* _VXFS_FSHEAD_H_ */
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_immed.c linux/fs/freevxfs/vxfs_immed.c
--- v2.4.4/linux/fs/freevxfs/vxfs_immed.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_immed.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_immed.c,v 1.10 2001/04/25 18:11:23 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - support for 'immed' inodes.
+ */
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+
+#include "vxfs.h"
+#include "vxfs_inode.h"
+
+
+static int	vxfs_immed_readlink(struct dentry *, char *, int);
+static int	vxfs_immed_follow_link(struct dentry *, struct nameidata *);
+
+static int	vxfs_immed_readpage(struct file *, struct page *);
+
+/*
+ * Inode operations for immed symlinks.
+ *
+ * Unliked all other operations we do not go through the pagecache,
+ * but do all work directly on the inode.
+ */
+struct inode_operations vxfs_immed_symlink_iops = {
+	.readlink =		vxfs_immed_readlink,
+	.follow_link =		vxfs_immed_follow_link,
+};
+
+/*
+ * Adress space operations for immed files and directories.
+ */
+struct address_space_operations vxfs_immed_aops = {
+	.readpage =		vxfs_immed_readpage,
+};
+
+
+/**
+ * vxfs_immed_readlink - read immed symlink
+ * @dp:		dentry for the link
+ * @bp:		output buffer
+ * @buflen:	length of @bp
+ *
+ * Description:
+ *   vxfs_immed_readlink calls vfs_readlink to read the link
+ *   described by @dp into userspace.
+ *
+ * Returns:
+ *   Number of bytes successfully copied to userspace.
+ */
+static int
+vxfs_immed_readlink(struct dentry *dp, char *bp, int buflen)
+{
+	struct vxfs_inode_info		*vip = VXFS_INO(dp->d_inode);
+
+	return (vfs_readlink(dp, bp, buflen, vip->vii_immed.vi_immed));
+}
+
+/**
+ * vxfs_immed_follow_link - follow immed symlink
+ * @dp:		dentry for the link
+ * @np:		pathname lookup data for the current path walk
+ *
+ * Description:
+ *   vxfs_immed_follow_link restarts the pathname lookup with
+ *   the data obtained from @dp.
+ *
+ * Returns:
+ *   Zero on success, else a negative error code.
+ */
+static int
+vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
+{
+	struct vxfs_inode_info		*vip = VXFS_INO(dp->d_inode);
+
+	return (vfs_follow_link(np, vip->vii_immed.vi_immed));
+}
+
+/**
+ * vxfs_immed_readpage - read part of an immed inode into pagecache
+ * @file:	file context (unused)
+ * @page:	page frame to fill in.
+ *
+ * Description:
+ *   vxfs_immed_readpage reads a part of the immed area of the
+ *   file that hosts @pp into the pagecache.
+ *
+ * Returns:
+ *   Zero on success, else a negative error code.
+ *
+ * Locking status:
+ *   @page is locked and will be unlocked.
+ */
+static int
+vxfs_immed_readpage(struct file *fp, struct page *pp)
+{
+	struct vxfs_inode_info	*vip = VXFS_INO(pp->mapping->host);
+	u_int64_t		offset = pp->index << PAGE_CACHE_SHIFT;
+	caddr_t			kaddr;
+
+	kaddr = kmap(pp);
+	memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE);
+	kunmap(pp);
+	
+	flush_dcache_page(pp);
+	SetPageUptodate(pp);
+        UnlockPage(pp);
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_inode.c linux/fs/freevxfs/vxfs_inode.c
--- v2.4.4/linux/fs/freevxfs/vxfs_inode.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_inode.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_inode.c,v 1.34 2001/05/21 15:33:08 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - inode routines.
+ */
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "vxfs.h"
+#include "vxfs_inode.h"
+#include "vxfs_extern.h"
+
+
+extern struct address_space_operations vxfs_aops;
+extern struct address_space_operations vxfs_immed_aops;
+
+extern struct inode_operations vxfs_immed_symlink_iops;
+
+static struct file_operations vxfs_file_operations = {
+	.read =			generic_file_read,
+	.mmap =			generic_file_mmap,
+};
+
+
+kmem_cache_t		*vxfs_inode_cachep;
+
+
+#ifdef DIAGNOSTIC
+/*
+ * Dump inode contents (partially).
+ */
+void
+vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
+{
+	printk(KERN_DEBUG "\n\n");
+	if (ino)
+		printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino);
+	else
+		printk(KERN_DEBUG "dumping unknown vxfs inode\n");
+
+	printk(KERN_DEBUG "---------------------------\n");
+	printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
+	printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
+			vip->vii_nlink, vip->vii_uid, vip->vii_gid);
+	printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
+			vip->vii_size, vip->vii_blocks);
+	printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
+}
+#endif
+
+
+/**
+ * vxfs_blkiget - find inode based on extent #
+ * @sbp:	superblock of the filesystem we search in
+ * @extent:	number of the extent to search
+ * @ino:	inode number to search
+ *
+ * Description:
+ *  vxfs_blkiget searches inode @ino in the filesystem described by
+ *  @sbp in the extent @extent.
+ *  Returns the matching VxFS inode on success, else a NULL pointer.
+ *
+ * NOTE:
+ *  While __vxfs_iget uses that pagecache this function uses the
+ *  buffercache.  This function should not be used outside the
+ *  read_super() method, othwerwise the data may be incoherent.
+ */
+struct vxfs_inode_info *
+vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
+{
+	struct buffer_head		*bp;
+	u_long				block, offset;
+
+	block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
+	offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
+	bp = bread(sbp->s_dev, block, sbp->s_blocksize);
+
+	if (buffer_mapped(bp)) {
+		struct vxfs_inode_info	*vip;
+		struct vxfs_dinode	*dip;
+
+		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
+			goto fail;
+		dip = (struct vxfs_dinode *)(bp->b_data + offset);
+		memcpy(vip, dip, sizeof(struct vxfs_inode_info));
+#ifdef DIAGNOSTIC
+		vxfs_dumpi(vip, ino);
+#endif
+		brelse(bp);
+		return (vip);
+	}
+
+fail:
+	printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
+	brelse(bp);
+	return NULL;
+}
+
+/**
+ * __vxfs_iget - generic find inode facility
+ * @sbp:		VFS superblock
+ * @ino:		inode number
+ * @ilistp:		inode list
+ *
+ * Description:
+ *  Search the for inode number @ino in the filesystem
+ *  described by @sbp.  Use the specified inode table (@ilistp).
+ *  Returns the matching VxFS inode on success, else a NULL pointer.
+ */
+static struct vxfs_inode_info *
+__vxfs_iget(struct super_block *sbp, ino_t ino, struct inode *ilistp)
+{
+	struct page			*pp;
+	u_long				offset;
+
+	offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
+	pp = vxfs_get_page(ilistp, ino * VXFS_ISIZE / PAGE_SIZE);
+
+	if (!IS_ERR(pp)) {
+		struct vxfs_inode_info	*vip;
+		struct vxfs_dinode	*dip;
+		caddr_t			kaddr = (char *)page_address(pp);
+
+		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, SLAB_KERNEL)))
+			goto fail;
+		dip = (struct vxfs_dinode *)(kaddr + offset);
+		memcpy(vip, dip, sizeof(struct vxfs_inode_info));
+#ifdef DIAGNOSTIC
+		vxfs_dumpi(vip, ino);
+#endif
+		vxfs_put_page(pp);
+		return (vip);
+	}
+
+	printk(KERN_WARNING "vxfs: error on page %p\n", pp);
+	return NULL;
+
+fail:
+	printk(KERN_WARNING "vxfs: unable to read inode %ld\n", ino);
+	vxfs_put_page(pp);
+	return NULL;
+}
+
+/**
+ * vxfs_stiget - find inode using the structural inode list
+ * @sbp:	VFS superblock
+ * @ino:	inode #
+ *
+ * Description:
+ *  Find inode @ino in the filesystem described by @sbp using
+ *  the structural inode list.
+ *  Returns the matching VxFS inode on success, else a NULL pointer.
+ */
+struct vxfs_inode_info *
+vxfs_stiget(struct super_block *sbp, ino_t ino)
+{
+        return __vxfs_iget(sbp, ino, VXFS_SBI(sbp)->vsi_stilist);
+}
+
+/**
+ * vxfs_transmod - mode for a VxFS inode
+ * @vip:	VxFS inode
+ *
+ * Description:
+ *  vxfs_transmod returns a Linux mode_t for a given
+ *  VxFS inode structure.
+ */
+static __inline__ mode_t
+vxfs_transmod(struct vxfs_inode_info *vip)
+{
+	mode_t			ret = vip->vii_mode & ~VXFS_TYPE_MASK;
+
+	if (VXFS_ISFIFO(vip))
+		ret |= S_IFIFO;
+	if (VXFS_ISCHR(vip))
+		ret |= S_IFCHR;
+	if (VXFS_ISDIR(vip))
+		ret |= S_IFDIR;
+	if (VXFS_ISBLK(vip))
+		ret |= S_IFBLK;
+	if (VXFS_ISLNK(vip))
+		ret |= S_IFLNK;
+	if (VXFS_ISREG(vip))
+		ret |= S_IFREG;
+	if (VXFS_ISSOC(vip))
+		ret |= S_IFSOCK;
+
+	return (ret);
+}
+
+/**
+ * vxfs_iinit- helper to fill inode fields
+ * @ip:		VFS inode
+ * @vip:	VxFS inode
+ *
+ * Description:
+ *  vxfs_instino is a helper function to fill in all relevant
+ *  fields in @ip from @vip.
+ */
+static void
+vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
+{
+
+	ip->i_mode = vxfs_transmod(vip);
+	ip->i_uid = (uid_t)vip->vii_uid;
+	ip->i_gid = (gid_t)vip->vii_gid;
+
+	ip->i_nlink = vip->vii_nlink;
+	ip->i_size = vip->vii_size;
+
+	ip->i_atime = vip->vii_atime;
+	ip->i_ctime = vip->vii_ctime;
+	ip->i_mtime = vip->vii_mtime;
+
+	ip->i_blksize = PAGE_SIZE;
+	ip->i_blocks = vip->vii_blocks;
+	ip->i_generation = vip->vii_gen;
+
+	ip->u.generic_ip = (void *)vip;
+	
+}
+
+/**
+ * vxfs_fake_inode - get fake inode structure
+ * @sbp:		filesystem superblock
+ * @vip:		fspriv inode
+ *
+ * Description:
+ *  vxfs_fake_inode gets a fake inode (not in the inode hash) for a
+ *  superblock, vxfs_inode pair.
+ *  Returns the filled VFS inode.
+ */
+struct inode *
+vxfs_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
+{
+	struct inode			*ip = NULL;
+
+	if ((ip = new_inode(sbp))) {
+		vxfs_iinit(ip, vip);
+		ip->i_mapping->a_ops = &vxfs_aops;
+	}
+	return (ip);
+}
+
+/**
+ * vxfs_read_inode - fill in inode information
+ * @ip:		inode pointer to fill
+ *
+ * Description:
+ *  vxfs_read_inode reads the disk inode for @ip and fills
+ *  in all relevant fields in @ip.
+ */
+void
+vxfs_read_inode(struct inode *ip)
+{
+	struct super_block		*sbp = ip->i_sb;
+	struct vxfs_inode_info		*vip;
+	struct address_space_operations	*aops;
+	ino_t				ino = ip->i_ino;
+
+	if (!(vip = __vxfs_iget(sbp, ino, VXFS_SBI(sbp)->vsi_ilist)))
+		return;
+
+	vxfs_iinit(ip, vip);
+
+	if (VXFS_ISIMMED(vip))
+		aops = &vxfs_immed_aops;
+	else
+		aops = &vxfs_aops;
+
+	if (S_ISREG(ip->i_mode)) {
+		ip->i_fop = &vxfs_file_operations;
+		ip->i_mapping->a_ops = aops;
+	} else if (S_ISDIR(ip->i_mode)) {
+		ip->i_op = &vxfs_dir_inode_ops;
+		ip->i_fop = &vxfs_dir_operations;
+		ip->i_mapping->a_ops = aops;
+	} else if (S_ISLNK(ip->i_mode)) {
+		if (!VXFS_ISIMMED(vip)) {
+			ip->i_op = &page_symlink_inode_operations;
+			ip->i_mapping->a_ops = &vxfs_aops;
+		} else
+			ip->i_op = &vxfs_immed_symlink_iops;
+	} else
+		init_special_inode(ip, ip->i_mode, vip->vii_rdev);
+
+	return;
+}
+
+/**
+ * vxfs_put_inode - remove inode from main memory
+ * @ip:		inode to discard.
+ *
+ * Description:
+ *  vxfs_put_inode() is called on each iput.  If we are the last
+ *  link in memory, free the fspriv inode area.
+ */
+void
+vxfs_put_inode(struct inode *ip)
+{
+	if (atomic_read(&ip->i_count) == 1)
+		kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_inode.h linux/fs/freevxfs/vxfs_inode.h
--- v2.4.4/linux/fs/freevxfs/vxfs_inode.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_inode.h	Mon May 21 12:31:06 2001
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+#ifndef _VXFS_INODE_H_
+#define _VXFS_INODE_H_
+
+#ident "$Id: vxfs_inode.h,v 1.14 2001/04/25 18:11:23 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - inode structure.
+ *
+ * This file contains the definition of the disk and core
+ * inodes of the Veritas Filesystem.
+ */
+
+
+#define VXFS_ISIZE		0x100		/* Inode size */
+
+#define VXFS_NDADDR		10		/* Number of direct addrs in inode */
+#define VXFS_NIADDR		2		/* Number of indirect addrs in inode */
+#define VXFS_NIMMED		96		/* Size of immediate data in inode */
+#define VXFS_NTYPED		6		/* Num of typed extents */
+
+#define VXFS_TYPED_OFFSETMASK	(0x00FFFFFFFFFFFFFFULL)
+#define VXFS_TYPED_TYPEMASK	(0xFF00000000000000ULL)
+#define VXFS_TYPED_TYPESHIFT	56
+
+#define VXFS_TYPED_PER_BLOCK(sbp) \
+	((sbp)->s_blocksize / sizeof(struct vxfs_typed))
+
+/*
+ * Possible extent descriptor types for %VXFS_ORG_TYPED extents.
+ */
+enum {
+	VXFS_TYPED_INDIRECT		= 1,
+	VXFS_TYPED_DATA			= 2,
+	VXFS_TYPED_INDIRECT_DEV4	= 3,
+	VXFS_TYPED_DATA_DEV4		= 4,
+};
+
+/*
+ * Data stored immediately in the inode.
+ */
+struct vxfs_immed {
+	u_int8_t	vi_immed[VXFS_NIMMED];
+};
+
+struct vxfs_ext4 {
+	u_int32_t		ve4_spare;		/* ?? */
+	u_int32_t		ve4_indsize;		/* Indirect extent size */
+	vx_daddr_t		ve4_indir[VXFS_NIADDR];	/* Indirect extents */
+	struct direct {					/* Direct extents */
+		vx_daddr_t	extent;			/* Extent number */
+		u_int32_t	size;			/* Size of extent */
+	} ve4_direct[VXFS_NDADDR];
+};
+
+struct vxfs_typed {
+	u_int64_t	vt_hdr;		/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
+	vx_daddr_t	vt_block;	/* Extent block */
+	int32_t		vt_size;	/* Size in blocks */
+};
+
+struct vxfs_typed_dev4 {
+	u_int64_t	vd4_hdr;	/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
+	u_int64_t	vd4_block;	/* Extent block */
+	u_int64_t	vd4_size;	/* Size in blocks */
+	int32_t		vd4_dev;	/* Device ID */
+	u_int32_t	__pad1;
+};
+
+/*
+ * The inode as contained on the physical device.
+ */
+struct vxfs_dinode {
+	int32_t		vdi_mode;
+	u_int32_t	vdi_nlink;	/* Link count */
+	u_int32_t	vdi_uid;	/* UID */
+	u_int32_t	vdi_gid;	/* GID */
+	u_int64_t	vdi_size;	/* Inode size in bytes */
+	u_int32_t	vdi_atime;	/* Last time accessed - sec */
+	u_int32_t	vdi_autime;	/* Last time accessed - usec */
+	u_int32_t	vdi_mtime;	/* Last modify time - sec */
+	u_int32_t	vdi_mutime;	/* Last modify time - usec */
+	u_int32_t	vdi_ctime;	/* Create time - sec */
+	u_int32_t	vdi_cutime;	/* Create time - usec */
+	u_int8_t	vdi_aflags;	/* Allocation flags */
+	u_int8_t	vdi_orgtype;	/* Organisation type */
+	u_int16_t	vdi_eopflags;
+	u_int32_t	vdi_eopdata;
+	union {
+		u_int32_t		rdev;
+		u_int32_t		dotdot;
+		struct {
+			u_int32_t	reserved;
+			u_int32_t	fixextsize;
+		} i_regular;
+		struct {
+			u_int32_t	matchino;
+			u_int32_t	fsetindex;
+		} i_vxspec;
+		u_int64_t		align;
+	} vdi_ftarea;
+	u_int32_t	vdi_blocks;	/* How much blocks does inode occupy */
+	u_int32_t	vdi_gen;	/* Inode generation */
+	u_int64_t	vdi_version;	/* Version */
+	union {
+		struct vxfs_immed	immed;
+		struct vxfs_ext4	ext4;
+		struct vxfs_typed	typed[VXFS_NTYPED];
+	} vdi_org;
+	u_int32_t	vdi_iattrino;
+};
+
+#define vdi_rdev	vdi_ftarea.rdev
+#define vdi_dotdot	vdi_ftarea.dotdot
+#define vdi_fixextsize	vdi_ftarea.regular.fixextsize
+#define vdi_matchino	vdi_ftarea.vxspec.matchino
+#define vdi_fsetindex	vdi_ftarea.vxspec.fsetindex
+
+#define vdi_immed	vdi_org.immed
+#define vdi_ext4	vdi_org.ext4
+#define vdi_typed	vdi_org.typed
+
+
+/*
+ * The inode as represented in the main memory.
+ *
+ * TBD: This should become a separate structure...
+ */
+#define vxfs_inode_info	vxfs_dinode
+
+#define vii_mode	vdi_mode
+#define vii_uid		vdi_uid
+#define vii_gid		vdi_gid
+#define vii_nlink	vdi_nlink
+#define vii_size	vdi_size
+#define vii_atime	vdi_atime
+#define vii_ctime	vdi_ctime
+#define vii_mtime	vdi_mtime
+#define vii_blocks	vdi_blocks
+#define vii_org		vdi_org
+#define vii_orgtype	vdi_orgtype
+#define vii_gen		vdi_gen
+
+#define vii_rdev	vdi_ftarea.rdev
+#define vii_dotdot	vdi_ftarea.dotdot
+#define vii_fixextsize	vdi_ftarea.regular.fixextsize
+#define vii_matchino	vdi_ftarea.vxspec.matchino
+#define vii_fsetindex	vdi_ftarea.vxspec.fsetindex
+
+#define vii_immed	vdi_org.immed
+#define vii_ext4	vdi_org.ext4
+#define vii_typed	vdi_org.typed
+
+#endif /* _VXFS_INODE_H_ */
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_lookup.c linux/fs/freevxfs/vxfs_lookup.c
--- v2.4.4/linux/fs/freevxfs/vxfs_lookup.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_lookup.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_lookup.c,v 1.17 2001/05/21 15:23:53 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - lookup and other directory related code.
+ */
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/kernel.h>
+#include <linux/pagemap.h>
+
+#include "vxfs.h"
+#include "vxfs_dir.h"
+#include "vxfs_inode.h"
+#include "vxfs_extern.h"
+
+/*
+ * Number of VxFS blocks per page.
+ */
+#define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
+
+
+static struct dentry *	vxfs_lookup(struct inode *, struct dentry *);
+static int		vxfs_readdir(struct file *, void *, filldir_t);
+
+struct inode_operations vxfs_dir_inode_ops = {
+	.lookup =		vxfs_lookup,
+};
+
+struct file_operations vxfs_dir_operations = {
+	.readdir =		vxfs_readdir,
+};
+
+ 
+static __inline__ u_long
+dir_pages(struct inode *inode)
+{
+	return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+}
+ 
+static __inline__ u_long
+dir_blocks(struct inode *ip)
+{
+	u_long			bsize = ip->i_sb->s_blocksize;
+	return (ip->i_size + bsize - 1) & ~(bsize - 1);
+}
+
+/*
+ * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
+ *
+ * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
+ */
+static __inline__ int
+vxfs_match(int len, const char * const name, struct vxfs_direct *de)
+{
+	if (len != de->d_namelen)
+		return 0;
+	if (!de->d_ino)
+		return 0;
+	return !memcmp(name, de->d_name, len);
+}
+
+static __inline__ struct vxfs_direct *
+vxfs_next_entry(struct vxfs_direct *de)
+{
+	return ((struct vxfs_direct *)((char*)de + de->d_reclen));
+}
+
+/**
+ * vxfs_find_entry - find a mathing directory entry for a dentry
+ * @ip:		directory inode
+ * @dp:		dentry for which we want to find a direct
+ * @ppp:	gets filled with the page the return value sits in
+ *
+ * Description:
+ *   vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
+ *   cache entry @dp.  @ppp will be filled with the page the return
+ *   value resides in.
+ *
+ * Returns:
+ *   The wanted direct on success, else a NULL pointer.
+ */
+static struct vxfs_direct *
+vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
+{
+	u_long				npages, page, nblocks, pblocks, block;
+	u_long				bsize = ip->i_sb->s_blocksize;
+	const char			*name = dp->d_name.name;
+	int				namelen = dp->d_name.len;
+
+	npages = dir_pages(ip);
+	nblocks = dir_blocks(ip);
+	pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
+	
+	for (page = 0; page < npages; page++) {
+		caddr_t			kaddr;
+		struct page		*pp;
+
+		pp = vxfs_get_page(ip, page);
+		if (IS_ERR(pp))
+			continue;
+		kaddr = (caddr_t)page_address(pp);
+
+		for (block = 0; block <= nblocks && block <= pblocks; block++) {
+			caddr_t			baddr, limit;
+			struct vxfs_dirblk	*dbp;
+			struct vxfs_direct	*de;
+
+			baddr = kaddr + (block * bsize);
+			limit = baddr + bsize - VXFS_DIRLEN(1);
+			
+			dbp = (struct vxfs_dirblk *)baddr;
+			de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
+
+			for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
+				if (!de->d_reclen)
+					break;
+				if (!de->d_ino)
+					continue;
+				if (vxfs_match(namelen, name, de)) {
+					*ppp = pp;
+					return (de);
+				}
+			}
+		}
+		vxfs_put_page(pp);
+	}
+
+	return NULL;
+}
+
+/**
+ * vxfs_inode_by_name - find inode number for dentry
+ * @dip:	directory to search in
+ * @dp:		dentry we seach for
+ *
+ * Description:
+ *   vxfs_inode_by_name finds out the inode number of
+ *   the path component described by @dp in @dip.
+ *
+ * Returns:
+ *   The wanted inode number on success, else Zero.
+ */
+static ino_t
+vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
+{
+	struct vxfs_direct		*de;
+	struct page			*pp;
+	ino_t				ino = 0;
+
+	de = vxfs_find_entry(dip, dp, &pp);
+	if (de) {
+		ino = de->d_ino;
+		kunmap(pp);
+		page_cache_release(pp);
+	}
+	
+	return (ino);
+}
+
+/**
+ * vxfs_lookup - lookup pathname component
+ * @dip:	dir in which we lookup
+ * @dp:		dentry we lookup
+ *
+ * Description:
+ *   vxfs_lookup tries to lookup the pathname component described
+ *   by @dp in @dip.
+ *
+ * Returns:
+ *   A NULL-pointer on success, else an negative error code encoded
+ *   in the return pointer.
+ */
+static struct dentry *
+vxfs_lookup(struct inode *dip, struct dentry *dp)
+{
+	struct inode		*ip = NULL;
+	ino_t			ino;
+			 
+	if (dp->d_name.len > VXFS_NAMELEN)
+		return ERR_PTR(-ENAMETOOLONG);
+				 
+	ino = vxfs_inode_by_name(dip, dp);
+	if (ino == 0)
+		return NULL;
+
+	ip = iget(dip->i_sb, ino);
+	if (!ip)
+		return ERR_PTR(-EACCES);
+	d_add(dp, ip);
+	return NULL;
+}
+
+/**
+ * vxfs_readdir - read a directory
+ * @fp:		the directory to read
+ * @retp:	return buffer
+ * @filler:	filldir callback
+ *
+ * Description:
+ *   vxfs_readdir fills @retp with directory entries from @fp
+ *   using the VFS supplied callback @filler.
+ *
+ * Returns:
+ *   Zero.
+ */
+static int
+vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
+{
+	struct inode		*ip = fp->f_dentry->d_inode;
+	struct super_block	*sbp = ip->i_sb;
+	u_long			bsize = sbp->s_blocksize;
+	u_long			page, npages, block, nblocks, offset;
+	loff_t			pos;
+	int			pblocks;
+
+	switch ((long)fp->f_pos) {
+	case 0:
+		if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
+			goto out;
+		fp->f_pos++;
+		/* fallthrough */
+	case 1:
+		if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0)
+			goto out;
+		fp->f_pos++;
+		/* fallthrough */
+	}
+
+	pos = fp->f_pos - 2;
+	
+	if (pos > VXFS_DIRROUND(ip->i_size))
+		return 0;
+
+	page = pos >> PAGE_CACHE_SHIFT;
+	offset = pos & ~PAGE_CACHE_MASK;
+	block = pos >> sbp->s_blocksize_bits;
+
+	npages = dir_pages(ip);
+	nblocks = dir_blocks(ip);
+	pblocks = VXFS_BLOCK_PER_PAGE(sbp);
+
+	for (; page < npages; page++, block = 0) {
+		caddr_t			kaddr;
+		struct page		*pp;
+
+		pp = vxfs_get_page(ip, page);
+		if (IS_ERR(pp))
+			continue;
+		kaddr = (caddr_t)page_address(pp);
+
+		for (; block <= nblocks && block <= pblocks; block++) {
+			caddr_t			baddr, limit;
+			struct vxfs_dirblk	*dbp;
+			struct vxfs_direct	*de;
+
+			baddr = kaddr + (block * bsize);
+			limit = baddr + bsize - VXFS_DIRLEN(1);
+	
+			dbp = (struct vxfs_dirblk *)baddr;
+			de = (struct vxfs_direct *)
+				(offset ?
+				 (kaddr + offset) :
+				 (baddr + VXFS_DIRBLKOV(dbp)));
+
+			for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
+				int	over;
+
+				if (!de->d_reclen)
+					break;
+				if (!de->d_ino)
+					continue;
+
+				offset = (caddr_t)de - kaddr;
+				over = filler(retp, de->d_name, de->d_namelen,
+					((page << PAGE_CACHE_SHIFT) | offset) + 2,
+					de->d_ino, DT_UNKNOWN);
+				if (over) {
+					vxfs_put_page(pp);
+					goto done;
+				}
+			}
+		}
+		vxfs_put_page(pp);
+		offset = 0;
+	}
+
+done:
+	fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
+out:
+	fp->f_version = ip->i_version;
+	return 0;
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_olt.c linux/fs/freevxfs/vxfs_olt.c
--- v2.4.4/linux/fs/freevxfs/vxfs_olt.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_olt.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_olt.c,v 1.8 2001/04/25 18:11:23 hch Exp hch $"
+
+/* 
+ * Veritas filesystem driver - object location table support.
+ */
+#include <linux/fs.h>
+#include <linux/kernel.h>
+
+#include "vxfs.h"
+#include "vxfs_olt.h"
+
+
+static __inline__ void
+vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
+{
+	if (infp->vsi_fshino)
+		BUG();
+	infp->vsi_fshino = fshp->olt_fsino[0];
+}
+
+static __inline__ void
+vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
+{
+	if (infp->vsi_iext)
+		BUG();
+	infp->vsi_iext = ilistp->olt_iext[0]; 
+}
+
+static __inline__ u_long
+vxfs_oblock(daddr_t oblock, u_long bsize)
+{
+	if ((oblock * BLOCK_SIZE) % bsize)
+		BUG();
+	return ((oblock * BLOCK_SIZE) / bsize);
+}
+
+
+/**
+ * vxfs_read_olt - read olt
+ * @sbp:	superblock of the filesystem
+ * @bsize:	blocksize of the filesystem
+ *
+ * Description:
+ *   vxfs_read_olt reads the olt of the filesystem described by @sbp
+ *   into main memory and does some basic setup.
+ *
+ * Returns:
+ *   Zero on success, else a negative error code.
+ */
+int
+vxfs_read_olt(struct super_block *sbp, u_long bsize)
+{
+	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
+	struct buffer_head	*bp;
+	struct vxfs_olt		*op;
+	char			*oaddr, *eaddr;
+
+
+	bp = bread(sbp->s_dev, vxfs_oblock(infp->vsi_oltext, bsize), bsize);
+	if (!bp || !bp->b_data)
+		goto fail;
+
+	op = (struct vxfs_olt *)bp->b_data;
+	if (op->olt_magic != VXFS_OLT_MAGIC) {
+		printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
+		goto fail;
+	}
+
+	oaddr = (char *)bp->b_data + op->olt_size;
+	eaddr = (char *)bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
+
+	while (oaddr < eaddr) {
+		struct vxfs_oltcommon	*ocp =
+			(struct vxfs_oltcommon *)oaddr;
+		
+		switch (ocp->olt_type) {
+		case VXFS_OLT_FSHEAD:
+			vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
+			break;
+		case VXFS_OLT_ILIST:
+			vxfs_get_ilist((struct vxfs_oltilist *)oaddr, infp);
+			break;
+		}
+
+		oaddr += ocp->olt_size;
+	}
+
+	brelse(bp);
+	return 0;
+
+fail:
+	brelse(bp);
+	return -EINVAL;
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_olt.h linux/fs/freevxfs/vxfs_olt.h
--- v2.4.4/linux/fs/freevxfs/vxfs_olt.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_olt.h	Mon May 21 12:31:06 2001
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+#ifndef _VXFS_OLT_H_
+#define _VXFS_OLT_H_
+
+#ident "$Id: vxfs_olt.h,v 1.5 2001/04/25 18:11:23 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - Object Location Table data structures.
+ *
+ * This file contains definitions for the Object Location Table used
+ * by the Veritas Filesystem version 2 and newer.
+ */
+
+
+/*
+ * OLT magic number (vxfs_olt->olt_magic).
+ */
+#define VXFS_OLT_MAGIC		0xa504FCF5
+
+/*
+ * VxFS OLT entry types.
+ */
+enum {
+	VXFS_OLT_FREE	= 1,
+	VXFS_OLT_FSHEAD	= 2,
+	VXFS_OLT_CUT	= 3,
+	VXFS_OLT_ILIST	= 4,
+	VXFS_OLT_DEV	= 5,
+	VXFS_OLT_SB	= 6
+};
+
+/*
+ * VxFS OLT header.
+ *
+ * The Object Location Table header is placed at the beginning of each
+ * OLT extent.  It is used to fing certain filesystem-wide metadata, e.g.
+ * the inital inode list, the fileset header or the device configuration.
+ */
+struct vxfs_olt {
+	u_int32_t	olt_magic;	/* magic number			*/
+	u_int32_t	olt_size;	/* size of this entry		*/
+	u_int32_t	olt_checksum;	/* checksum of extent		*/
+	u_int32_t	__unused1;	/* ???				*/
+	u_int32_t	olt_mtime;	/* time of last mod. (sec)	*/
+	u_int32_t	olt_mutime;	/* time of last mod. (usec)	*/
+	u_int32_t	olt_totfree;	/* free space in OLT extent	*/
+	vx_daddr_t	olt_extents[2];	/* addr of this extent, replica	*/
+	u_int32_t	olt_esize;	/* size of this extent		*/
+	vx_daddr_t	olt_next[2];    /* addr of next extent, replica	*/
+	u_int32_t	olt_nsize;	/* size of next extent		*/
+	u_int32_t	__unused2;	/* align to 8 byte boundary	*/
+};
+
+/*
+ * VxFS common OLT entry (on disk).
+ */
+struct vxfs_oltcommon {
+	u_int32_t	olt_type;	/* type of this record		*/
+	u_int32_t	olt_size;	/* size of this record		*/
+};
+
+/*
+ * VxFS free OLT entry (on disk).
+ */
+struct vxfs_oltfree {
+	u_int32_t	olt_type;	/* type of this record		*/
+	u_int32_t	olt_fsize;	/* size of this free record	*/
+};
+
+/*
+ * VxFS initial-inode list (on disk).
+ */
+struct vxfs_oltilist {
+	u_int32_t	olt_type;	/* type of this record		*/
+	u_int32_t	olt_size;	/* size of this record		*/
+	vx_ino_t	olt_iext[2];	/* initial inode list, replica	*/
+};
+
+/*
+ * Current Usage Table 
+ */
+struct vxfs_oltcut {
+	u_int32_t	olt_type;	/* type of this record		*/
+	u_int32_t	olt_size;	/* size of this record		*/
+	vx_ino_t	olt_cutino;	/* inode of current usage table	*/
+	u_int32_t	__pad;		/* unused, 8 byte align		*/
+};
+
+/*
+ * Inodes containing Superblock, Intent log and OLTs 
+ */
+struct vxfs_oltsb {
+	u_int32_t	olt_type;	/* type of this record		*/
+	u_int32_t	olt_size;	/* size of this record		*/
+	vx_ino_t	olt_sbino;	/* inode of superblock file	*/
+	u_int32_t	__unused1;	/* ???				*/
+	vx_ino_t	olt_logino[2];	/* inode of log file,replica	*/
+	vx_ino_t	olt_oltino[2];	/* inode of OLT, replica	*/
+};
+
+/*
+ * Inode containing device configuration + it's replica 
+ */
+struct vxfs_oltdev {
+	u_int32_t	olt_type;	/* type of this record		*/
+	u_int32_t	olt_size;	/* size of this record		*/
+	vx_ino_t	olt_devino[2];	/* inode of device config files	*/
+};
+
+/*
+ * Fileset header 
+ */
+struct vxfs_oltfshead {
+	u_int32_t	olt_type;	/* type number			*/
+	u_int32_t	olt_size;	/* size of this record		*/
+	vx_ino_t	olt_fsino[2];   /* inodes of fileset header	*/
+};
+
+#endif /* _VXFS_OLT_H_ */
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_subr.c linux/fs/freevxfs/vxfs_subr.c
--- v2.4.4/linux/fs/freevxfs/vxfs_subr.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_subr.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_subr.c,v 1.5 2001/04/26 22:49:51 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - shared subroutines.
+ */
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+
+#include "vxfs_extern.h"
+
+
+static int		vxfs_readpage(struct file *, struct page *);
+static int		vxfs_bmap(struct address_space *, long);
+
+struct address_space_operations vxfs_aops = {
+	.readpage =		vxfs_readpage,
+	.bmap =			vxfs_bmap
+};
+
+
+/**
+ * vxfs_get_page - read a page into memory.
+ * @ip:		inode to read from
+ * @n:		page number
+ *
+ * Description:
+ *   vxfs_get_page reads the @n th page of @ip into the pagecache.
+ *
+ * Returns:
+ *   The wanted page on success, else a NULL pointer.
+ */
+struct page *
+vxfs_get_page(struct inode *ip, u_long n)
+{
+	struct address_space *		mapping = ip->i_mapping;
+	struct page *			pp;
+
+	pp = read_cache_page(mapping, n,
+			(filler_t*)mapping->a_ops->readpage, NULL);
+
+	if (!IS_ERR(pp)) {
+		wait_on_page(pp);
+		kmap(pp);
+		if (!Page_Uptodate(pp))
+			goto fail;
+		/** if (!PageChecked(pp)) **/
+			/** vxfs_check_page(pp); **/
+		if (PageError(pp))
+			goto fail;
+	}
+	
+	return (pp);
+		 
+fail:
+	vxfs_put_page(pp);
+	return ERR_PTR(-EIO);
+}
+
+__inline__ void
+vxfs_put_page(struct page *pp)
+{
+	kunmap(pp);
+	page_cache_release(pp);
+}
+
+/**
+ * vxfs_bread - read buffer for a give inode,block tuple
+ * @ip:		inode
+ * @block:	logical block
+ *
+ * Description:
+ *   The vxfs_bread function reads block no @block  of
+ *   @ip into the buffercache.
+ *
+ * Returns:
+ *   The resulting &struct buffer_head.
+ */
+struct buffer_head *
+vxfs_bread(struct inode *ip, int block)
+{
+	struct buffer_head	*bp;
+	daddr_t			pblock;
+
+	pblock = vxfs_bmap1(ip, block);
+	bp = bread(ip->i_dev, pblock, ip->i_sb->s_blocksize);
+
+	return (bp);
+}
+
+/**
+ * vxfs_get_block - locate buffer for given inode,block tuple 
+ * @ip:		inode
+ * @iblock:	logical block
+ * @bp:		buffer skeleton
+ * @create:	%TRUE if blocks may be newly allocated.
+ *
+ * Description:
+ *   The vxfs_get_block function fills @bp with the right physical
+ *   block and device number to perform a lowlevel read/write on
+ *   it.
+ *
+ * Returns:
+ *   Zero on success, else a negativ error code (-EIO).
+ */
+static int
+vxfs_getblk(struct inode *ip, long iblock,
+	    struct buffer_head *bp, int create)
+{
+	daddr_t			pblock;
+
+	pblock = vxfs_bmap1(ip, iblock);
+	if (pblock != 0) {
+		bp->b_dev = ip->i_dev;
+		bp->b_blocknr = pblock;
+		bp->b_state |= (1UL << BH_Mapped);
+
+		return 0;
+	}
+
+	return -EIO;
+}
+
+/**
+ * vxfs_readpage - read one page synchronously into the pagecache
+ * @file:	file context (unused)
+ * @page:	page frame to fill in.
+ *
+ * Description:
+ *   The vxfs_readpage routine reads @page synchronously into the
+ *   pagecache.
+ *
+ * Returns:
+ *   Zero on success, else a negative error code.
+ *
+ * Locking status:
+ *   @page is locked and will be unlocked.
+ */
+static int
+vxfs_readpage(struct file *file, struct page *page)
+{
+	return block_read_full_page(page, vxfs_getblk);
+}
+ 
+/**
+ * vxfs_bmap - perform logical to physical block mapping
+ * @mapping:	logical to physical mapping to use
+ * @block:	logical block (relative to @mapping).
+ *
+ * Description:
+ *   Vxfs_bmap find out the corresponding phsical block to the
+ *   @mapping, @block pair.
+ *
+ * Returns:
+ *   Physical block number on success, else Zero.
+ *
+ * Locking status:
+ *   We are under the bkl.
+ */
+static int
+vxfs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping, block, vxfs_getblk);
+}
diff -u --recursive --new-file v2.4.4/linux/fs/freevxfs/vxfs_super.c linux/fs/freevxfs/vxfs_super.c
--- v2.4.4/linux/fs/freevxfs/vxfs_super.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/freevxfs/vxfs_super.c	Mon May 21 12:31:06 2001
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2000-2001 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#ident "$Id: vxfs_super.c,v 1.24 2001/05/20 15:21:14 hch Exp hch $"
+
+/*
+ * Veritas filesystem driver - superblock related routines.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <linux/blkdev.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+
+#include "vxfs.h"
+#include "vxfs_extern.h"
+#include "vxfs_dir.h"
+#include "vxfs_inode.h"
+
+
+MODULE_AUTHOR("Christoph Hellwig");
+MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
+
+
+static void		vxfs_put_super(struct super_block *);
+static int		vxfs_statfs(struct super_block *, struct statfs *);
+
+
+static struct super_operations vxfs_super_ops = {
+	.read_inode =		vxfs_read_inode,
+	.put_inode =		vxfs_put_inode,
+	.put_super =		vxfs_put_super,
+	.statfs =		vxfs_statfs,
+};
+
+static __inline__ u_long
+vxfs_validate_bsize(kdev_t dev)
+{
+	u_long			bsize;
+	
+	bsize = get_hardsect_size(dev);
+	if (bsize < BLOCK_SIZE)
+		bsize = BLOCK_SIZE;
+
+	set_blocksize(dev, bsize);
+	return (bsize);
+}
+
+/**
+ * vxfs_put_super - free superblock resources
+ * @sbp:	VFS superblock.
+ *
+ * Description:
+ *   vxfs_put_super frees all resources allocated for @sbp
+ *   after the last instance of the filesystem is unmounted.
+ */
+static void
+vxfs_put_super(struct super_block *sbp)
+{
+	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
+
+	vxfs_put_inode(infp->vsi_fship);
+	vxfs_put_inode(infp->vsi_ilist);
+	vxfs_put_inode(infp->vsi_stilist);
+
+	brelse(infp->vsi_bp);
+	kfree(infp);
+}
+
+/**
+ * vxfs_statfs - get filesystem information
+ * @sbp:	VFS superblock
+ * @bufp:	output buffer
+ *
+ * Description:
+ *   vxfs_statfs fills the statfs buffer @bufp with information
+ *   about the filesystem described by @sbp.
+ *
+ * Returns:
+ *   Zero.
+ *
+ * Locking:
+ *   We are under bkl and @sbp->s_lock.
+ *
+ * Notes:
+ *   This is everything but complete...
+ */
+static int
+vxfs_statfs(struct super_block *sbp, struct statfs *bufp)
+{
+	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
+
+	bufp->f_type = VXFS_SUPER_MAGIC;
+	bufp->f_bsize = sbp->s_blocksize;
+	bufp->f_blocks = infp->vsi_raw->vs_dsize;
+	bufp->f_bfree = infp->vsi_raw->vs_free;
+	bufp->f_bavail = 0;
+	bufp->f_files = 0;
+	bufp->f_ffree = infp->vsi_raw->vs_ifree;
+	bufp->f_namelen = VXFS_NAMELEN;
+
+	return 0;
+}
+
+/**
+ * vxfs_read_super - read superblock into memory and initalize filesystem
+ * @sbp:		VFS superblock (to fill)
+ * @dp:			fs private mount data
+ * @silent:		???
+ *
+ * Description:
+ *   We are called on the first mount of a filesystem to read the
+ *   superblock into memory and do some basic setup.
+ *
+ * Returns:
+ *   The superblock on success, else %NULL.
+ *
+ * Locking:
+ *   We are under the bkl and @sbp->s_lock.
+ */
+static struct super_block *
+vxfs_read_super(struct super_block *sbp, void *dp, int silent)
+{
+	struct vxfs_sb_info	*infp;
+	struct vxfs_sb		*rsbp;
+	struct buffer_head	*bp;
+	u_long			bsize;
+	kdev_t			dev = sbp->s_dev;
+
+	infp = kmalloc(sizeof(struct vxfs_sb_info), GFP_KERNEL);
+	if (!infp) {
+		printk(KERN_WARNING "vxfs: unable to allocate incore superblock\n");
+		return NULL;
+	}
+	memset(infp, 0, sizeof(struct vxfs_sb_info));
+
+	bsize = vxfs_validate_bsize(dev);
+
+	bp = bread(dev, 1, bsize);
+	if (!bp) {
+		printk(KERN_WARNING "vxfs: unable to read disk superblock\n");
+		return NULL;
+	}
+
+	rsbp = (struct vxfs_sb *)bp->b_data;
+	if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
+		printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+		return NULL;
+	}
+
+	if (rsbp->vs_version < 2 || rsbp->vs_version > 4) {
+		printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", rsbp->vs_version);
+		return NULL;
+	}
+
+#ifdef DIAGNOSTIC
+	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
+	printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
+#endif
+
+	sbp->s_magic = rsbp->vs_magic;
+	sbp->u.generic_sbp = (void *)infp;
+
+	infp->vsi_raw = rsbp;
+	infp->vsi_bp = bp;
+	infp->vsi_oltext = rsbp->vs_oltext[0];
+	infp->vsi_oltsize = rsbp->vs_oltsize;
+	
+	sbp->s_blocksize = rsbp->vs_bsize;
+
+	switch (rsbp->vs_bsize) {
+	case 1024:
+		sbp->s_blocksize_bits = 10;
+		break;
+	case 2048:
+		sbp->s_blocksize_bits = 11;
+		break;
+	case 4096:
+		sbp->s_blocksize_bits = 12;
+		break;
+	default:
+		printk(KERN_WARNING "vxfs: unsupported blocksise: %d\n",
+				rsbp->vs_bsize);
+		return NULL;
+	}
+
+	if (vxfs_read_olt(sbp, bsize)) {
+		printk(KERN_WARNING "vxfs: unable to read olt\n");
+		return NULL;
+	}
+
+	if (vxfs_read_fshead(sbp)) {
+		printk(KERN_WARNING "vxfs: unable to read fshead\n");
+		return NULL;
+	}
+
+	sbp->s_op = &vxfs_super_ops;
+	if ((sbp->s_root = d_alloc_root(iget(sbp, VXFS_ROOT_INO))))
+		return (sbp);
+	
+	printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
+	return NULL;
+}
+
+
+/*
+ * The usual module blurb.
+ */
+static DECLARE_FSTYPE_DEV(vxfs_fs_type, "vxfs", vxfs_read_super);
+
+static int __init
+vxfs_init(void)
+{
+	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+			sizeof(struct vxfs_inode_info), 0, 0, NULL, NULL);
+	if (vxfs_inode_cachep)
+		return (register_filesystem(&vxfs_fs_type));
+	return 0;
+}
+
+static void __exit
+vxfs_cleanup(void)
+{
+	unregister_filesystem(&vxfs_fs_type);
+	kmem_cache_destroy(vxfs_inode_cachep);
+}
+
+module_init(vxfs_init);
+module_exit(vxfs_cleanup);
diff -u --recursive --new-file v2.4.4/linux/fs/inode.c linux/fs/inode.c
--- v2.4.4/linux/fs/inode.c	Fri Apr 27 14:11:30 2001
+++ linux/fs/inode.c	Tue May 22 09:35:42 2001
@@ -497,6 +497,10 @@
 		bdput(inode->i_bdev);
 		inode->i_bdev = NULL;
 	}
+	if (inode->i_cdev) {
+		cdput(inode->i_cdev);
+		inode->i_cdev = NULL;
+	}
 	inode->i_state = I_CLEAR;
 }
 
@@ -591,6 +595,22 @@
 
 	return busy;
 }
+ 
+int invalidate_device(kdev_t dev, int do_sync)
+{
+	struct super_block *sb = get_super(dev);
+	int res;
+
+	if (do_sync)
+		fsync_dev(dev);
+
+	res = 0;
+	if (sb)
+		res = invalidate_inodes(sb);
+	invalidate_buffers(dev);
+	return res;
+}
+
 
 /*
  * This is called with the inode lock held. It searches
@@ -612,12 +632,13 @@
 {
 	LIST_HEAD(list);
 	struct list_head *entry, *freeable = &list;
-	int count = 0, synced = 0;
+	int count, synced = 0;
 	struct inode * inode;
 
 	spin_lock(&inode_lock);
 
 free_unused:
+	count = 0;
 	entry = inode_unused.prev;
 	while (entry != &inode_unused)
 	{
@@ -733,6 +754,7 @@
 	memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
 	inode->i_pipe = NULL;
 	inode->i_bdev = NULL;
+	inode->i_cdev = NULL;
 	inode->i_data.a_ops = &empty_aops;
 	inode->i_data.host = inode;
 	inode->i_data.gfp_mask = GFP_HIGHUSER;
diff -u --recursive --new-file v2.4.4/linux/fs/isofs/util.c linux/fs/isofs/util.c
--- v2.4.4/linux/fs/isofs/util.c	Wed Nov 29 10:11:38 2000
+++ linux/fs/isofs/util.c	Tue May  1 18:21:01 2001
@@ -1,90 +1,10 @@
 /*
  *  linux/fs/isofs/util.c
- *
- *  The special functions in the file are numbered according to the section
- *  of the iso 9660 standard in which they are described.  isonum_733 will
- *  convert numbers according to section 7.3.3, etc.
- *
- *  isofs special functions.  This file was lifted in its entirety from
- *  the 386BSD iso9660 filesystem, by Pace Willisson <pace@blitz.com>.
  */
 
 #include <linux/time.h>
-
-int
-isonum_711 (char * p)
-{
-	return (*p & 0xff);
-}
-
-int
-isonum_712 (char * p)
-{
-	int val;
-	
-	val = *p;
-	if (val & 0x80)
-		val |= 0xffffff00;
-	return (val);
-}
-
-int
-isonum_721 (char * p)
-{
-	return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
-}
-
-int
-isonum_722 (char * p)
-{
-	return (((p[0] & 0xff) << 8) | (p[1] & 0xff));
-}
-
-int
-isonum_723 (char * p)
-{
-#if 0
-	if (p[0] != p[3] || p[1] != p[2]) {
-		fprintf (stderr, "invalid format 7.2.3 number\n");
-		exit (1);
-	}
-#endif
-	return (isonum_721 (p));
-}
-
-int
-isonum_731 (char * p)
-{
-	return ((p[0] & 0xff)
-		| ((p[1] & 0xff) << 8)
-		| ((p[2] & 0xff) << 16)
-		| ((p[3] & 0xff) << 24));
-}
-
-int
-isonum_732 (char * p)
-{
-	return (((p[0] & 0xff) << 24)
-		| ((p[1] & 0xff) << 16)
-		| ((p[2] & 0xff) << 8)
-		| (p[3] & 0xff));
-}
-
-int
-isonum_733 (char * p)
-{
-#if 0
-	int i;
-
-	for (i = 0; i < 4; i++) {
-		if (p[i] != p[7-i]) {
-			fprintf (stderr, "bad format 7.3.3 number\n");
-			exit (1);
-		}
-	}
-#endif
-	return (isonum_731 (p));
-}
+#include <linux/fs.h>
+#include <linux/iso_fs.h>
 
 /* 
  * We have to convert from a MM/DD/YY format to the Unix ctime format.
diff -u --recursive --new-file v2.4.4/linux/fs/jffs/inode-v23.c linux/fs/jffs/inode-v23.c
--- v2.4.4/linux/fs/jffs/inode-v23.c	Fri Mar  2 11:12:11 2001
+++ linux/fs/jffs/inode-v23.c	Sun May 20 11:35:00 2001
@@ -160,7 +160,6 @@
 
 	D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
 
-	sb->s_dev = 0;
 	jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp);
 	D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
 	       kdevname(dev)));
diff -u --recursive --new-file v2.4.4/linux/fs/namei.c linux/fs/namei.c
--- v2.4.4/linux/fs/namei.c	Fri Apr 20 16:04:32 2001
+++ linux/fs/namei.c	Sat May 19 18:02:45 2001
@@ -748,26 +748,24 @@
 }
 
 /* SMP-safe */
-struct dentry * lookup_one(const char * name, struct dentry * base)
+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
 {
 	unsigned long hash;
 	struct qstr this;
 	unsigned int c;
 
 	this.name = name;
-	c = *(const unsigned char *)name;
-	if (!c)
+	this.len = len;
+	if (!len)
 		goto access;
 
 	hash = init_name_hash();
-	do {
-		name++;
-		if (c == '/')
+	while (len--) {
+		c = *(const unsigned char *)name++;
+		if (c == '/' || c == '\0')
 			goto access;
 		hash = partial_name_hash(c, hash);
-		c = *(const unsigned char *)name;
-	} while (c);
-	this.len = name - (const char *) this.name;
+	}
 	this.hash = end_name_hash(hash);
 
 	return lookup_hash(&this, base);
diff -u --recursive --new-file v2.4.4/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.4.4/linux/fs/nfs/dir.c	Thu Mar 15 09:56:07 2001
+++ linux/fs/nfs/dir.c	Sat May 19 18:02:45 2001
@@ -802,7 +802,7 @@
 		dfprintk(VFS, "trying to rename %s to %s\n",
 			 dentry->d_name.name, silly);
 		
-		sdentry = lookup_one(silly, dentry->d_parent);
+		sdentry = lookup_one_len(silly, dentry->d_parent, slen);
 		/*
 		 * N.B. Better to return EBUSY here ... it could be
 		 * dangerous to delete the file while it's in use.
diff -u --recursive --new-file v2.4.4/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.4.4/linux/fs/nfs/file.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/nfs/file.c	Tue May 22 09:26:06 2001
@@ -39,6 +39,7 @@
 static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *);
 static int  nfs_file_flush(struct file *);
 static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
+static int  nfs_file_release(struct inode *, struct file *);
 
 struct file_operations nfs_file_operations = {
 	read:		nfs_file_read,
@@ -46,7 +47,7 @@
 	mmap:		nfs_file_mmap,
 	open:		nfs_open,
 	flush:		nfs_file_flush,
-	release:	nfs_release,
+	release:	nfs_file_release,
 	fsync:		nfs_fsync,
 	lock:		nfs_lock,
 };
@@ -87,6 +88,13 @@
 	return status;
 }
 
+static int
+nfs_file_release(struct inode *inode, struct file *file)
+{
+	filemap_fdatasync(inode->i_mapping);
+	return nfs_release(inode,file);
+}
+
 static ssize_t
 nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
 {
@@ -283,16 +291,21 @@
 	 * Flush all pending writes before doing anything
 	 * with locks..
 	 */
-	down(&filp->f_dentry->d_inode->i_sem);
+	filemap_fdatasync(inode->i_mapping);
+	down(&inode->i_sem);
 	status = nfs_wb_all(inode);
-	up(&filp->f_dentry->d_inode->i_sem);
+	up(&inode->i_sem);
+	filemap_fdatawait(inode->i_mapping);
 	if (status < 0)
 		return status;
 
-	if ((status = nlmclnt_proc(inode, cmd, fl)) < 0)
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	unlock_kernel();
+	if (status < 0)
 		return status;
-	else
-		status = 0;
+	
+	status = 0;
 
 	/*
 	 * Make sure we clear the cache whenever we try to get the lock.
@@ -300,10 +313,12 @@
 	 */
  out_ok:
 	if ((cmd == F_SETLK || cmd == F_SETLKW) && fl->fl_type != F_UNLCK) {
-		down(&filp->f_dentry->d_inode->i_sem);
+		filemap_fdatasync(inode->i_mapping);
+		down(&inode->i_sem);
 		nfs_wb_all(inode);      /* we may have slept */
+		up(&inode->i_sem);
+		filemap_fdatawait(inode->i_mapping);
 		nfs_zap_caches(inode);
-		up(&filp->f_dentry->d_inode->i_sem);
 	}
 	return status;
 }
diff -u --recursive --new-file v2.4.4/linux/fs/nfs/flushd.c linux/fs/nfs/flushd.c
--- v2.4.4/linux/fs/nfs/flushd.c	Tue Apr  3 13:45:37 2001
+++ linux/fs/nfs/flushd.c	Sat May 19 17:47:55 2001
@@ -174,7 +174,7 @@
 	 */
 	NFS_FLAGS(inode) |= NFS_INO_FLUSH;
 	atomic_inc(&inode->i_count);
- out:
+out:;
 }
 
 /* Protect me using the BKL */
diff -u --recursive --new-file v2.4.4/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.4.4/linux/fs/nfs/inode.c	Wed Apr 25 14:58:17 2001
+++ linux/fs/nfs/inode.c	Sat May 19 18:14:38 2001
@@ -45,6 +45,7 @@
 static void nfs_invalidate_inode(struct inode *);
 
 static void nfs_read_inode(struct inode *);
+static void nfs_write_inode(struct inode *,int);
 static void nfs_delete_inode(struct inode *);
 static void nfs_put_super(struct super_block *);
 static void nfs_umount_begin(struct super_block *);
@@ -52,7 +53,7 @@
 
 static struct super_operations nfs_sops = { 
 	read_inode:	nfs_read_inode,
-	put_inode:	force_delete,
+	write_inode:	nfs_write_inode,
 	delete_inode:	nfs_delete_inode,
 	put_super:	nfs_put_super,
 	statfs:		nfs_statfs,
@@ -116,6 +117,14 @@
 }
 
 static void
+nfs_write_inode(struct inode *inode, int sync)
+{
+	int flags = sync ? FLUSH_WAIT : 0;
+
+	nfs_sync_file(inode, NULL, 0, 0, flags);
+}
+
+static void
 nfs_delete_inode(struct inode * inode)
 {
 	dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
@@ -887,40 +896,23 @@
  * A very similar scenario holds for the dir cache.
  */
 int
-nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+__nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
 	__u64		new_size, new_mtime;
 	loff_t		new_isize;
 	int		invalid = 0;
-	int		error = -EIO;
-
-	if (!inode || !fattr) {
-		printk(KERN_ERR "nfs_refresh_inode: inode or fattr is NULL\n");
-		goto out;
-	}
-	if (inode->i_mode == 0) {
-		printk(KERN_ERR "nfs_refresh_inode: empty inode\n");
-		goto out;
-	}
-
-	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
-		goto out;
-
-	if (is_bad_inode(inode))
-		goto out;
 
 	dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d info=0x%x)\n",
 			inode->i_dev, inode->i_ino,
 			atomic_read(&inode->i_count), fattr->valid);
 
-
 	if (NFS_FSID(inode) != fattr->fsid ||
 	    NFS_FILEID(inode) != fattr->fileid) {
 		printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n"
 		       "expected (0x%Lx/0x%Lx), got (0x%Lx/0x%Lx)\n",
 		       (long long)NFS_FSID(inode), (long long)NFS_FILEID(inode),
 		       (long long)fattr->fsid, (long long)fattr->fileid);
-		goto out;
+		goto out_err;
 	}
 
 	/*
@@ -933,8 +925,6 @@
 	new_size = fattr->size;
  	new_isize = nfs_size_to_loff_t(fattr->size);
 
-	error = 0;
-
 	/*
 	 * Update the read time so we don't revalidate too often.
 	 */
@@ -1024,11 +1014,9 @@
 
 	if (invalid)
 		nfs_zap_caches(inode);
+	return 0;
 
-out:
-	return error;
-
-out_changed:
+ out_changed:
 	/*
 	 * Big trouble! The inode has become a different object.
 	 */
@@ -1042,7 +1030,8 @@
 	 * (But we fall through to invalidate the caches.)
 	 */
 	nfs_invalidate_inode(inode);
-	goto out;
+ out_err:
+	return -EIO;
 }
 
 /*
diff -u --recursive --new-file v2.4.4/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.4.4/linux/fs/nfs/write.c	Tue Apr  3 13:45:37 2001
+++ linux/fs/nfs/write.c	Mon May 21 12:29:14 2001
@@ -457,6 +457,7 @@
 	 *     spinlock since it can run flushd().
 	 */
 	inode_schedule_scan(inode, req->wb_timeout);
+	mark_inode_dirty(inode);
 }
 
 /*
@@ -489,6 +490,7 @@
 	 *     spinlock since it can run flushd().
 	 */
 	inode_schedule_scan(inode, req->wb_timeout);
+	mark_inode_dirty(inode);
 }
 #endif
 
@@ -861,9 +863,12 @@
 		req = _nfs_find_request(inode, page);
 		if (req) {
 			if (!nfs_lock_request(req)) {
+				int error;
 				spin_unlock(&nfs_wreq_lock);
-				nfs_wait_on_request(req);
+				error = nfs_wait_on_request(req);
 				nfs_release_request(req);
+				if (error < 0)
+					return ERR_PTR(error);
 				continue;
 			}
 			spin_unlock(&nfs_wreq_lock);
@@ -1013,7 +1018,6 @@
 	struct dentry	*dentry = file->f_dentry;
 	struct inode	*inode = dentry->d_inode;
 	struct nfs_page	*req;
-	int		synchronous = file->f_flags & O_SYNC;
 	int		status = 0;
 
 	dprintk("NFS:      nfs_updatepage(%s/%s %d@%Ld)\n",
@@ -1044,24 +1048,14 @@
 	if (status < 0)
 		goto done;
 
-	if (req->wb_bytes == PAGE_CACHE_SIZE)
-		SetPageUptodate(page);
-
 	status = 0;
-	if (synchronous) {
-		int error;
-
-		error = nfs_sync_file(inode, file, page_index(page), 1, FLUSH_SYNC|FLUSH_STABLE);
-		if (error < 0 || (error = file->f_error) < 0)
-			status = error;
-		file->f_error = 0;
-	} else {
-		/* If we wrote past the end of the page.
-		 * Call the strategy routine so it can send out a bunch
-		 * of requests.
-		 */
-		if (req->wb_offset == 0 && req->wb_bytes == PAGE_CACHE_SIZE)
-			nfs_strategy(inode);
+	/* If we wrote past the end of the page.
+	 * Call the strategy routine so it can send out a bunch
+	 * of requests.
+	 */
+	if (req->wb_offset == 0 && req->wb_bytes == PAGE_CACHE_SIZE) {
+		SetPageUptodate(page);
+		nfs_strategy(inode);
 	}
 	nfs_release_request(req);
 done:
diff -u --recursive --new-file v2.4.4/linux/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
--- v2.4.4/linux/fs/nfsd/nfs3xdr.c	Fri Dec 29 14:07:23 2000
+++ linux/fs/nfsd/nfs3xdr.c	Sat May 19 18:02:45 2001
@@ -707,15 +707,13 @@
 		exp  = cd->dirfh->fh_export;
 
 		fh_init(&fh, NFS3_FHSIZE);
-		if (fh_verify(cd->rqstp, cd->dirfh, S_IFDIR, MAY_EXEC) != 0)
-			goto noexec;
 		if (isdotent(name, namlen)) {
 			dchild = dparent;
 			if (namlen == 2)
 				dchild = dchild->d_parent;
 			dchild = dget(dchild);
 		} else
-			dchild = lookup_one(name, dparent);
+			dchild = lookup_one_len(name, dparent,namlen);
 		if (IS_ERR(dchild))
 			goto noexec;
 		if (fh_compose(&fh, exp, dchild) != 0 || !dchild->d_inode)
diff -u --recursive --new-file v2.4.4/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.4.4/linux/fs/nfsd/nfsctl.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/nfsd/nfsctl.c	Wed May 16 10:04:25 2001
@@ -158,7 +158,7 @@
 			err = -EINVAL;
 		else {
 			memset(res,0, NFS_FHSIZE);
-			memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+			memcpy(res, &fh.fh_base, fh.fh_size);
 		}
 	}
 
@@ -191,7 +191,7 @@
 			err = -EINVAL;
 		else {
 			memset(res,0, NFS_FHSIZE);
-			memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+			memcpy(res, &fh.fh_base, fh.fh_size);
 		}
 	}
 
diff -u --recursive --new-file v2.4.4/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- v2.4.4/linux/fs/nfsd/nfsfh.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/nfsd/nfsfh.c	Sat May 19 17:47:55 2001
@@ -156,6 +156,7 @@
 		result = list_entry(lp,struct dentry, d_alias);
 		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
 			dget_locked(result);
+			result->d_vfs_flags |= DCACHE_REFERENCED;
 			spin_unlock(&dcache_lock);
 			iput(inode);
 			return result;
@@ -244,6 +245,11 @@
 	 */
 	pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
 	d_drop(tdentry); /* we never want ".." hashed */
+	if (!pdentry && tdentry->d_inode == NULL) {
+		/* File system cannot find ".." ... sad but possible */
+		dput(tdentry);
+		pdentry = ERR_PTR(-EINVAL);
+	}
 	if (!pdentry) {
 		/* I don't want to return a ".." dentry.
 		 * I would prefer to return an unconnected "IS_ROOT" dentry,
@@ -407,7 +413,7 @@
 				d_drop(result);
 				dput(result);
 				result = tmp;
-				/* If !found, then this is really wierd, but it shouldn't hurt */
+				/* If !found, then this is really weird, but it shouldn't hurt */
 			}
 		}
 	} else {
diff -u --recursive --new-file v2.4.4/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.4.4/linux/fs/nfsd/nfsproc.c	Mon Mar 12 18:14:55 2001
+++ linux/fs/nfsd/nfsproc.c	Sat May 19 18:02:45 2001
@@ -216,7 +216,7 @@
 	if (isdotent(argp->name, argp->len))
 		goto done;
 	fh_lock(dirfhp);
-	dchild = lookup_one(argp->name, dirfhp->fh_dentry);
+	dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
 	if (IS_ERR(dchild)) {
 		nfserr = nfserrno(PTR_ERR(dchild));
 		goto out_unlock;
diff -u --recursive --new-file v2.4.4/linux/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c
--- v2.4.4/linux/fs/nfsd/nfssvc.c	Thu Mar 15 09:56:07 2001
+++ linux/fs/nfsd/nfssvc.c	Sat May 19 17:47:55 2001
@@ -117,7 +117,7 @@
 	return error;
 }
 
-static void inline
+static inline void
 update_thread_usage(int busy_threads)
 {
 	unsigned long prev_call;
@@ -253,7 +253,7 @@
 		return 0;
 	case RC_REPLY:
 		return 1;
-	case RC_DOIT:
+	case RC_DOIT:;
 		/* do it */
 	}
 
diff -u --recursive --new-file v2.4.4/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.4.4/linux/fs/nfsd/vfs.c	Mon Mar 12 18:13:28 2001
+++ linux/fs/nfsd/vfs.c	Sat May 19 18:02:45 2001
@@ -98,7 +98,7 @@
 	struct dentry		*dentry;
 	int			err;
 
-	dprintk("nfsd: nfsd_lookup(fh %s, %s)\n", SVCFH_fmt(fhp), name);
+	dprintk("nfsd: nfsd_lookup(fh %s, %*.*s)\n", SVCFH_fmt(fhp), len,len,name);
 
 	/* Obtain dentry and export. */
 	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
@@ -111,40 +111,42 @@
 	err = nfserr_acces;
 
 	/* Lookup the name, but don't follow links */
-	if (strcmp(name, ".")==0) {
-		dentry = dget(dparent);
-	} else if (strcmp(name, "..")==0) {
-		/* checking mountpoint crossing is very different when stepping up */
-		if (dparent == exp->ex_dentry) {
-			if (!EX_CROSSMNT(exp))
-				dentry = dget(dparent); /* .. == . just like at / */
-			else
-			{
-				struct svc_export *exp2 = NULL;
-				struct dentry *dp;
-				struct vfsmount *mnt = mntget(exp->ex_mnt);
-				dentry = dget(dparent);
-				while(follow_up(&mnt, &dentry))
-					;
-				dp = dget(dentry->d_parent);
-				dput(dentry);
-				dentry = dp;
-				for ( ; exp2 == NULL && dp->d_parent != dp;
-				     dp=dp->d_parent)
-					exp2 = exp_get(exp->ex_client, dp->d_inode->i_dev, dp->d_inode->i_ino);
-				if (exp2==NULL) {
-					dput(dentry);
+	if (isdotent(name, len)) {
+		if (len==1)
+			dentry = dget(dparent);
+		else  { /* must be ".." */
+			/* checking mountpoint crossing is very different when stepping up */
+			if (dparent == exp->ex_dentry) {
+				if (!EX_CROSSMNT(exp))
+					dentry = dget(dparent); /* .. == . just like at / */
+				else
+				{
+					struct svc_export *exp2 = NULL;
+					struct dentry *dp;
+					struct vfsmount *mnt = mntget(exp->ex_mnt);
 					dentry = dget(dparent);
-				} else {
-					exp = exp2;
+					while(follow_up(&mnt, &dentry))
+						;
+					dp = dget(dentry->d_parent);
+					dput(dentry);
+					dentry = dp;
+					for ( ; exp2 == NULL && dp->d_parent != dp;
+					      dp=dp->d_parent)
+						exp2 = exp_get(exp->ex_client, dp->d_inode->i_dev, dp->d_inode->i_ino);
+					if (exp2==NULL) {
+						dput(dentry);
+						dentry = dget(dparent);
+					} else {
+						exp = exp2;
+					}
+					mntput(mnt);
 				}
-				mntput(mnt);
-			}
-		} else
-			dentry = dget(dparent->d_parent);
+			} else
+				dentry = dget(dparent->d_parent);
+		}
 	} else {
 		fh_lock(fhp);
-		dentry = lookup_one(name, dparent);
+		dentry = lookup_one_len(name, dparent, len);
 		err = PTR_ERR(dentry);
 		if (IS_ERR(dentry))
 			goto out_nfserr;
@@ -843,7 +845,7 @@
 	if (!resfhp->fh_dentry) {
 		/* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
 		fh_lock(fhp);
-		dchild = lookup_one(fname, dentry);
+		dchild = lookup_one_len(fname, dentry, flen);
 		err = PTR_ERR(dchild);
 		if (IS_ERR(dchild))
 			goto out_nfserr;
@@ -968,7 +970,7 @@
 	/*
 	 * Compose the response file handle.
 	 */
-	dchild = lookup_one(fname, dentry);
+	dchild = lookup_one_len(fname, dentry, flen);
 	err = PTR_ERR(dchild);
 	if (IS_ERR(dchild))
 		goto out_nfserr;
@@ -1132,7 +1134,7 @@
 		goto out;
 	fh_lock(fhp);
 	dentry = fhp->fh_dentry;
-	dnew = lookup_one(fname, dentry);
+	dnew = lookup_one_len(fname, dentry, flen);
 	err = PTR_ERR(dnew);
 	if (IS_ERR(dnew))
 		goto out_nfserr;
@@ -1197,7 +1199,7 @@
 	ddir = ffhp->fh_dentry;
 	dirp = ddir->d_inode;
 
-	dnew = lookup_one(fname, ddir);
+	dnew = lookup_one_len(fname, ddir, len);
 	err = PTR_ERR(dnew);
 	if (IS_ERR(dnew))
 		goto out_nfserr;
@@ -1268,7 +1270,7 @@
 	fill_pre_wcc(ffhp);
 	fill_pre_wcc(tfhp);
 
-	odentry = lookup_one(fname, fdentry);
+	odentry = lookup_one_len(fname, fdentry, flen);
 	err = PTR_ERR(odentry);
 	if (IS_ERR(odentry))
 		goto out_nfserr;
@@ -1277,7 +1279,7 @@
 	if (!odentry->d_inode)
 		goto out_dput_old;
 
-	ndentry = lookup_one(tname, tdentry);
+	ndentry = lookup_one_len(tname, tdentry, tlen);
 	err = PTR_ERR(ndentry);
 	if (IS_ERR(ndentry))
 		goto out_dput_old;
@@ -1339,7 +1341,7 @@
 	dentry = fhp->fh_dentry;
 	dirp = dentry->d_inode;
 
-	rdentry = lookup_one(fname, dentry);
+	rdentry = lookup_one_len(fname, dentry, flen);
 	err = PTR_ERR(rdentry);
 	if (IS_ERR(rdentry))
 		goto out_nfserr;
diff -u --recursive --new-file v2.4.4/linux/fs/nls/Config.in linux/fs/nls/Config.in
--- v2.4.4/linux/fs/nls/Config.in	Fri Apr  6 10:51:19 2001
+++ linux/fs/nls/Config.in	Sat May 19 17:47:55 2001
@@ -56,7 +56,7 @@
   tristate 'NLS ISO 8859-14 (Latin 8; Celtic)'      CONFIG_NLS_ISO8859_14
   tristate 'NLS ISO 8859-15 (Latin 9; Western European Languages with Euro)' CONFIG_NLS_ISO8859_15
   tristate 'NLS KOI8-R (Russian)'                   CONFIG_NLS_KOI8_R
-  tristate 'NLS KOI8-U (Ukrainian)'                 CONFIG_NLS_KOI8_U
+  tristate 'NLS KOI8-U/RU (Ukrainian, Belarussian)' CONFIG_NLS_KOI8_U
   tristate 'NLS UTF8'                               CONFIG_NLS_UTF8
   endmenu
 fi
diff -u --recursive --new-file v2.4.4/linux/fs/nls/Makefile linux/fs/nls/Makefile
--- v2.4.4/linux/fs/nls/Makefile	Fri Apr  6 10:51:19 2001
+++ linux/fs/nls/Makefile	Sat May 19 17:47:55 2001
@@ -49,7 +49,7 @@
 obj-$(CONFIG_NLS_ISO8859_14)	+= nls_iso8859-14.o
 obj-$(CONFIG_NLS_ISO8859_15)	+= nls_iso8859-15.o
 obj-$(CONFIG_NLS_KOI8_R)	+= nls_koi8-r.o
-obj-$(CONFIG_NLS_KOI8_U)	+= nls_koi8-u.o
+obj-$(CONFIG_NLS_KOI8_U)	+= nls_koi8-u.o nls_koi8-ru.o
 obj-$(CONFIG_NLS_ABC)		+= nls_abc.o
 obj-$(CONFIG_NLS_UTF8)		+= nls_utf8.o
 
diff -u --recursive --new-file v2.4.4/linux/fs/nls/nls_cp1255.c linux/fs/nls/nls_cp1255.c
--- v2.4.4/linux/fs/nls/nls_cp1255.c	Fri Apr  6 10:51:19 2001
+++ linux/fs/nls/nls_cp1255.c	Sat May 19 17:47:55 2001
@@ -254,7 +254,7 @@
 };
 
 static unsigned char *page_uni2charset[256] = {
-	page00, NULL,   NULL,   NULL,   NULL,   page05, NULL,   NULL,   
+	page00, page01, page02, NULL,   NULL,   page05, NULL,   NULL,   
 	NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 	NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 	NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
diff -u --recursive --new-file v2.4.4/linux/fs/nls/nls_iso8859-13.c linux/fs/nls/nls_iso8859-13.c
--- v2.4.4/linux/fs/nls/nls_iso8859-13.c	Fri Apr  6 10:51:19 2001
+++ linux/fs/nls/nls_iso8859-13.c	Sat May 19 17:47:55 2001
@@ -149,35 +149,6 @@
 	0x00, 0xca, 0xea, 0xdd, 0xfd, 0xde, 0xfe, 0x00, /* 0x78-0x7f */
 };
 
-static unsigned char page02[256] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
-	0x00, 0xff, 0x00, 0x00, 0xb4, 0xa1, 0xa5, 0x00, /* 0x18-0x1f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
-	
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
-};
-
 static unsigned char page20[256] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
diff -u --recursive --new-file v2.4.4/linux/fs/nls/nls_koi8-ru.c linux/fs/nls/nls_koi8-ru.c
--- v2.4.4/linux/fs/nls/nls_koi8-ru.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/nls/nls_koi8-ru.c	Sat May 19 17:47:55 2001
@@ -0,0 +1,99 @@
+/*
+ * linux/fs/nls_koi8-ru.c
+ *
+ * Charset koi8-ru translation based on charset koi8-u.
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include <linux/errno.h>
+
+static struct nls_table *p_nls;
+
+static int uni2char(const wchar_t uni,
+		    unsigned char *out, int boundlen)
+{
+	if (boundlen <= 0)
+		return -ENAMETOOLONG;
+
+	if ((uni & 0xffaf) == 0x040e || (uni & 0xffce) == 0x254c) {
+		/* koi8-ru and koi8-u differ only on two characters */
+		if (uni == 0x040e)
+			return 0xbe;
+		else if (uni == 0x045e)
+			return 0xae;
+		else if (uni == 0x255d || uni == 0x256c)
+			return 0;
+		else
+			return p_nls->uni2char(uni, out, boundlen);
+	}
+	else
+		/* fast path */
+		return p_nls->uni2char(uni, out, boundlen);
+}
+
+static int char2uni(const unsigned char *rawstring, int boundlen,
+		    wchar_t *uni)
+{
+	int n;
+
+	if ((*rawstring & 0xef) != 0xae) {
+		/* koi8-ru and koi8-u differ only on two characters */
+		*uni = (*rawstring & 0x10) ? 0x040e : 0x045e;
+		return 1;
+	}
+
+	n = p_nls->char2uni(rawstring, boundlen, uni);
+	return n;
+}
+
+static struct nls_table table = {
+	"koi8-ru",
+	uni2char,
+	char2uni,
+	NULL,
+	NULL,
+	THIS_MODULE,
+};
+
+static int __init init_nls_koi8_ru(void)
+{
+	p_nls = load_nls("koi8-u");
+
+	if (p_nls) {
+		table.charset2upper = p_nls->charset2upper;
+		table.charset2lower = p_nls->charset2lower;
+		return register_nls(&table);
+	}
+
+	return -EINVAL;
+}
+
+static void __exit exit_nls_koi8_ru(void)
+{
+	unregister_nls(&table);
+	unload_nls(p_nls);
+}
+
+module_init(init_nls_koi8_ru)
+module_exit(exit_nls_koi8_ru)
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff -u --recursive --new-file v2.4.4/linux/fs/nls/nls_koi8-u.c linux/fs/nls/nls_koi8-u.c
--- v2.4.4/linux/fs/nls/nls_koi8-u.c	Fri Apr  6 10:51:19 2001
+++ linux/fs/nls/nls_koi8-u.c	Sat May 19 17:47:55 2001
@@ -141,14 +141,15 @@
 	0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0x40-0x47 */
 	0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, /* 0x48-0x4f */
 	0x00, 0xa3, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
 
-	0xbd, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0xbd, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
 };
 
 static unsigned char page22[256] = {
diff -u --recursive --new-file v2.4.4/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.4.4/linux/fs/partitions/check.c	Fri Feb 16 16:02:37 2001
+++ linux/fs/partitions/check.c	Wed May 16 14:01:32 2001
@@ -33,10 +33,7 @@
 #include "ibm.h"
 #include "ultrix.h"
 
-extern void device_init(void);
 extern int *blk_size[];
-extern void rd_load(void);
-extern void initrd_load(void);
 
 struct gendisk *gendisk_head;
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
@@ -438,19 +435,3 @@
 		blk_size[dev->major] = dev->sizes;
 	}
 }
-
-int __init partition_setup(void)
-{
-	device_init();
-
-#ifdef CONFIG_BLK_DEV_RAM
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start && mount_initrd) initrd_load();
-	else
-#endif
-	rd_load();
-#endif
-	return 0;
-}
-
-__initcall(partition_setup);
diff -u --recursive --new-file v2.4.4/linux/fs/partitions/ibm.c linux/fs/partitions/ibm.c
--- v2.4.4/linux/fs/partitions/ibm.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/partitions/ibm.c	Sun May 20 12:11:39 2001
@@ -10,7 +10,6 @@
  * 02/13/00 VTOC partition support added
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
diff -u --recursive --new-file v2.4.4/linux/fs/proc/Makefile linux/fs/proc/Makefile
--- v2.4.4/linux/fs/proc/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/fs/proc/Makefile	Tue May  8 16:41:32 2001
@@ -9,10 +9,10 @@
 
 O_TARGET := proc.o
 
-export-objs := procfs_syms.o
+export-objs := root.o
 
 obj-y    := inode.o root.o base.o generic.o array.o \
-		kmsg.o proc_tty.o proc_misc.o kcore.o procfs_syms.o
+		kmsg.o proc_tty.o proc_misc.o kcore.o
 
 ifeq ($(CONFIG_PROC_DEVICETREE),y)
 obj-y += proc_devtree.o
diff -u --recursive --new-file v2.4.4/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.4.4/linux/fs/proc/array.c	Fri Apr  6 10:51:19 2001
+++ linux/fs/proc/array.c	Fri May  4 14:44:06 2001
@@ -157,7 +157,7 @@
 		"Uid:\t%d\t%d\t%d\t%d\n"
 		"Gid:\t%d\t%d\t%d\t%d\n",
 		get_task_state(p),
-		p->pid, p->p_opptr->pid, p->p_pptr->pid != p->p_opptr->pid ? p->p_pptr->pid : 0,
+		p->pid, p->pid ? p->p_opptr->pid : 0, 0,
 		p->uid, p->euid, p->suid, p->fsuid,
 		p->gid, p->egid, p->sgid, p->fsgid);
 	read_unlock(&tasklist_lock);	
@@ -339,7 +339,7 @@
 	nice = task->nice;
 
 	read_lock(&tasklist_lock);
-	ppid = task->p_opptr->pid;
+	ppid = task->pid ? task->p_opptr->pid : 0;
 	read_unlock(&tasklist_lock);
 	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
diff -u --recursive --new-file v2.4.4/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.4.4/linux/fs/proc/base.c	Mon Mar 19 12:34:55 2001
+++ linux/fs/proc/base.c	Fri May  4 14:44:06 2001
@@ -586,7 +586,7 @@
 	struct pid_entry *p;
 
 	pid = inode->u.proc_i.task->pid;
-	if (!inode->u.proc_i.task->p_pptr)
+	if (!pid)
 		return -ENOENT;
 	i = filp->f_pos;
 	switch (i) {
@@ -641,7 +641,7 @@
 	 */
 	inode->u.proc_i.task = task;
 	get_task_struct(task);
-	if (!task->p_pptr)
+	if (!task->pid)
 		goto out_unlock;
 
 	inode->i_uid = 0;
@@ -673,7 +673,7 @@
  */
 static int pid_base_revalidate(struct dentry * dentry, int flags)
 {
-	if (dentry->d_inode->u.proc_i.task->p_pptr)
+	if (dentry->d_inode->u.proc_i.task->pid)
 		return 1;
 	d_drop(dentry);
 	return 0;
diff -u --recursive --new-file v2.4.4/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.4.4/linux/fs/proc/generic.c	Mon Dec 11 13:45:42 2000
+++ linux/fs/proc/generic.c	Thu May 24 14:54:54 2001
@@ -428,6 +428,7 @@
 	ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
 	if (!ent->data) {
 		kfree(ent);
+		ent = NULL;
 		goto out;
 	}
 	strcpy((char*)ent->data,dest);
diff -u --recursive --new-file v2.4.4/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.4.4/linux/fs/proc/procfs_syms.c	Mon Sep 11 08:41:07 2000
+++ linux/fs/proc/procfs_syms.c	Wed Dec 31 16:00:00 1969
@@ -1,46 +0,0 @@
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-
-extern struct proc_dir_entry *proc_sys_root;
-
-#ifdef CONFIG_SYSCTL
-EXPORT_SYMBOL(proc_sys_root);
-#endif
-EXPORT_SYMBOL(proc_symlink);
-EXPORT_SYMBOL(proc_mknod);
-EXPORT_SYMBOL(proc_mkdir);
-EXPORT_SYMBOL(create_proc_entry);
-EXPORT_SYMBOL(remove_proc_entry);
-EXPORT_SYMBOL(proc_root);
-EXPORT_SYMBOL(proc_root_fs);
-EXPORT_SYMBOL(proc_net);
-EXPORT_SYMBOL(proc_bus);
-EXPORT_SYMBOL(proc_root_driver);
-
-static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE);
-
-static int __init init_proc_fs(void)
-{
-	int err = register_filesystem(&proc_fs_type);
-	if (!err) {
-		proc_mnt = kern_mount(&proc_fs_type);
-		err = PTR_ERR(proc_mnt);
-		if (IS_ERR(proc_mnt))
-			unregister_filesystem(&proc_fs_type);
-		else
-			err = 0;
-	}
-	return err;
-}
-
-static void __exit exit_proc_fs(void)
-{
-	unregister_filesystem(&proc_fs_type);
-	kern_umount(proc_mnt);
-}
-
-module_init(init_proc_fs)
-module_exit(exit_proc_fs)
diff -u --recursive --new-file v2.4.4/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.4.4/linux/fs/proc/root.c	Thu Nov 23 09:07:36 2000
+++ linux/fs/proc/root.c	Wed May 16 18:05:34 2001
@@ -14,6 +14,7 @@
 #include <linux/stat.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <asm/bitops.h>
 
 struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
@@ -22,8 +23,19 @@
 struct proc_dir_entry *proc_sys_root;
 #endif
 
+static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE);
+
 void __init proc_root_init(void)
 {
+	int err = register_filesystem(&proc_fs_type);
+	if (err)
+		return;
+	proc_mnt = kern_mount(&proc_fs_type);
+	err = PTR_ERR(proc_mnt);
+	if (IS_ERR(proc_mnt)) {
+		unregister_filesystem(&proc_fs_type);
+		return;
+	}
 	proc_misc_init();
 	proc_net = proc_mkdir("net", 0);
 #ifdef CONFIG_SYSVIPC
@@ -42,6 +54,9 @@
 #ifdef CONFIG_PROC_DEVICETREE
 	proc_device_tree_init();
 #endif
+#ifdef CONFIG_PPC_RTAS
+	proc_rtas_init();
+#endif
 	proc_bus = proc_mkdir("bus", 0);
 }
 
@@ -106,3 +121,17 @@
 	proc_fops:	&proc_root_operations,
 	parent:		&proc_root,
 };
+
+#ifdef CONFIG_SYSCTL
+EXPORT_SYMBOL(proc_sys_root);
+#endif
+EXPORT_SYMBOL(proc_symlink);
+EXPORT_SYMBOL(proc_mknod);
+EXPORT_SYMBOL(proc_mkdir);
+EXPORT_SYMBOL(create_proc_entry);
+EXPORT_SYMBOL(remove_proc_entry);
+EXPORT_SYMBOL(proc_root);
+EXPORT_SYMBOL(proc_root_fs);
+EXPORT_SYMBOL(proc_net);
+EXPORT_SYMBOL(proc_bus);
+EXPORT_SYMBOL(proc_root_driver);
diff -u --recursive --new-file v2.4.4/linux/fs/ramfs/inode.c linux/fs/ramfs/inode.c
--- v2.4.4/linux/fs/ramfs/inode.c	Fri Jan  5 23:06:19 2001
+++ linux/fs/ramfs/inode.c	Tue May 22 09:31:25 2001
@@ -118,7 +118,7 @@
 		inode->i_gid = current->fsgid;
 		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks = 0;
-		inode->i_rdev = to_kdev_t(dev);
+		inode->i_rdev = NODEV;
 		inode->i_mapping->a_ops = &ramfs_aops;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		switch (mode & S_IFMT) {
diff -u --recursive --new-file v2.4.4/linux/fs/reiserfs/prints.c linux/fs/reiserfs/prints.c
--- v2.4.4/linux/fs/reiserfs/prints.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/reiserfs/prints.c	Wed May 16 10:31:27 2001
@@ -349,8 +349,6 @@
 #endif
 
   /* this is to prevent panic from syncing this filesystem */
-  if (sb && sb->s_lock)
-    sb->s_lock=0;
   if (sb)
     sb->s_flags |= MS_RDONLY;
 
diff -u --recursive --new-file v2.4.4/linux/fs/select.c linux/fs/select.c
--- v2.4.4/linux/fs/select.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/select.c	Wed May 16 10:31:27 2001
@@ -414,8 +414,11 @@
 	int nchunks, nleft;
 
 	/* Do a sanity check on nfds ... */
-	if (nfds > current->files->max_fds)
+	if (nfds > NR_OPEN)
 		return -EINVAL;
+
+	if (nfds > current->files->max_fds)
+		nfds = current->files->max_fds;
 
 	if (timeout) {
 		/* Careful about overflow in the intermediate values */
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog
--- v2.4.4/linux/fs/smbfs/ChangeLog	Tue Mar  6 19:14:59 2001
+++ linux/fs/smbfs/ChangeLog	Tue May 15 13:40:55 2001
@@ -1,5 +1,30 @@
 ChangeLog for smbfs.
 
+2001-05-08 Urban Widmark <urban@teststation.com>
+
+	* inode.c: Fix for changes on the server side not being detected
+	  properly. Must always drop cached pages when updating an inode with
+	  new size.
+
+2001-05-05 Urban Widmark <urban@teststation.com>
+
+	* file.c, proc.c: Drop SMB_F_LOCALWRITE to detect changes made on
+	  both server and client, using flush with to force win9x to remember
+	  the right filesize.
+
+2001-04-25 René Scharfe <l.s.r@web.de>
+
+	* inode.c: Don't clear s_flags and allow ro mounts
+
+2001-04-21 Urban Widmark <urban@teststation.com>
+
+	* dir.c, proc.c: replace tests on conn_pid with tests on state to
+	  fix smbmount reconnect on smb_retry timeout and up the timeout to 30s.
+	* proc.c: smb_newconn must have the server locked while updating it.
+	* inode.c, proc.c: need flush after truncate on some servers (win9x)
+	* file.c: add call to send SMBflush on fsync
+	  (as suggested by Jochen Dolze <dolze@epcnet.de>)
+
 2001-03-06 Urban Widmark <urban@teststation.com>
 
 	* cache.c: d_add on hashed dentries corrupts d_hash list and
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.4.4/linux/fs/smbfs/dir.c	Fri Feb 16 16:03:24 2001
+++ linux/fs/smbfs/dir.c	Tue May 15 13:40:55 2001
@@ -210,10 +210,6 @@
 	return result;
 }
 
-/*
- * Note: in order to allow the smbmount process to open the
- * mount point, we don't revalidate if conn_pid is NULL.
- */
 static int
 smb_dir_open(struct inode *dir, struct file *file)
 {
@@ -230,14 +226,18 @@
 	 */
 	lock_kernel();
 	server = server_from_dentry(dentry);
-	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
-	{
+	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
 		unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
 		if (age > 2*HZ)
 			smb_invalid_dir_cache(dir);
 	}
 
-	if (server->conn_pid)
+	/*
+	 * Note: in order to allow the smbmount process to open the
+	 * mount point, we only revalidate if the connection is valid or
+	 * if the process is trying to access something other than the root.
+	 */
+	if (server->state == CONN_VALID || !IS_ROOT(dentry))
 		error = smb_revalidate_inode(dentry);
 	unlock_kernel();
 	return error;
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.4.4/linux/fs/smbfs/file.c	Fri Feb 16 16:03:24 2001
+++ linux/fs/smbfs/file.c	Tue May 15 13:40:55 2001
@@ -28,8 +28,23 @@
 static int
 smb_fsync(struct file *file, struct dentry * dentry, int datasync)
 {
+	struct smb_sb_info *server = server_from_dentry(dentry);
+	int result;
+
 	VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
-	return 0;
+
+	/*
+	 * The VFS will writepage() all dirty pages for us, but we
+	 * should send a SMBflush to the server, letting it know that
+	 * we want things synchronized with actual storage.
+	 *
+	 * Note: this function requires all pages to have been written already
+	 *       (should be ok with writepage_sync)
+	 */
+	smb_lock_server(server);
+	result = smb_proc_flush(server, dentry->d_inode->u.smbfs_i.fileid);
+	smb_unlock_server(server);
+	return result;
 }
 
 /*
@@ -138,7 +153,6 @@
 		inode->i_mtime = inode->i_atime = CURRENT_TIME;
 		if (offset > inode->i_size)
 			inode->i_size = offset;
-		inode->u.smbfs_i.flags |= SMB_F_LOCALWRITE;
 	} while (count);
 
 	kunmap(page);
@@ -207,8 +221,7 @@
 		(unsigned long) count, (unsigned long) *ppos);
 
 	status = smb_revalidate_inode(dentry);
-	if (status)
-	{
+	if (status) {
 		PARANOIA("%s/%s validation failed, error=%Zd\n",
 			 DENTRY_PATH(dentry), status);
 		goto out;
@@ -233,8 +246,7 @@
 		DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
 
 	status = smb_revalidate_inode(dentry);
-	if (status)
-	{
+	if (status) {
 		PARANOIA("%s/%s validation failed, error=%d\n",
 			 DENTRY_PATH(dentry), status);
 		goto out;
@@ -294,8 +306,7 @@
 		(unsigned long) count, (unsigned long) *ppos);
 
 	result = smb_revalidate_inode(dentry);
-	if (result)
-	{
+	if (result) {
 		PARANOIA("%s/%s validation failed, error=%Zd\n",
 			 DENTRY_PATH(dentry), result);
 		goto out;
@@ -305,8 +316,7 @@
 	if (result)
 		goto out;
 
-	if (count > 0)
-	{
+	if (count > 0) {
 		result = generic_file_write(file, buf, count, ppos);
 		VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
 			(long) file->f_pos, (long) dentry->d_inode->i_size,
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.4.4/linux/fs/smbfs/inode.c	Tue Apr 17 23:16:39 2001
+++ linux/fs/smbfs/inode.c	Tue May 15 13:40:55 2001
@@ -109,9 +109,20 @@
 		fattr->attr |= aRONLY;
 }
 
+/*
+ * Update the inode, possibly causing it to invalidate its pages if mtime/size
+ * is different from last time.
+ */
 void
 smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
 {
+	/*
+	 * A size change should have a different mtime, or same mtime
+	 * but different size.
+	 */
+	time_t last_time = inode->i_mtime;
+	loff_t last_sz = inode->i_size;
+
 	inode->i_mode	= fattr->f_mode;
 	inode->i_nlink	= fattr->f_nlink;
 	inode->i_uid	= fattr->f_uid;
@@ -120,21 +131,24 @@
 	inode->i_ctime	= fattr->f_ctime;
 	inode->i_blksize= fattr->f_blksize;
 	inode->i_blocks = fattr->f_blocks;
-	/*
-	 * Don't change the size and mtime/atime fields
-	 * if we're writing to the file.
-	 */
-	if (!(inode->u.smbfs_i.flags & SMB_F_LOCALWRITE)) {
-		inode->i_size  = fattr->f_size;
-		inode->i_mtime = fattr->f_mtime;
-		inode->i_atime = fattr->f_atime;
-	}
-
+	inode->i_size	= fattr->f_size;
+	inode->i_mtime	= fattr->f_mtime;
+	inode->i_atime	= fattr->f_atime;
 	inode->u.smbfs_i.attr = fattr->attr;
 	/*
 	 * Update the "last time refreshed" field for revalidation.
 	 */
 	inode->u.smbfs_i.oldmtime = jiffies;
+
+	if (inode->i_mtime != last_time || inode->i_size != last_sz) {
+		VERBOSE("%s/%s changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
+			DENTRY_PATH(dentry),
+			(long) last_time, (long) inode->i_mtime,
+			(long) last_sz, (long) inode->i_size);
+
+		if (!S_ISDIR(inode->i_mode))
+			invalidate_inode_pages(inode);
+	}
 }
 
 /*
@@ -209,8 +223,6 @@
 {
 	struct smb_sb_info *s = server_from_dentry(dentry);
 	struct inode *inode = dentry->d_inode;
-	time_t last_time;
-	loff_t last_sz;
 	int error = 0;
 
 	DEBUG1("smb_revalidate_inode\n");
@@ -225,22 +237,7 @@
 		goto out;
 	}
 
-	/*
-	 * Save the last modified time, then refresh the inode.
-	 * (Note: a size change should have a different mtime,
-	 *  or same mtime but different size.)
-	 */
-	last_time = inode->i_mtime;
-	last_sz   = inode->i_size;
 	error = smb_refresh_inode(dentry);
-	if (error || inode->i_mtime != last_time || inode->i_size != last_sz) {
-		VERBOSE("%s/%s changed, old=%ld, new=%ld\n",
-			DENTRY_PATH(dentry),
-			(long) last_time, (long) inode->i_mtime);
-
-		if (!S_ISDIR(inode->i_mode))
-			invalidate_inode_pages(inode);
-	}
 out:
 	unlock_kernel();
 	return error;
@@ -355,8 +352,8 @@
 	if (server->conn_pid)
 	       kill_proc(server->conn_pid, SIGTERM, 1);
 
-	kfree(server->mnt);
-	kfree(sb->u.smbfs_sb.temp_buf);
+	smb_kfree(server->mnt);
+	smb_kfree(sb->u.smbfs_sb.temp_buf);
 	if (server->packet)
 		smb_vfree(server->packet);
 
@@ -390,7 +387,6 @@
 	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = SMB_SUPER_MAGIC;
-	sb->s_flags = 0;
 	sb->s_op = &smb_sops;
 
 	sb->u.smbfs_sb.mnt = NULL;
@@ -400,13 +396,13 @@
 	sb->u.smbfs_sb.conn_pid = 0;
 	sb->u.smbfs_sb.state = CONN_INVALID; /* no connection yet */
 	sb->u.smbfs_sb.generation = 0;
-	sb->u.smbfs_sb.packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);	
+	sb->u.smbfs_sb.packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
 	sb->u.smbfs_sb.packet = smb_vmalloc(sb->u.smbfs_sb.packet_size);
 	if (!sb->u.smbfs_sb.packet)
 		goto out_no_mem;
 
 	/* Allocate the global temp buffer */
-	sb->u.smbfs_sb.temp_buf = kmalloc(2*SMB_MAXPATHLEN + 20, GFP_KERNEL);
+	sb->u.smbfs_sb.temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
 	if (!sb->u.smbfs_sb.temp_buf)
 		goto out_no_temp;
 
@@ -417,7 +413,7 @@
 
 	/* Allocate the mount data structure */
 	/* FIXME: merge this with the other malloc and get a whole page? */
-	mnt = kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
+	mnt = smb_kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
 	if (!mnt)
 		goto out_no_mount;
 	sb->u.smbfs_sb.mnt = mnt;
@@ -482,9 +478,9 @@
 out_no_root:
 	iput(root_inode);
 out_bad_option:
-	kfree(sb->u.smbfs_sb.mnt);
+	smb_kfree(sb->u.smbfs_sb.mnt);
 out_no_mount:
-	kfree(sb->u.smbfs_sb.temp_buf);
+	smb_kfree(sb->u.smbfs_sb.temp_buf);
 out_no_temp:
 	smb_vfree(sb->u.smbfs_sb.packet);
 out_no_mem:
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- v2.4.4/linux/fs/smbfs/ioctl.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/smbfs/ioctl.c	Tue May 15 13:40:55 2001
@@ -23,7 +23,7 @@
 smb_ioctl(struct inode *inode, struct file *filp,
 	  unsigned int cmd, unsigned long arg)
 {
-	struct smb_sb_info *server = SMB_SERVER(inode);
+	struct smb_sb_info *server = server_from_inode(inode);
 	struct smb_conn_opt opt;
 	int result = -EINVAL;
 
@@ -37,7 +37,7 @@
 		break;
 
 	case SMB_IOC_NEWCONN:
-		/* require an argument == the mount data, else it is EINVAL */
+		/* require an argument == smb_conn_opt, else it is EINVAL */
 		if (!arg)
 			break;
 
@@ -45,7 +45,8 @@
 		if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
 			result = smb_newconn(server, &opt);
 		break;
-	default:;
+	default:
+		break;
 	}
 
 	return result;
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v2.4.4/linux/fs/smbfs/proc.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/smbfs/proc.c	Tue May 15 13:40:55 2001
@@ -54,18 +54,6 @@
 		    struct smb_fattr *fattr);
 
 
-static inline void
-smb_lock_server(struct smb_sb_info *server)
-{
-	down(&(server->sem));
-}
-
-static inline void
-smb_unlock_server(struct smb_sb_info *server)
-{
-	up(&(server->sem));
-}
-
 
 static void
 str_upper(char *name, int len)
@@ -661,7 +649,7 @@
 	pid_t pid = server->conn_pid;
 	int error, result = 0;
 
-	if (server->state != CONN_INVALID)
+	if (server->state == CONN_VALID || server->state == CONN_RETRYING)
 		goto out;
 
 	smb_close_socket(server);
@@ -673,17 +661,18 @@
 	}
 
 	/*
-	 * Clear the pid to enable the ioctl.
+	 * Change state so that only one retry per server will be started.
 	 */
-	server->conn_pid = 0;
+	server->state = CONN_RETRYING;
 
 	/*
 	 * Note: use the "priv" flag, as a user process may need to reconnect.
 	 */
 	error = kill_proc(pid, SIGUSR1, 1);
 	if (error) {
+		/* FIXME: this is fatal */
 		printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
-		goto out_restore;
+		goto out;
 	}
 	VERBOSE("signalled pid %d, waiting for new connection\n", pid);
 
@@ -691,7 +680,9 @@
 	 * Wait for the new connection.
 	 */
 #ifdef SMB_RETRY_INTR
-	interruptible_sleep_on_timeout(&server->wait,  5*HZ);
+	smb_unlock_server(server);
+	interruptible_sleep_on_timeout(&server->wait,  30*HZ);
+	smb_lock_server(server);
 	if (signal_pending(current))
 		printk(KERN_INFO "smb_retry: caught signal\n");
 #else
@@ -702,8 +693,13 @@
 	 *
 	 * smbmount should be able to reconnect later, but it can't because
 	 * it will get an -EIO on attempts to open the mountpoint!
+	 *
+	 * FIXME: go back to the interruptable version now that smbmount
+	 * can avoid -EIO on the mountpoint when reconnecting?
 	 */
-	sleep_on_timeout(&server->wait, 5*HZ);
+	smb_unlock_server(server);
+	sleep_on_timeout(&server->wait, 30*HZ);
+	smb_lock_server(server);
 #endif
 
 	/*
@@ -715,15 +711,11 @@
 		PARANOIA("successful, new pid=%d, generation=%d\n",
 			 server->conn_pid, server->generation);
 		result = 1;
+	} else if (server->state == CONN_RETRYING) {
+		/* allow further attempts later */
+		server->state = CONN_RETRIED;
 	}
 
-	/*
-	 * Restore the original pid if we didn't get a new one.
-	 */
-out_restore:
-	if (!server->conn_pid)
-		server->conn_pid = pid;
-
 out:
 	return result;
 }
@@ -742,19 +734,16 @@
 	s->err = 0;
 
 	/* Make sure we have a connection */
-	if (s->state != CONN_VALID)
-	{
+	if (s->state != CONN_VALID) {
 		if (!smb_retry(s))
 			goto out;
 	}
 
-	if (smb_request(s) < 0)
-	{
+	if (smb_request(s) < 0) {
 		DEBUG1("smb_request failed\n");
 		goto out;
 	}
-	if (smb_valid_packet(s->packet) != 0)
-	{
+	if (smb_valid_packet(s->packet) != 0) {
 		PARANOIA("invalid packet!\n");
 		goto out;
 	}
@@ -764,8 +753,7 @@
 	 * is squashing some error codes, but I don't think this is
 	 * correct: after a server error the packet won't be valid.
 	 */
-	if (s->rcls != 0)
-	{
+	if (s->rcls != 0) {
 		result = -smb_errno(s);
 		if (!result)
 			printk(KERN_DEBUG "smb_request_ok: rcls=%d, err=%d mapped to 0\n",
@@ -785,10 +773,6 @@
 /*
  * This implements the NEWCONN ioctl. It installs the server pid,
  * sets server->state to CONN_VALID, and wakes up the waiting process.
- *
- * Note that this must be called with the server locked, except for
- * the first call made after mounting the volume. The server pid
- * will be set to zero to indicate that smbfs is awaiting a connection.
  */
 int
 smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
@@ -798,11 +782,13 @@
 
 	VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
 
+	smb_lock_server(server);
+
 	/*
-	 * Make sure we don't already have a pid ...
+	 * Make sure we don't already have a valid connection ...
 	 */
 	error = -EINVAL;
-	if (server->conn_pid)
+	if (server->state == CONN_VALID)
 		goto out;
 
 	error = -EACCES;
@@ -836,9 +822,7 @@
 	    (server->opt.max_xmit < 0x1000) &&
 	    !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
 		server->mnt->flags |= SMB_MOUNT_WIN95;
-#ifdef SMBFS_DEBUG_VERBOSE
-		printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n");
-#endif
+		VERBOSE("smb_newconn: detected WIN95 server\n");
 	}
 
 	VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
@@ -851,6 +835,8 @@
 		int len = smb_round_length(server->opt.max_xmit);
 		char *buf = smb_vmalloc(len);
 		if (buf) {
+			if (server->packet)
+				smb_vfree(server->packet);
 			server->packet = buf;
 			server->packet_size = len;
 		} else {
@@ -863,6 +849,8 @@
 	}
 
 out:
+	smb_unlock_server(server);
+
 #ifdef SMB_RETRY_INTR
 	wake_up_interruptible(&server->wait);
 #else
@@ -1016,7 +1004,7 @@
 	}
 
 	if (!smb_is_open(inode)) {
-		struct smb_sb_info *server = SMB_SERVER(inode);
+		struct smb_sb_info *server = server_from_inode(inode);
 		smb_lock_server(server);
 		result = 0;
 		if (!smb_is_open(inode))
@@ -1102,7 +1090,6 @@
 
 		result = smb_proc_close(server, ino->u.smbfs_i.fileid,
 						ino->i_mtime);
-		ino->u.smbfs_i.flags &= ~SMB_F_LOCALWRITE;
 		/*
 		 * Force a revalidation after closing ... some servers
 		 * don't post the size until the file has been closed.
@@ -1119,9 +1106,8 @@
 {
 	int result = 0;
 
-	if (smb_is_open(ino))
-	{
-		struct smb_sb_info *server = SMB_SERVER(ino);
+	if (smb_is_open(ino)) {
+		struct smb_sb_info *server = server_from_inode(ino);
 		smb_lock_server(server);
 		result = smb_proc_close_inode(server, ino);
 		smb_unlock_server(server);
@@ -1203,14 +1189,15 @@
 	struct smb_sb_info *server = server_from_inode(inode);
 	int result;
 	__u8 *p;
-	
+	__u16 fileid = inode->u.smbfs_i.fileid;
+
 	VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",
 		inode->i_ino, inode->u.smbfs_i.fileid, count, offset,
 		server->packet_size);
 
 	smb_lock_server(server);
 	p = smb_setup_header(server, SMBwrite, 5, count + 3);
-	WSET(server->packet, smb_vwv0, inode->u.smbfs_i.fileid);
+	WSET(server->packet, smb_vwv0, fileid);
 	WSET(server->packet, smb_vwv1, count);
 	DSET(server->packet, smb_vwv2, offset);
 	WSET(server->packet, smb_vwv4, 0);
@@ -1223,6 +1210,11 @@
 	if (result >= 0)
 		result = WVAL(server->packet, smb_vwv0);
 
+	/* flush to disk, to trigger win9x to update its filesize */
+	/* FIXME: this will be rather costly, won't it? */
+	if (server->mnt->flags & SMB_MOUNT_WIN95)
+		smb_proc_flush(server, fileid);
+
 	smb_unlock_server(server);
 	return result;
 }
@@ -1423,6 +1415,17 @@
 	return result;
 }
 
+/*
+ * Called with the server locked
+ */
+int
+smb_proc_flush(struct smb_sb_info *server, __u16 fileid)
+{
+	smb_setup_header(server, SMBflush, 1, 0);
+	WSET(server->packet, smb_vwv0, fileid);
+	return smb_request_ok(server, SMBflush, 0, 0);
+}
+
 int
 smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
 {
@@ -1431,7 +1434,7 @@
 
 	smb_lock_server(server);
 
-      retry:
+retry:
 	p = smb_setup_header(server, SMBwrite, 5, 3);
 	WSET(server->packet, smb_vwv0, fid);
 	WSET(server->packet, smb_vwv1, 0);
@@ -1445,7 +1448,15 @@
 			goto retry;
 		goto out;
 	}
-	result = 0;
+
+	/*
+	 * win9x doesn't appear to update the size immediately.
+	 * It will return the old file size after the truncate,
+	 * confusing smbfs.
+	 * NT and Samba return the new value immediately.
+	 */
+	if (server->mnt->flags & SMB_MOUNT_WIN95)
+		smb_proc_flush(server, fid);
 out:
 	smb_unlock_server(server);
 	return result;
diff -u --recursive --new-file v2.4.4/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c
--- v2.4.4/linux/fs/smbfs/sock.c	Fri Feb 16 16:03:24 2001
+++ linux/fs/smbfs/sock.c	Tue May 15 13:40:55 2001
@@ -150,14 +150,14 @@
 	DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
 	if (found)
 		found_data(job->sk);
-	kfree(ptr);
+	smb_kfree(ptr);
 }
 
 static void
 smb_data_ready(struct sock *sk, int len)
 {
 	struct data_callback* job;
-	job = kmalloc(sizeof(struct data_callback),GFP_ATOMIC);
+	job = smb_kmalloc(sizeof(struct data_callback),GFP_ATOMIC);
 	if(job == 0) {
 		printk("smb_data_ready: lost SESSION KEEPALIVE due to OOM.\n");
 		found_data(sk);
diff -u --recursive --new-file v2.4.4/linux/fs/super.c linux/fs/super.c
--- v2.4.4/linux/fs/super.c	Fri Apr 27 14:11:31 2001
+++ linux/fs/super.c	Thu May 24 15:02:06 2001
@@ -282,6 +282,24 @@
 
 static LIST_HEAD(vfsmntlist);
 
+static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
+{
+	old_nd->dentry = mnt->mnt_mountpoint;
+	old_nd->mnt = mnt->mnt_parent;
+	mnt->mnt_parent = mnt;
+	mnt->mnt_mountpoint = mnt->mnt_root;
+	list_del_init(&mnt->mnt_child);
+	list_del_init(&mnt->mnt_clash);
+}
+
+static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd)
+{
+	mnt->mnt_parent = mntget(nd->mnt);
+	mnt->mnt_mountpoint = dget(nd->dentry);
+	list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt);
+	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+}
+
 /**
  *	add_vfsmnt - add a new mount node
  *	@nd: location of mountpoint or %NULL if we want a root node
@@ -337,13 +355,12 @@
 	if (nd && !IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
 		goto fail;
 	mnt->mnt_root = dget(root);
-	mnt->mnt_mountpoint = nd ? dget(nd->dentry) : dget(root);
-	mnt->mnt_parent = nd ? mntget(nd->mnt) : mnt;
 
 	if (nd) {
-		list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
-		list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt);
+		attach_mnt(mnt, nd);
 	} else {
+		mnt->mnt_mountpoint = mnt->mnt_root;
+		mnt->mnt_parent = mnt;
 		INIT_LIST_HEAD(&mnt->mnt_child);
 		INIT_LIST_HEAD(&mnt->mnt_clash);
 	}
@@ -362,12 +379,10 @@
 }
 
 static void move_vfsmnt(struct vfsmount *mnt,
-			struct dentry *mountpoint,
-			struct vfsmount *parent,
+			struct nameidata *nd, 
 			const char *dev_name)
 {
-	struct dentry *old_mountpoint;
-	struct vfsmount *old_parent;
+	struct nameidata parent_nd;
 	char *new_devname = NULL;
 
 	if (dev_name) {
@@ -377,56 +392,35 @@
 	}
 
 	spin_lock(&dcache_lock);
-	old_mountpoint = mnt->mnt_mountpoint;
-	old_parent = mnt->mnt_parent;
+	detach_mnt(mnt, &parent_nd);
+	attach_mnt(mnt, nd);
 
-	/* flip names */
 	if (new_devname) {
 		if (mnt->mnt_devname)
 			kfree(mnt->mnt_devname);
 		mnt->mnt_devname = new_devname;
 	}
-
-	/* flip the linkage */
-	mnt->mnt_mountpoint = dget(mountpoint);
-	mnt->mnt_parent = parent ? mntget(parent) : mnt;
-	list_del(&mnt->mnt_clash);
-	list_del(&mnt->mnt_child);
-	if (parent) {
-		list_add(&mnt->mnt_child, &parent->mnt_mounts);
-		list_add(&mnt->mnt_clash, &mountpoint->d_vfsmnt);
-	} else {
-		INIT_LIST_HEAD(&mnt->mnt_child);
-		INIT_LIST_HEAD(&mnt->mnt_clash);
-	}
 	spin_unlock(&dcache_lock);
 
 	/* put the old stuff */
-	dput(old_mountpoint);
-	if (old_parent != mnt)
-		mntput(old_parent);
+	if (parent_nd.mnt != mnt)
+		path_release(&parent_nd);
 }
 
-/*
- * Called with spinlock held, releases it.
- */
-static void remove_vfsmnt(struct vfsmount *mnt)
+static void kill_super(struct super_block *);
+
+void __mntput(struct vfsmount *mnt)
 {
-	/* First of all, remove it from all lists */
-	list_del(&mnt->mnt_instances);
-	list_del(&mnt->mnt_clash);
-	list_del(&mnt->mnt_list);
-	list_del(&mnt->mnt_child);
-	spin_unlock(&dcache_lock);
-	/* Now we can work safely */
-	if (mnt->mnt_parent != mnt)
-		mntput(mnt->mnt_parent);
+	struct super_block *sb = mnt->mnt_sb;
 
-	dput(mnt->mnt_mountpoint);
 	dput(mnt->mnt_root);
+	spin_lock(&dcache_lock);
+	list_del(&mnt->mnt_instances);
+	spin_unlock(&dcache_lock);
 	if (mnt->mnt_devname)
 		kfree(mnt->mnt_devname);
 	kfree(mnt);
+	kill_super(sb);
 }
 
 
@@ -580,30 +574,7 @@
 #undef MANGLE
 #undef FREEROOM
 }
-
-/**
- *	__wait_on_super	- wait on a superblock
- *	@sb: superblock to wait on
- *
- *	Waits for a superblock to become unlocked and then returns. It does
- *	not take the lock. This is an internal function. See wait_on_super().
- */
  
-void __wait_on_super(struct super_block * sb)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&sb->s_wait, &wait);
-repeat:
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	if (sb->s_lock) {
-		schedule();
-		goto repeat;
-	}
-	remove_wait_queue(&sb->s_wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
 /*
  * Note: check the dirty flag before waiting, so we don't
  * hold up the sync while mounting a device. (The newly
@@ -648,7 +619,9 @@
 	s = sb_entry(super_blocks.next);
 	while (s != sb_entry(&super_blocks))
 		if (s->s_dev == dev) {
-			wait_on_super(s);
+			/* Yes, it sucks. As soon as we get refcounting... */
+			lock_super(s);
+			unlock_super(s);
 			if (s->s_dev == dev)
 				return s;
 			goto restart;
@@ -700,9 +673,7 @@
 	     s  = sb_entry(s->s_list.next)) {
 		if (s->s_dev)
 			continue;
-		if (!s->s_lock)
-			return s;
-		printk("VFS: empty superblock %p locked!\n", s);
+		return s;
 	}
 	/* Need a new one... */
 	if (nr_super_blocks >= max_super_blocks)
@@ -714,10 +685,14 @@
 		INIT_LIST_HEAD(&s->s_dirty);
 		INIT_LIST_HEAD(&s->s_locked_inodes);
 		list_add (&s->s_list, super_blocks.prev);
-		init_waitqueue_head(&s->s_wait);
 		INIT_LIST_HEAD(&s->s_files);
 		INIT_LIST_HEAD(&s->s_mounts);
 		init_rwsem(&s->s_umount);
+		sema_init(&s->s_lock, 1);
+		sema_init(&s->s_vfs_rename_sem,1);
+		sema_init(&s->s_nfsd_free_path_sem,1);
+		sema_init(&s->s_dquot.dqio_sem, 1);
+		sema_init(&s->s_dquot.dqoff_sem, 1);
 	}
 	return s;
 }
@@ -734,11 +709,7 @@
 	s->s_bdev = bdev;
 	s->s_flags = flags;
 	s->s_dirt = 0;
-	sema_init(&s->s_vfs_rename_sem,1);
-	sema_init(&s->s_nfsd_free_path_sem,1);
 	s->s_type = type;
-	sema_init(&s->s_dquot.dqio_sem, 1);
-	sema_init(&s->s_dquot.dqoff_sem, 1);
 	s->s_dquot.flags = 0;
 	s->s_maxbytes = MAX_NON_LFS;
 	lock_super(s);
@@ -889,7 +860,7 @@
 	return sb;
 }
 
-static void kill_super(struct super_block *sb, int umount_root)
+static void kill_super(struct super_block *sb)
 {
 	struct block_device *bdev;
 	kdev_t dev;
@@ -897,6 +868,12 @@
 	struct file_system_type *fs = sb->s_type;
 	struct super_operations *sop = sb->s_op;
 
+	spin_lock(&dcache_lock);
+	if (!list_empty(&sb->s_mounts)) {
+		spin_unlock(&dcache_lock);
+		return;
+	}
+	spin_unlock(&dcache_lock);
 	down_write(&sb->s_umount);
 	sb->s_root = NULL;
 	/* Need to clean after the sucker */
@@ -927,12 +904,6 @@
 	sb->s_type = NULL;
 	unlock_super(sb);
 	up_write(&sb->s_umount);
-	if (umount_root) {
-		/* special: the old device driver is going to be
-		   a ramdisk and the point of this call is to free its
-		   protected memory (even if dirty). */
-		destroy_buffers(dev);
-	}
 	if (bdev) {
 		blkdev_put(bdev, BDEV_FS);
 		bdput(bdev);
@@ -988,23 +959,13 @@
 	}
 	mnt = add_vfsmnt(NULL, sb->s_root, NULL);
 	if (!mnt) {
-		kill_super(sb, 0);
+		kill_super(sb);
 		return ERR_PTR(-ENOMEM);
 	}
 	type->kern_mnt = mnt;
 	return mnt;
 }
 
-/* Call only after unregister_filesystem() - it's a final cleanup */
-
-void kern_umount(struct vfsmount *mnt)
-{
-	struct super_block *sb = mnt->mnt_sb;
-	spin_lock(&dcache_lock);
-	remove_vfsmnt(mnt);
-	kill_super(sb, 0);
-}
-
 /*
  * Doesn't take quota and stuff into account. IOW, in some cases it will
  * give false negatives. The main reason why it's here is that we need
@@ -1017,9 +978,10 @@
 	return 0;
 }
 
-static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
+static int do_umount(struct vfsmount *mnt, int flags)
 {
 	struct super_block * sb = mnt->mnt_sb;
+	struct nameidata parent_nd;
 
 	/*
 	 * No sense to grab the lock for this test, but test itself looks
@@ -1031,12 +993,11 @@
 	 * /reboot - static binary that would close all descriptors and
 	 * call reboot(9). Then init(8) could umount root and exec /reboot.
 	 */
-	if (mnt == current->fs->rootmnt && !umount_root) {
+	if (mnt == current->fs->rootmnt) {
 		/*
 		 * Special case for "unmounting" root ...
 		 * we just try to remount it readonly.
 		 */
-		mntput(mnt);
 		return do_remount("/", MS_RDONLY, NULL);
 	}
 
@@ -1045,14 +1006,16 @@
 	if (mnt->mnt_instances.next != mnt->mnt_instances.prev) {
 		if (atomic_read(&mnt->mnt_count) > 2) {
 			spin_unlock(&dcache_lock);
-			mntput(mnt);
 			return -EBUSY;
 		}
 		if (sb->s_type->fs_flags & FS_SINGLE)
 			put_filesystem(sb->s_type);
-		/* We hold two references, so mntput() is safe */
+		detach_mnt(mnt, &parent_nd);
+		list_del(&mnt->mnt_list);
+		spin_unlock(&dcache_lock);
 		mntput(mnt);
-		remove_vfsmnt(mnt);
+		if (parent_nd.mnt != mnt)
+			path_release(&parent_nd);
 		return 0;
 	}
 	spin_unlock(&dcache_lock);
@@ -1084,15 +1047,16 @@
 	spin_lock(&dcache_lock);
 	if (atomic_read(&mnt->mnt_count) > 2) {
 		spin_unlock(&dcache_lock);
-		mntput(mnt);
 		return -EBUSY;
 	}
 
 	/* OK, that's the point of no return */
+	detach_mnt(mnt, &parent_nd);
+	list_del(&mnt->mnt_list);
+	spin_unlock(&dcache_lock);
 	mntput(mnt);
-	remove_vfsmnt(mnt);
-
-	kill_super(sb, umount_root);
+	if (parent_nd.mnt != mnt)
+		path_release(&parent_nd);
 	return 0;
 }
 
@@ -1110,7 +1074,6 @@
 	char *kname;
 	int retval;
 
-	lock_kernel();
 	kname = getname(name);
 	retval = PTR_ERR(kname);
 	if (IS_ERR(kname))
@@ -1129,16 +1092,16 @@
 	if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
 		goto dput_and_out;
 
-	dput(nd.dentry);
-	/* puts nd.mnt */
 	down(&mount_sem);
-	retval = do_umount(nd.mnt, 0, flags);
+	lock_kernel();
+	retval = do_umount(nd.mnt, flags);
+	unlock_kernel();
+	path_release(&nd);
 	up(&mount_sem);
 	goto out;
 dput_and_out:
 	path_release(&nd);
 out:
-	unlock_kernel();
 	return retval;
 }
 
@@ -1288,12 +1251,18 @@
 }
 
 /*
- * Flags is a 32-bit value that allows up to 32 non-fs dependent flags to
+ * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
  * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
  *
  * data is a (void *) that can point to any structure up to
  * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
  * information (or be NULL).
+ *
+ * Pre-0.97 versions of mount() didn't have a flags word.
+ * When the flags word was introduced its top half was required
+ * to have the magic value 0xC0ED, and this remained so until 2.4.0-test9.
+ * Therefore, if this magic number is present, it carries no information
+ * and must be discarded.
  */
 long do_mount(char * dev_name, char * dir_name, char *type_page,
 		  unsigned long flags, void *data_page)
@@ -1304,6 +1273,10 @@
 	struct super_block *sb;
 	int retval = 0;
 
+	/* Discard magic */
+	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+		flags &= ~MS_MGC_MSK;
+
 	/* Basic sanity checks */
 
 	if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
@@ -1391,8 +1364,7 @@
 fail:
 	if (fstype->fs_flags & FS_SINGLE)
 		put_filesystem(fstype);
-	if (list_empty(&sb->s_mounts))
-		kill_super(sb, 0);
+	kill_super(sb);
 	goto unlock_out;
 }
 
@@ -1631,8 +1603,9 @@
  *  - we don't move root/cwd if they are not at the root (reason: if something
  *    cared enough to change them, it's probably wrong to force them elsewhere)
  *  - it's okay to pick a root that isn't the root of a file system, e.g.
- *    /nfs/my_root where /nfs is the mount point. Better avoid creating
- *    unreachable mount points this way, though.
+ *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
+ *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
+ *    first.
  */
 
 asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
@@ -1640,7 +1613,7 @@
 	struct dentry *root;
 	struct vfsmount *root_mnt;
 	struct vfsmount *tmp;
-	struct nameidata new_nd, old_nd;
+	struct nameidata new_nd, old_nd, parent_nd, root_parent;
 	char *name;
 	int error;
 
@@ -1688,6 +1661,10 @@
 	if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
 		goto out2; /* loop */
 	error = -EINVAL;
+	if (root_mnt->mnt_root != root)
+		goto out2;
+	if (new_nd.mnt->mnt_root != new_nd.dentry)
+		goto out2; /* not a mountpoint */
 	tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
 	spin_lock(&dcache_lock);
 	if (tmp != new_nd.mnt) {
@@ -1702,12 +1679,18 @@
 			goto out3;
 	} else if (!is_subdir(old_nd.dentry, new_nd.dentry))
 		goto out3;
+	detach_mnt(new_nd.mnt, &parent_nd);
+	detach_mnt(root_mnt, &root_parent);
+	attach_mnt(root_mnt, &old_nd);
+	if (root_parent.mnt != root_mnt)
+		attach_mnt(new_nd.mnt, &root_parent);
 	spin_unlock(&dcache_lock);
-
-	move_vfsmnt(new_nd.mnt, new_nd.dentry, NULL, NULL);
-	move_vfsmnt(root_mnt, old_nd.dentry, old_nd.mnt, NULL);
 	chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
 	error = 0;
+	if (root_parent.mnt != root_mnt)
+		path_release(&root_parent);
+	if (parent_nd.mnt != new_nd.mnt)
+		path_release(&parent_nd);
 out2:
 	up(&old_nd.dentry->d_inode->i_zombie);
 	up(&mount_sem);
@@ -1742,10 +1725,9 @@
 	if (!error) {
 		if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC &&
 		    devfs_nd.dentry == devfs_nd.mnt->mnt_root) {
-			dput(devfs_nd.dentry);
 			down(&mount_sem);
-			/* puts devfs_nd.mnt */
-			do_umount(devfs_nd.mnt, 0, 0);
+			do_umount(devfs_nd.mnt, 0);
+			path_release(&devfs_nd);
 			up(&mount_sem);
 		} else 
 			path_release(&devfs_nd);
@@ -1766,18 +1748,26 @@
 		error = path_walk(put_old, &nd);
 	if (error) {
 		int blivet;
+		struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev;
 
+		blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
 		printk(KERN_NOTICE "Trying to unmount old root ... ");
-		blivet = do_umount(old_rootmnt, 1, 0);
 		if (!blivet) {
-			printk("okay\n");
-			return 0;
+			blivet = do_umount(old_rootmnt, 0);
+			mntput(old_rootmnt);
+			if (!blivet) {
+				ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
+				printk("okay\n");
+				error = 0;
+			}
+			blkdev_put(ramdisk, BDEV_FS);
 		}
-		printk(KERN_ERR "error %d\n", blivet);
+		if (blivet)
+			printk(KERN_ERR "error %d\n", blivet);
 		return error;
 	}
 	/* FIXME: we should hold i_zombie on nd.dentry */
-	move_vfsmnt(old_rootmnt, nd.dentry, nd.mnt, "/dev/root.old");
+	move_vfsmnt(old_rootmnt, &nd, "/dev/root.old");
 	mntput(old_rootmnt);
 	path_release(&nd);
 	return 0;
diff -u --recursive --new-file v2.4.4/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.4.4/linux/fs/ufs/super.c	Tue Apr 17 23:16:39 2001
+++ linux/fs/ufs/super.c	Wed May 16 10:31:27 2001
@@ -230,9 +230,6 @@
 	va_start (args, fmt);
 	vsprintf (error_buf, fmt, args);
 	va_end (args);
-	/* this is to prevent panic from syncing this filesystem */
-	if (sb->s_lock)
-		sb->s_lock = 0;
 	sb->s_flags |= MS_RDONLY;
 	printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
 		kdevname(sb->s_dev), function, error_buf);
diff -u --recursive --new-file v2.4.4/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.4.4/linux/fs/umsdos/inode.c	Mon Oct 16 12:58:51 2000
+++ linux/fs/umsdos/inode.c	Sat May 19 18:02:45 2001
@@ -378,7 +378,7 @@
 	 * lookup_dentry needs a (so far non-existent) root. 
 	 */
 	printk(KERN_INFO "check_pseudo_root: mounted as root\n");
-	root = lookup_one(UMSDOS_PSDROOT_NAME, sb->s_root); 
+	root = lookup_one_len(UMSDOS_PSDROOT_NAME, sb->s_root,UMSDOS_PSDROOT_LEN); 
 	if (IS_ERR(root))
 		goto out_noroot;
 	if (!root->d_inode || !S_ISDIR(root->d_inode->i_mode))
@@ -387,12 +387,12 @@
 	printk(KERN_INFO "check_pseudo_root: found %s/%s\n", root->d_parent->d_name.name, root->d_name.name);
 
 	/* look for /sbin/init */
-	sbin = lookup_one("sbin", root);
+	sbin = lookup_one_len("sbin", root, 4);
 	if (IS_ERR(sbin))
 		goto out_dput;
 	if (!sbin->d_inode || !S_ISDIR(sbin->d_inode->i_mode))
 		goto out_dput_sbin;
-	init = lookup_one("init", sbin);
+	init = lookup_one_len("init", sbin, 4);
 	if (IS_ERR(init))
 		goto out_dput_sbin;
 	if (!init->d_inode)
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h
--- v2.4.4/linux/include/asm-alpha/bitops.h	Sun Dec  3 17:45:20 2000
+++ linux/include/asm-alpha/bitops.h	Thu May 24 15:20:18 2001
@@ -46,7 +46,7 @@
 {
 	int *m = ((int *) addr) + (nr >> 5);
 
-	*m |= 1UL << (nr & 31);
+	*m |= 1 << (nr & 31);
 }
 
 #define smp_mb__before_clear_bit()	smp_mb()
@@ -70,6 +70,17 @@
 	:"Ir" (~(1UL << (nr & 31))), "m" (*m));
 }
 
+/*
+ * WARNING: non atomic version.
+ */
+static __inline__ void
+__change_bit(unsigned long nr, volatile void * addr)
+{
+	int *m = ((int *) addr) + (nr >> 5);
+
+	*m ^= 1 << (nr & 31);
+}
+
 extern __inline__ void
 change_bit(unsigned long nr, volatile void * addr)
 {
@@ -167,6 +178,20 @@
 	int old = *m;
 
 	*m = old & ~mask;
+	return (old & mask) != 0;
+}
+
+/*
+ * WARNING: non atomic version.
+ */
+static __inline__ int
+__test_and_change_bit(unsigned long nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	int *m = ((int *) addr) + (nr >> 5);
+	int old = *m;
+
+	*m = old ^ mask;
 	return (old & mask) != 0;
 }
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/compiler.h linux/include/asm-alpha/compiler.h
--- v2.4.4/linux/include/asm-alpha/compiler.h	Sun Apr 22 19:10:53 2001
+++ linux/include/asm-alpha/compiler.h	Sun May 20 12:11:39 2001
@@ -72,4 +72,13 @@
   __asm__("stw %1,%0" : "=m"(mem) : "r"(val))
 #endif
 
+/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
+   a mechanism by which the user can annotate likely branch directions and
+   expect the blocks to be reordered appropriately.  Define __builtin_expect
+   to nothing for earlier compilers.  */
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
 #endif /* __ALPHA_COMPILER_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h
--- v2.4.4/linux/include/asm-alpha/core_tsunami.h	Mon Jun 19 17:59:33 2000
+++ linux/include/asm-alpha/core_tsunami.h	Thu May 24 15:24:37 2001
@@ -275,6 +275,9 @@
 /* The IO address space is larger than 0xffff */
 #define TSUNAMI_IO_SPACE	(TSUNAMI_CONF(0) - TSUNAMI_IO(0))
 
+/* Offset between ram physical addresses and pci64 DAC bus addresses */
+#define TSUNAMI_DAC_OFFSET	(1UL << 40)
+
 /*
  * Data structure for handling TSUNAMI machine checks:
  */
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/mmzone.h linux/include/asm-alpha/mmzone.h
--- v2.4.4/linux/include/asm-alpha/mmzone.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/mmzone.h	Thu May 24 15:20:18 2001
@@ -0,0 +1,127 @@
+/*
+ * Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99
+ * Adapted for the alpha wildfire architecture Jan 2001.
+ */
+#ifndef _ASM_MMZONE_H_
+#define _ASM_MMZONE_H_
+
+#include <linux/config.h>
+#ifdef CONFIG_NUMA_SCHED
+#include <linux/numa_sched.h>
+#endif
+#ifdef NOTYET
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/klkernvars.h>
+#endif /* NOTYET */
+
+typedef struct plat_pglist_data {
+	pg_data_t	gendata;
+#ifdef NOTYET
+	kern_vars_t	kern_vars;
+#endif
+#if defined(CONFIG_NUMA) && defined(CONFIG_NUMA_SCHED)
+	struct numa_schedule_data schedule_data;
+#endif
+} plat_pg_data_t;
+
+struct bootmem_data_t; /* stupid forward decl. */
+
+/*
+ * Following are macros that are specific to this numa platform.
+ */
+
+extern plat_pg_data_t *plat_node_data[];
+
+#ifdef CONFIG_ALPHA_WILDFIRE
+# define ALPHA_PA_TO_NID(pa)	((pa) >> 36)	/* 16 nodes max due 43bit kseg */
+#define NODE_MAX_MEM_SIZE	(64L * 1024L * 1024L * 1024L) /* 64 GB */
+#define MAX_NUMNODES		WILDFIRE_MAX_QBB
+#else
+# define ALPHA_PA_TO_NID(pa)	(0)
+#define NODE_MAX_MEM_SIZE	(~0UL)
+#define MAX_NUMNODES		1
+#endif
+
+#define PHYSADDR_TO_NID(pa)		ALPHA_PA_TO_NID(pa)
+#define PLAT_NODE_DATA(n)		(plat_node_data[(n)])
+#define PLAT_NODE_DATA_STARTNR(n)	\
+	(PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
+#define PLAT_NODE_DATA_SIZE(n)		(PLAT_NODE_DATA(n)->gendata.node_size)
+
+#if 1
+#define PLAT_NODE_DATA_LOCALNR(p, n)	\
+	(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
+#else
+static inline unsigned long
+PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
+{
+	unsigned long temp;
+	temp = p - PLAT_NODE_DATA(n)->gendata.node_start_paddr;
+	return (temp >> PAGE_SHIFT);
+}
+#endif
+
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * Following are macros that each numa implmentation must define.
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(kaddr)	PHYSADDR_TO_NID(__pa(kaddr))
+
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(n)	(&((PLAT_NODE_DATA(n))->gendata))
+
+/*
+ * NODE_MEM_MAP gives the kaddr for the mem_map of the node.
+ */
+#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and returns the the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr) \
+			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
+
+/*
+ * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
+ * and returns the kaddr corresponding to first physical page in the
+ * node's mem_map.
+ */
+#define LOCAL_BASE_ADDR(kaddr)	((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_paddr))
+
+#define LOCAL_MAP_NR(kvaddr) \
+	(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT)
+
+#define kern_addr_valid(kaddr)	test_bit(LOCAL_MAP_NR(kaddr), \
+					 NODE_DATA(KVADDR_TO_NID(kaddr))->valid_addr_bitmap)
+
+#define virt_to_page(kaddr)	(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+#define VALID_PAGE(page)	(((page) - mem_map) < max_mapnr)
+
+#ifdef CONFIG_NUMA
+#ifdef CONFIG_NUMA_SCHED
+#define NODE_SCHEDULE_DATA(nid)	(&((PLAT_NODE_DATA(nid))->schedule_data))
+#endif
+
+#ifdef CONFIG_ALPHA_WILDFIRE
+/* With wildfire assume 4 CPUs per node */
+#define cputonode(cpu)	((cpu) >> 2)
+#else
+#define cputonode(cpu)	0
+#endif /* CONFIG_ALPHA_WILDFIRE */
+
+#define numa_node_id()	cputonode(smp_processor_id())
+#endif /* CONFIG_NUMA */
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* _ASM_MMZONE_H_ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h
--- v2.4.4/linux/include/asm-alpha/page.h	Thu Feb  8 12:56:29 2001
+++ linux/include/asm-alpha/page.h	Thu May 24 15:20:18 2001
@@ -1,6 +1,8 @@
 #ifndef _ALPHA_PAGE_H
 #define _ALPHA_PAGE_H
 
+#include <asm/pal.h>
+
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	13
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
@@ -33,6 +35,7 @@
 #define pgprot_val(x)	((x).pgprot)
 
 #define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
 #define __pgd(x)	((pgd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
@@ -56,7 +59,11 @@
 
 #endif /* STRICT_MM_TYPECHECKS */
 
-#define BUG()		__asm__ __volatile__("call_pal 129 # bugchk")
+#define BUG()									\
+do {										\
+	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);			\
+	__asm__ __volatile__("call_pal %0  # bugchk" : : "i" (PAL_bugchk));	\
+} while (0)
 #define PAGE_BUG(page)	BUG()
 
 /* Pure 2^n version of get_order */
@@ -86,8 +93,10 @@
 
 #define __pa(x)			((unsigned long) (x) - PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long) (x) + PAGE_OFFSET))
+#ifndef CONFIG_DISCONTIGMEM
 #define virt_to_page(kaddr)	(mem_map + (__pa(kaddr) >> PAGE_SHIFT))
-#define VALID_PAGE(page)	((page - mem_map) < max_mapnr)
+#define VALID_PAGE(page)	(((page) - mem_map) < max_mapnr)
+#endif /* CONFIG_DISCONTIGMEM */
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- v2.4.4/linux/include/asm-alpha/pci.h	Fri Mar  2 11:12:07 2001
+++ linux/include/asm-alpha/pci.h	Mon May 21 13:38:41 2001
@@ -146,6 +146,8 @@
 
 extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask);
 
+/* Return the index of the PCI controller for device PDEV. */
+extern int pci_controller_num(struct pci_dev *pdev);
 #endif /* __KERNEL__ */
 
 /* Values for the `which' argument to sys_pciconfig_iobase.  */
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/pgalloc.h linux/include/asm-alpha/pgalloc.h
--- v2.4.4/linux/include/asm-alpha/pgalloc.h	Mon Apr 23 15:28:07 2001
+++ linux/include/asm-alpha/pgalloc.h	Thu May 24 15:20:18 2001
@@ -229,6 +229,7 @@
 #ifndef CONFIG_SMP
 extern struct pgtable_cache_struct {
 	unsigned long *pgd_cache;
+	unsigned long *pmd_cache;
 	unsigned long *pte_cache;
 	unsigned long pgtable_cache_sz;
 } quicklists;
@@ -237,7 +238,7 @@
 #define quicklists cpu_data[smp_processor_id()]
 #endif
 #define pgd_quicklist (quicklists.pgd_cache)
-#define pmd_quicklist ((unsigned long *)0)
+#define pmd_quicklist (quicklists.pmd_cache)
 #define pte_quicklist (quicklists.pte_cache)
 #define pgtable_cache_size (quicklists.pgtable_cache_sz)
 
@@ -252,7 +253,7 @@
 
 	if ((ret = pgd_quicklist) != NULL) {
 		pgd_quicklist = (unsigned long *)(*ret);
-		ret[0] = ret[1];
+		ret[0] = 0;
 		pgtable_cache_size--;
 	} else
 		ret = (unsigned long *)get_pgd_slow();
@@ -285,7 +286,7 @@
 
 	if ((ret = (unsigned long *)pte_quicklist) != NULL) {
 		pte_quicklist = (unsigned long *)(*ret);
-		ret[0] = ret[1];
+		ret[0] = 0;
 		pgtable_cache_size--;
 	}
 	return (pmd_t *)ret;
@@ -317,7 +318,7 @@
 
 	if ((ret = (unsigned long *)pte_quicklist) != NULL) {
 		pte_quicklist = (unsigned long *)(*ret);
-		ret[0] = ret[1];
+		ret[0] = 0;
 		pgtable_cache_size--;
 	}
 	return (pte_t *)ret;
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v2.4.4/linux/include/asm-alpha/pgtable.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-alpha/pgtable.h	Thu May 24 15:20:18 2001
@@ -9,6 +9,7 @@
  * in <asm/page.h> (currently 8192).
  */
 #include <linux/config.h>
+#include <linux/mmzone.h>
 
 #include <asm/page.h>
 #include <asm/processor.h>	/* For TASK_SIZE */
@@ -189,6 +190,15 @@
  * Conversion functions:  convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
+#ifndef CONFIG_DISCONTIGMEM
+#define PAGE_TO_PA(page)	((page - mem_map) << PAGE_SHIFT)
+#else
+#define PAGE_TO_PA(page) \
+		((((page)-(page)->zone->zone_mem_map) << PAGE_SHIFT) \
+		+ (page)->zone->zone_start_paddr)
+#endif
+
+#ifndef CONFIG_DISCONTIGMEM
 #define mk_pte(page, pgprot)						\
 ({									\
 	pte_t pte;							\
@@ -197,6 +207,19 @@
 		       pgprot_val(pgprot);				\
 	pte;								\
 })
+#else
+#define mk_pte(page, pgprot)							\
+({										\
+	pte_t pte;								\
+	unsigned long pfn;							\
+										\
+	pfn = ((unsigned long)((page)-(page)->zone->zone_mem_map)) << 32;	\
+	pfn += (page)->zone->zone_start_paddr << (32-PAGE_SHIFT);		\
+	pte_val(pte) = pfn | pgprot_val(pgprot);				\
+										\
+	pte;									\
+})
+#endif
 
 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 { pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
@@ -210,7 +233,20 @@
 extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
 { pgd_val(*pgdp) = _PAGE_TABLE | ((((unsigned long) pmdp) - PAGE_OFFSET) << (32-PAGE_SHIFT)); }
 
+#ifndef CONFIG_DISCONTIGMEM
 #define pte_page(x)	(mem_map+(unsigned long)((pte_val(x) >> 32)))
+#else
+#define pte_page(x)							\
+({									\
+	unsigned long kvirt;						\
+	struct page * __xx;						\
+									\
+	kvirt = (unsigned long)__va(pte_val(x) >> (32-PAGE_SHIFT));	\
+	__xx = virt_to_page(kvirt);					\
+									\
+	__xx;								\
+})
+#endif
 
 extern inline unsigned long pmd_page(pmd_t pmd)
 { return PAGE_OFFSET + ((pmd_val(pmd) & _PFN_MASK) >> (32-PAGE_SHIFT)); }
@@ -303,7 +339,10 @@
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 #define PageSkip(page)		(0)
+
+#ifndef CONFIG_DISCONTIGMEM
 #define kern_addr_valid(addr)	(1)
+#endif
 
 #define io_remap_page_range(start, busaddr, size, prot) \
 	remap_page_range(start, virt_to_phys(__ioremap(busaddr)), size, prot)
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.4.4/linux/include/asm-alpha/semaphore.h	Sun Apr 22 19:10:53 2001
+++ linux/include/asm-alpha/semaphore.h	Sun May 20 12:11:39 2001
@@ -11,7 +11,7 @@
 #include <asm/current.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
-#include <linux/compiler.h>
+#include <asm/compiler.h>
 #include <linux/wait.h>
 #include <linux/rwsem.h>
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h
--- v2.4.4/linux/include/asm-alpha/smp.h	Fri Mar  2 11:30:15 2001
+++ linux/include/asm-alpha/smp.h	Thu May 24 15:20:18 2001
@@ -29,6 +29,7 @@
 	int need_new_asn;
 	int asn_lock;
 	unsigned long *pgd_cache;
+	unsigned long *pmd_cache;
 	unsigned long *pte_cache;
 	unsigned long pgtable_cache_sz;
 	unsigned long ipi_count;
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h
--- v2.4.4/linux/include/asm-alpha/spinlock.h	Sun Nov 12 19:27:11 2000
+++ linux/include/asm-alpha/spinlock.h	Thu May 24 15:20:18 2001
@@ -96,6 +96,8 @@
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
 
+#define rwlock_init(x)	do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
 #if DEBUG_RWLOCK
 extern void write_lock(rwlock_t * lock);
 extern void read_lock(rwlock_t * lock);
diff -u --recursive --new-file v2.4.4/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v2.4.4/linux/include/asm-alpha/system.h	Fri Dec 29 14:07:23 2000
+++ linux/include/asm-alpha/system.h	Thu May 24 15:20:18 2001
@@ -35,6 +35,18 @@
 
 #define START_ADDR	(PAGE_OFFSET+KERNEL_START_PHYS+0x10000)
 
+/*
+ * This is setup by the secondary bootstrap loader.  Because
+ * the zero page is zeroed out as soon as the vm system is
+ * initialized, we need to copy things out into a more permanent
+ * place.
+ */
+#define PARAM			ZERO_PGE
+#define COMMAND_LINE		((char*)(PARAM + 0x0000))
+#define COMMAND_LINE_SIZE	256
+#define INITRD_START		(*(unsigned long *) (PARAM+0x100))
+#define INITRD_SIZE		(*(unsigned long *) (PARAM+0x108))
+
 #ifndef __ASSEMBLY__
 #include <linux/kernel.h>
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-arm/arch-ebsa285/system.h linux/include/asm-arm/arch-ebsa285/system.h
--- v2.4.4/linux/include/asm-arm/arch-ebsa285/system.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-ebsa285/system.h	Wed May 16 15:25:16 2001
@@ -63,14 +63,24 @@
 			 */
 			outb(0xc4, 0x338);
 		} else {
-			/* To reboot, we set up the 21285 watchdog and
-			 * enable it.  We then wait for it to timeout.
+			/* 
+			 * Force the watchdog to do a CPU reset.
+			 *
+			 * After making sure that the watchdog is disabled
+			 * (so we can change the timer registers) we first
+			 * enable the timer to autoreload itself.  Next, the
+			 * timer interval is set really short and any
+			 * current interrupt request is cleared (so we can
+			 * see an edge transition).  Finally, TIMER4 is
+			 * enabled as the watchdog.
 			 */
-			*CSR_TIMER4_LOAD = 0x8000;
+			*CSR_SA110_CNTL &= ~(1 << 13);
 			*CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
 					   TIMER_CNTL_AUTORELOAD |
 					   TIMER_CNTL_DIV16;
-			*CSR_SA110_CNTL |= 1 << 13;
+			*CSR_TIMER4_LOAD = 0x2;
+			*CSR_TIMER4_CLR  = 0;
+			*CSR_SA110_CNTL |= (1 << 13);
 		}
 	}
 }
diff -u --recursive --new-file v2.4.4/linux/include/asm-arm/arch-l7200/keyboard.h linux/include/asm-arm/arch-l7200/keyboard.h
--- v2.4.4/linux/include/asm-arm/arch-l7200/keyboard.h	Thu Apr 12 12:20:31 2001
+++ linux/include/asm-arm/arch-l7200/keyboard.h	Wed May 16 15:25:16 2001
@@ -42,7 +42,7 @@
 #define kbd_unexpected_up(kc)           (0200)
 #define kbd_leds(leds)                  do {} while (0)
 #define kbd_init_hw()                   l7200kbd_init_hw()
-#define kbd_sysrq_xlate                 do {} while (0)
+#define kbd_sysrq_xlate                 ((unsigned char *)NULL)
 #define kbd_disable_irq()               disable_irq(IRQ_GCTC2)
 #define kbd_enable_irq()                enable_irq(IRQ_GCTC2)
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-arm/pci.h linux/include/asm-arm/pci.h
--- v2.4.4/linux/include/asm-arm/pci.h	Mon Nov 27 17:07:59 2000
+++ linux/include/asm-arm/pci.h	Wed May 16 10:31:27 2001
@@ -148,6 +148,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* __KERNEL__ */
  
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/asm-arm/uaccess.h linux/include/asm-arm/uaccess.h
--- v2.4.4/linux/include/asm-arm/uaccess.h	Tue Mar  6 19:44:35 2001
+++ linux/include/asm-arm/uaccess.h	Wed May 16 15:25:16 2001
@@ -75,6 +75,8 @@
 {
 	if (access_ok(VERIFY_READ, from, n))
 		__do_copy_from_user(to, from, n);
+	else /* security hole - plug it */
+		memzero(to, n);
 	return n;
 }
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/axisflashmap.h linux/include/asm-cris/axisflashmap.h
--- v2.4.4/linux/include/asm-cris/axisflashmap.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/axisflashmap.h	Tue May  1 16:05:00 2001
@@ -15,7 +15,7 @@
  * tools/mkptable is used to generate the ptable. 
  */
 
-/* The partition table start with kod to "jump over" it: */
+/* The partition table starts with code to "jump over" it: */
 #define PARTITIONTABLE_CODE_START { \
  0x0f, 0x05, /* nop 0 */\
  0x25, 0xf0, /* di  2 */\
@@ -24,7 +24,7 @@
 /* The actual offset depend on the number of entries */
 #define PARTITIONTABLE_CODE_END { \
  0x00, 0x00, /* ba offset 6 */\
- 0x0f, 0x0f  /* nop 8 */}
+ 0x0f, 0x05  /* nop 8 */}
 
 #define PARTITION_TABLE_OFFSET 10
 #define PARTITION_TABLE_MAGIC 0xbeef /* Not a good magic */
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/elf.h linux/include/asm-cris/elf.h
--- v2.4.4/linux/include/asm-cris/elf.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/elf.h	Tue May  1 16:05:00 2001
@@ -36,7 +36,14 @@
 	   that have been loaded before the code runs.
 
 	   A value of 0 tells we have no such handler.  */
-#define ELF_PLAT_INIT(_r)	((_r)->r10 = 0)
+	
+	/* Explicitly set registers to 0 to increase determinism.  */
+#define ELF_PLAT_INIT(_r)	do { \
+	(_r)->r13 = 0; (_r)->r12 = 0; (_r)->r11 = 0; (_r)->r10 = 0; \
+	(_r)->r9 = 0;  (_r)->r8 = 0;  (_r)->r7 = 0;  (_r)->r6 = 0;  \
+	(_r)->r5 = 0;  (_r)->r4 = 0;  (_r)->r3 = 0;  (_r)->r2 = 0;  \
+	(_r)->r1 = 0;  (_r)->r0 = 0;  (_r)->mof = 0; (_r)->srp = 0; \
+} while (0)
 
 #undef USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	8192
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/etraxgpio.h linux/include/asm-cris/etraxgpio.h
--- v2.4.4/linux/include/asm-cris/etraxgpio.h	Fri Apr  6 10:51:19 2001
+++ linux/include/asm-cris/etraxgpio.h	Tue May  1 16:05:00 2001
@@ -28,5 +28,7 @@
 #define IO_SETOUTPUT  0xA  /* Set direction 0=unchanged 1=output,
                               returns current dir */
 
+/* LED ioctl extended */
+#define IO_LED_SETBIT 0xB
+#define IO_LED_CLRBIT 0xC
 #endif
-
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/io.h linux/include/asm-cris/io.h
--- v2.4.4/linux/include/asm-cris/io.h	Fri Apr  6 10:51:19 2001
+++ linux/include/asm-cris/io.h	Tue May  1 16:05:00 2001
@@ -9,9 +9,9 @@
    use will be evident. */
 #ifdef CONFIG_SVINTO_SIM
   /* Let's use the ucsim interface since it lets us do write(2, ...) */
-#define SIMCOUT(s,len) asm ("moveq 4,r9\n\tmoveq 2,r10\n\tmove.d %0,r11\n\tmove.d %1,r12\
+#define SIMCOUT(s,len) asm ("moveq 4,r1\n\tmoveq 2,r10\n\tmove.d %0,r11\n\tmove.d %1,r12\
 \n\tpush irp\n\t.word 0xae3f\n\t.dword 0f\n\tjump -6809\n0:\n\tpop irp" \
-       : : "rm" (s), "rm" (len) : "r9","r10","r11","r12","memory")
+       : : "rm" (s), "rm" (len) : "r1","r10","r11","r12","memory")
 #define TRACE_ON() __extension__ \
  ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \
 			       (255)); _Foofoo; })
@@ -36,7 +36,14 @@
 extern unsigned char port_pb_dir_shadow;
 extern unsigned char port_pb_data_shadow;
 extern unsigned long r_timer_ctrl_shadow;
-extern unsigned long port_90000000_shadow;
+
+extern unsigned long port_cse1_shadow;
+extern unsigned long port_csp0_shadow;
+extern unsigned long port_csp4_shadow;
+
+extern volatile unsigned long *port_cse1_addr;
+extern volatile unsigned long *port_csp0_addr;
+extern volatile unsigned long *port_csp4_addr;
 
 /* macro for setting regs through a shadow - 
  * r = register name (like R_PORT_PA_DATA)
@@ -45,74 +52,104 @@
  * v = value (0 or 1)
  */
 
-#define REG_SHADOW_SET(r,s,b,v) *r = s = (s & ~(1 << b)) | ((v) << b) 
+#define REG_SHADOW_SET(r,s,b,v) *r = s = (s & ~(1 << (b))) | ((v) << (b))
 
 /* The LED's on various Etrax-based products are set differently. */
 
 #if defined(CONFIG_ETRAX_NO_LEDS) || defined(CONFIG_SVINTO_SIM)
 #undef CONFIG_ETRAX_PA_LEDS
 #undef CONFIG_ETRAX_PB_LEDS
-#undef CONFIG_ETRAX_90000000_LEDS
-#define LED_NETWORK_RX_SET(x)
-#define LED_NETWORK_TX_SET(x)
-#define LED_ACTIVE_SET(x)
+#undef CONFIG_ETRAX_CSP0_LEDS
+#define LED_NETWORK_SET_G(x)
+#define LED_NETWORK_SET_R(x)
 #define LED_ACTIVE_SET_G(x)
 #define LED_ACTIVE_SET_R(x)
 #define LED_DISK_WRITE(x)
 #define LED_DISK_READ(x)
 #endif
 
+#if !defined(CONFIG_ETRAX_CSP0_LEDS)
+#define LED_BIT_SET(x)
+#define LED_BIT_CLR(x)
+#endif
+
+#define LED_OFF    0x00
+#define LED_GREEN  0x01
+#define LED_RED    0x02
+#define LED_ORANGE (LED_GREEN | LED_RED)
+
+#if CONFIG_ETRAX_LED1G == CONFIG_ETRAX_LED1R 
+#define LED_NETWORK_SET(x)                          \
+	do {                                        \
+		LED_NETWORK_SET_G((x) & LED_GREEN); \
+	} while (0)
+#else
+#define LED_NETWORK_SET(x)                          \
+	do {                                        \
+		LED_NETWORK_SET_G((x) & LED_GREEN); \
+		LED_NETWORK_SET_R((x) & LED_RED);   \
+	} while (0)
+#endif
+#if CONFIG_ETRAX_LED2G == CONFIG_ETRAX_LED2R 
+#define LED_ACTIVE_SET(x)                           \
+	do {                                        \
+		LED_ACTIVE_SET_G((x) & LED_GREEN);  \
+	} while (0)
+#else
+#define LED_ACTIVE_SET(x)                           \
+	do {                                        \
+		LED_ACTIVE_SET_G((x) & LED_GREEN);  \
+		LED_ACTIVE_SET_R((x) & LED_RED);    \
+	} while (0)
+#endif
+
 #ifdef CONFIG_ETRAX_PA_LEDS
-#define LED_NETWORK_RX_SET(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1G, !x)
-#define LED_NETWORK_TX_SET(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1R, !x)
-#define LED_ACTIVE_SET(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_NETWORK_SET_G(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1G, !(x))
+#define LED_NETWORK_SET_R(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1R, !(x))
 #define LED_ACTIVE_SET_G(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !x)
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !(x))
 #define LED_ACTIVE_SET_R(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2R, !x)
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2R, !(x))
 #define LED_DISK_WRITE(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !x)
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !(x))
 #define LED_DISK_READ(x) \
-         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !x) 
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !(x)) 
 #endif
 
 #ifdef CONFIG_ETRAX_PB_LEDS
-#define LED_NETWORK_RX_SET(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1G, !x)
-#define LED_NETWORK_TX_SET(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1R, !x)
-#define LED_ACTIVE_SET(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_NETWORK_SET_G(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1G, !(x))
+#define LED_NETWORK_SET_R(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1R, !(x))
 #define LED_ACTIVE_SET_G(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !x)
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !(x))
 #define LED_ACTIVE_SET_R(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2R, !x)
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2R, !(x))
 #define LED_DISK_WRITE(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !x)
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !(x))
 #define LED_DISK_READ(x) \
-         REG_SHADOW_SET(R_PORT_PB_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !x)     
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !(x))     
 #endif
 
-#ifdef CONFIG_ETRAX_90000000_LEDS
-/* TODO: this won't work, need a vremap into kernel virtual memory of 90000000 */
-#define LED_PORT_90 (volatile unsigned long*)0x90000000
-#define LED_ACTIVE_SET(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED2G, !x)
-#define LED_NETWORK_RX_SET(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED1G, !x)
-#define LED_NETWORK_TX_SET(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED1R, !x)
+#ifdef CONFIG_ETRAX_CSP0_LEDS
+#define LED_NETWORK_SET_G(x) \
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED1G, !(x))
+#define LED_NETWORK_SET_R(x) \
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED1R, !(x))
 #define LED_ACTIVE_SET_G(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED2G, !x)
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED2G, !(x))
 #define LED_ACTIVE_SET_R(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED2R, !x)
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED2R, !(x))
 #define LED_DISK_WRITE(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED3R, !x)
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3R, !(x))
 #define LED_DISK_READ(x) \
-         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED3G, !x)           
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, CONFIG_ETRAX_LED3G, !(x))
+#define LED_BIT_SET(x) \
+         REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, x, 1)
+#define LED_BIT_CLR(x) \
+          REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, x, 0)        
 #endif
 
 /*
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/irq.h linux/include/asm-cris/irq.h
--- v2.4.4/linux/include/asm-cris/irq.h	Fri Apr  6 10:51:19 2001
+++ linux/include/asm-cris/irq.h	Tue May  1 16:05:00 2001
@@ -45,7 +45,7 @@
 /* SAVE_ALL saves registers so they match pt_regs */
 
 #define SAVE_ALL \
-  "push irp\n\t"       /* push instruction pointer */ \
+  "move irp,[sp=sp-16]\n\t" /* push instruction pointer and fake SBFS struct */ \
   "push srp\n\t"       /* push subroutine return pointer */ \
   "push dccr\n\t"      /* push condition codes */ \
   "push mof\n\t"       /* push multiply overflow reg */ \
@@ -94,7 +94,9 @@
           "_bad_IRQ" #nr "_interrupt:\n\t" \
 	  "push r0\n\t" \
 	  BLOCK_IRQ(mask,nr) \
-	  "pop r0\n\t");
+	  "pop r0\n\t" \
+          "reti\n\t" \
+          "nop\n");
 
 
 #endif  /* _ASM_IRQ_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/pgalloc.h linux/include/asm-cris/pgalloc.h
--- v2.4.4/linux/include/asm-cris/pgalloc.h	Mon Apr 23 15:28:07 2001
+++ linux/include/asm-cris/pgalloc.h	Tue May  1 16:05:00 2001
@@ -1,24 +1,25 @@
 #ifndef _CRIS_PGALLOC_H
 #define _CRIS_PGALLOC_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 #include <linux/threads.h>
 
-/* bunch of protos */
+extern struct pgtable_cache_struct {
+        unsigned long *pgd_cache;
+        unsigned long *pte_cache;
+        unsigned long pgtable_cache_sz;
+} quicklists;
 
-extern pgd_t *get_pgd_slow(void);
-extern void free_pgd_slow(pgd_t *pgd);
-extern __inline__ void free_pmd_slow(pmd_t *pmd) { }
-extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
+#define pgd_quicklist           (quicklists.pgd_cache)
+#define pmd_quicklist           ((unsigned long *)0)
+#define pte_quicklist           (quicklists.pte_cache)
+#define pgtable_cache_size      (quicklists.pgtable_cache_sz)
 
-/* first the non-cached versions */
+#define pmd_populate(mm, pmd, pte) pmd_set(pmd, pte)
 
-extern __inline__ void free_pte_slow(pte_t *pte)
-{
-        free_page((unsigned long)pte);
-}
+/*
+ * Allocate and free page tables.
+ */
 
 extern __inline__ pgd_t *get_pgd_slow(void)
 {
@@ -37,27 +38,6 @@
         free_page((unsigned long)pgd);
 }
 
-/*
- * Now for the page table cache versions
- */
-
-#ifndef CONFIG_NO_PGT_CACHE
-
-#ifdef CONFIG_SMP
-#error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif  /* CONFIG_SMP */
-
-extern struct pgtable_cache_struct {
-        unsigned long *pgd_cache;
-        unsigned long *pte_cache;
-        unsigned long pgtable_cache_sz;
-} quicklists;
-
-#define pgd_quicklist           (quicklists.pgd_cache)
-#define pmd_quicklist           ((unsigned long *)0)
-#define pte_quicklist           (quicklists.pte_cache)
-#define pgtable_cache_size      (quicklists.pgtable_cache_sz)
-
 extern __inline__ pgd_t *get_pgd_fast(void)
 {
         unsigned long *ret;
@@ -78,16 +58,17 @@
         pgtable_cache_size++;
 }
 
-/* We don't use pmd cache, so this is a dummy routine */
-
-extern __inline__ pmd_t *get_pmd_fast(void)
+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-        return (pmd_t *)0;
-}
+        pte_t *pte;
 
-extern __inline__ void free_pmd_fast(pmd_t *pmd) { }
+        pte = (pte_t *) __get_free_page(GFP_KERNEL);
+        if (pte)
+                clear_page(pte);
+        return pte;
+}
 
-extern __inline__ pte_t *get_pte_fast(void)
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
         unsigned long *ret;
 
@@ -99,99 +80,33 @@
         return (pte_t *)ret;
 }
 
-extern __inline__ void free_pte_fast(pte_t *pte)
+static __inline__ void pte_free_fast(pte_t *pte)
 {
         *(unsigned long *)pte = (unsigned long) pte_quicklist;
         pte_quicklist = (unsigned long *) pte;
         pgtable_cache_size++;
 }
 
-#else   /* CONFIG_NO_PGT_CACHE */
-
-#define pgd_quicklist           ((unsigned long *)0)
-#define pmd_quicklist           ((unsigned long *)0)
-#define pte_quicklist           ((unsigned long *)0)
-
-#define get_pgd_fast()          ((pgd_t *)0)
-#define get_pmd_fast()          ((pmd_t *)0)
-#define get_pte_fast()          ((pte_t *)0)
-
-#define free_pgd_fast(pgd)      free_pgd_slow(pgd)
-#define free_pmd_fast(pmd)      free_pmd_slow(pmd)
-#define free_pte_fast(pte)      free_pte_slow(pte)
-
-#endif  /* CONFIG_NO_PGT_CACHE */
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-
-#define pte_free_kernel(pte)    free_pte_slow(pte)
-#define pte_free(pte)           free_pte_slow(pte)
-
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+static __inline__ void pte_free_slow(pte_t *pte)
 {
-        if (!pmd)
-                BUG();
-        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-        if (pmd_none(*pmd)) {
-                pte_t * page = (pte_t *) get_pte_fast();
-                if (!page)
-                        return get_pte_kernel_slow(pmd, address);
-		pmd_set_kernel(pmd, page);
-                return page + address;
-        }
-        if (pmd_bad(*pmd)) {
-                __handle_bad_pmd_kernel(pmd);
-                return NULL;
-        }
-        return (pte_t *) pmd_page(*pmd) + address;
+        free_page((unsigned long)pte);
 }
 
-extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
-{
-        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
-        if (pmd_none(*pmd))
-                goto getnew;
-        if (pmd_bad(*pmd))
-                goto fix;
-        return (pte_t *)pmd_page(*pmd) + address;
- getnew:
-	{
-		pte_t * page = (pte_t *) get_pte_fast();
-		if (!page)
-			return get_pte_slow(pmd, address);
-		pmd_set(pmd, page);
-		return page + address;
-	}
- fix:
-        __handle_bad_pmd(pmd);
-        return NULL;
-}
+#define pte_free(pte)      pte_free_slow(pte)
+#define pgd_free(pgd)      free_pgd_slow(pgd)
+#define pgd_alloc(mm)      get_pgd_fast()
 
 /*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
+ * We don't have any real pmd's, and this code never triggers because
+ * the pgd will always be present..
  */
 
-#define pmd_free(pmd)      free_pmd_slow(pmd)
-#define pmd_free_kernel    pmd_free
-#define pmd_alloc_kernel   pmd_alloc
-
-extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-        if (!pgd)
-                BUG();
-        return (pmd_t *) pgd;
-}
-
-/* pgd handling */
-
-#define pgd_free(pgd)      free_pgd_slow(pgd)
-#define pgd_alloc(mm)      get_pgd_fast()
+#define pmd_alloc_one_fast(mm, addr)    ({ BUG(); ((pmd_t *)1); })
+#define pmd_alloc_one(mm, addr)         ({ BUG(); ((pmd_t *)2); })
+#define pmd_free_slow(x)                do { } while (0)
+#define pmd_free_fast(x)                do { } while (0)
+#define pmd_free(x)                     do { } while (0)
+#define pgd_populate(mm, pmd, pte)      BUG()
 
 /* other stuff */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/pgtable.h linux/include/asm-cris/pgtable.h
--- v2.4.4/linux/include/asm-cris/pgtable.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/pgtable.h	Tue May  1 16:05:00 2001
@@ -3,6 +3,12 @@
  * HISTORY:
  *
  * $Log: pgtable.h,v $
+ * Revision 1.11  2001/04/04 14:38:36  bjornw
+ * Removed bad_pagetable handling and the _kernel functions
+ *
+ * Revision 1.10  2001/03/23 07:46:42  starvik
+ * Corrected according to review remarks
+ *
  * Revision 1.9  2000/11/22 14:57:53  bjornw
  * * extern inline -> static inline
  * * include asm-generic/pgtable.h
@@ -97,7 +103,9 @@
  * the CRIS page table tree.
  */
 
-/* The cache doesn't need to be flushed when TLB entries change (I think!) */
+/* The cache doesn't need to be flushed when TLB entries change because 
+ * the cache is mapped to physical memory, not virtual memory
+ */
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(mm, start, end)	do { } while (0)
@@ -244,27 +252,8 @@
 
 /* zero page used for uninitialized stuff */
 extern unsigned long empty_zero_page;
-
-/*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
-
-#define BAD_PAGETABLE    __bad_pagetable()
-#define BAD_PAGE         __bad_page()
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
-/*
- * Handling allocation failures during page table setup.
- */
-extern void __handle_bad_pmd(pmd_t * pmd);
-extern void __handle_bad_pmd_kernel(pmd_t * pmd);
-
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
 
@@ -452,9 +441,6 @@
 
 static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
 { pmd_val(*pmdp) = _PAGE_TABLE | (unsigned long) ptep; }
-
-static inline void pmd_set_kernel(pmd_t * pmdp, pte_t * ptep)
-{ pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep; }
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/processor.h linux/include/asm-cris/processor.h
--- v2.4.4/linux/include/asm-cris/processor.h	Fri Apr  6 10:51:19 2001
+++ linux/include/asm-cris/processor.h	Tue May  1 16:05:00 2001
@@ -18,7 +18,7 @@
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
  */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+#define current_text_addr() ({void *pc; __asm__ ("move.d pc,%0" : "=rm" (pc)); pc; })
 
 /* CRIS has no problems with write protection */
 
@@ -40,6 +40,14 @@
  */
 #define TASK_UNMAPPED_BASE      (TASK_SIZE / 3)
 
+/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
+ * normally, the stack is found by doing something like p + THREAD_SIZE
+ * in CRIS, a page is 8192 bytes, which seems like a sane size
+ */
+
+#define THREAD_SIZE       PAGE_SIZE
+#define KERNEL_STACK_SIZE PAGE_SIZE
+
 /* CRIS thread_struct. this really has nothing to do with the processor itself, since
  * CRIS does not do any hardware task-switching, but it's here for legacy reasons.
  * The thread_struct here is used when task-switching using _resume defined in entry.S.
@@ -50,13 +58,24 @@
 struct thread_struct {
 	unsigned long ksp;     /* kernel stack pointer */
 	unsigned long usp;     /* user stack pointer */
-	unsigned long esp0;    /* points to start of saved stack frame, set in entry.S */  
 	unsigned long dccr;    /* saved flag register */
 };
 
-/* saved stack-frame upon syscall entry, points to registers */
+/*
+ * At user->kernel entry, the pt_regs struct is stacked on the top of the kernel-stack.
+ * This macro allows us to find those regs for a task.
+ * Notice that subsequent pt_regs stackings, like recursive interrupts occuring while
+ * we're in the kernel, won't affect this - only the first user->kernel transition
+ * registers are reached by this.
+ */
 
-#define current_regs() (current->thread.esp0)
+#define user_regs(task) (((struct pt_regs *)((unsigned long)(task) + THREAD_SIZE)) - 1)
+
+/*
+ * Dito but for the currently running task
+ */
+
+#define current_regs() user_regs(current)
 
 /* INIT_MMAP is the kernels map of memory, between KSEG_C and KSEG_D */
 
@@ -69,11 +88,7 @@
 #endif
 
 #define INIT_THREAD  { \
-   0, 0, 0, 0x20 }  /* ccr = int enable, nothing else */
-
-/* TODO: REMOVE */
-#define alloc_kernel_stack()    __get_free_page(GFP_KERNEL)
-#define free_kernel_stack(page) free_page((page))
+   0, 0, 0x20 }  /* ccr = int enable, nothing else */
 
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
@@ -94,9 +109,10 @@
 #define KSTK_EIP(tsk)   \
     ({                  \
         unsigned long eip = 0;   \
-        if ((tsk)->thread.esp0 > PAGE_SIZE && \
-            VALID_PAGE(virt_to_page((tsk)->thread.esp0))) \
-              eip = ((struct pt_regs *) (tsk)->thread.esp0)->irp; \
+        unsigned long regs = (unsigned long)user_regs(tsk); \
+        if (regs > PAGE_SIZE && \
+            VALID_PAGE(virt_to_page(regs))) \
+              eip = ((struct pt_regs *)regs)->irp; \
         eip; })
 
 #define KSTK_ESP(tsk)   ((tsk) == current ? rdusp() : (tsk)->thread.usp)
@@ -111,11 +127,13 @@
 
 static inline void exit_thread(void)
 {
+        /* Nothing needs to be done.  */
 }
 
 /* Free all resources held by a thread. */
 static inline void release_thread(struct task_struct *dead_task)
 {
+        /* Nothing needs to be done.  */
 }
 
 /*
@@ -123,16 +141,8 @@
  */
 extern inline unsigned long thread_saved_pc(struct thread_struct *t)
 {
-	return (unsigned long)((struct pt_regs *)t->esp0)->irp;
+	return (unsigned long)user_regs(t)->irp;
 }
-
-/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
- * normally, the stack is found by doing something like p + THREAD_SIZE
- * in CRIS, a page is 8192 bytes, which seems like a sane size
- */
-
-#define THREAD_SIZE     PAGE_SIZE
-#define KERNEL_STACK_SIZE PAGE_SIZE
 
 #define alloc_task_struct()  ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)  free_pages((unsigned long) (p), 1)
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/ptrace.h linux/include/asm-cris/ptrace.h
--- v2.4.4/linux/include/asm-cris/ptrace.h	Fri Apr  6 10:51:19 2001
+++ linux/include/asm-cris/ptrace.h	Tue May  1 16:05:00 2001
@@ -23,14 +23,16 @@
 #define PT_DCCR      17
 #define PT_SRP       18
 #define PT_IRP       19
-#define PT_USP       20    /* special case - USP is not in the pt_regs */
-#define PT_MAX       20
+#define PT_CSRINSTR  20    /* CPU Status record remnants - valid if frametype == busfault */
+#define PT_CSRADDR   21
+#define PT_CSRDATA   22
+#define PT_USP       23    /* special case - USP is not in the pt_regs */
+#define PT_MAX       23
 
 /* Frame types */
 
-#define CRIS_FRAME_NORMAL   0  /* normal frame like pt_regs struct */
-#define CRIS_FRAME_BUSFAULT 1  /* SBFS frame of 4 longwords on top, including irp */
-#define CRIS_FRAME_FIXUP    2  /* SBFS frame which should do a normal return, not RBF */
+#define CRIS_FRAME_NORMAL   0  /* normal frame without SBFS stacking */
+#define CRIS_FRAME_BUSFAULT 1  /* frame stacked using SBFS, need RBF return path */
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
@@ -63,6 +65,9 @@
 	unsigned long dccr;
 	unsigned long srp;
 	unsigned long irp;
+	unsigned long csrinstr;
+	unsigned long csraddr;
+	unsigned long csrdata;
 };
 
 /* switch_stack is the extra stuff pushed onto the stack in _resume (entry.S) when
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/rtc.h linux/include/asm-cris/rtc.h
--- v2.4.4/linux/include/asm-cris/rtc.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/rtc.h	Tue May  1 16:05:00 2001
@@ -1,4 +1,4 @@
-/* $Id: rtc.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+/* $Id: rtc.h,v 1.3 2001/03/21 09:56:31 magnusmn Exp $ */
 
 #ifndef RTC_H
 #define RTC_H
@@ -14,8 +14,21 @@
 #define RTC_MONTH 4
 #define RTC_WEEKDAY 5
 #define RTC_YEAR 6
+#define RTC_CONTROL 7
 
-#ifdef CONFIG_DS1302
+/* Bits in CONTROL register */
+#define RTC_CONTROL_WRITEPROTECT 0x80
+#define RTC_TRICKLECHARGER 8
+/* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS */
+#define   RTC_TCR_PATTERN 0xA0 /* 1010xxxx */
+#define   RTC_TCR_1DIOD 0x04 /* xxxx01xx */
+#define   RTC_TCR_2DIOD 0x08 /* xxxx10xx */
+#define   RTC_TCR_DISABLED 0x00 /* xxxxxx00 Disabled */
+#define   RTC_TCR_2KOHM 0x01      /* xxxxxx01 2KOhm */
+#define   RTC_TCR_4KOHM 0x02      /* xxxxxx10 4kOhm */
+#define   RTC_TCR_8KOHM 0x03      /* xxxxxx11 8kOhm */
+
+#ifdef CONFIG_ETRAX_DS1302
 #define CMOS_READ(x) ds1302_readreg(x)
 #define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
 #define RTC_INIT() ds1302_init()
@@ -55,5 +68,8 @@
 
 #define RTC_RD_TIME	_IOR('p', 0x09, struct rtc_time) /* Read RTC time   */
 #define RTC_SET_TIME	_IOW('p', 0x0a, struct rtc_time) /* Set RTC time    */
+#define RTC_SET_CHARGE  _IOW('p', 0x0b, int) /* Set CHARGE mode    */
 
 #endif
+
+
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/segment.h linux/include/asm-cris/segment.h
--- v2.4.4/linux/include/asm-cris/segment.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/segment.h	Tue May  1 16:05:00 2001
@@ -1,14 +1,6 @@
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
-/* argh. really legacy. totally misnomed. */
-
-#define __KERNEL_CS	0x10
-#define __KERNEL_DS	0x18
-
-#define __USER_CS	0x23
-#define __USER_DS	0x2B
-
 typedef struct {
   unsigned long seg;
 } mm_segment_t;
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/semaphore-helper.h linux/include/asm-cris/semaphore-helper.h
--- v2.4.4/linux/include/asm-cris/semaphore-helper.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/semaphore-helper.h	Tue May  1 16:05:00 2001
@@ -1,4 +1,4 @@
-/* $Id: semaphore-helper.h,v 1.1 2000/07/13 16:52:42 bjornw Exp $
+/* $Id: semaphore-helper.h,v 1.3 2001/03/26 15:00:33 orjanf Exp $
  *
  * SMP- and interrupt-safe semaphores helper functions. Generic versions, no
  * optimizations whatsoever... 
@@ -10,6 +10,12 @@
 
 #include <asm/atomic.h>
 
+#define read(a) ((a)->counter)
+#define inc(a) (((a)->counter)++)
+#define dec(a) (((a)->counter)--)
+
+#define count_inc(a) ((*(a))++)
+
 /*
  * These two _must_ execute atomically wrt each other.
  */
@@ -17,12 +23,6 @@
 {
 	atomic_inc(&sem->waking);
 }
-
-#define read(a) ((a)->counter)
-#define inc(a) (((a)->counter)++)
-#define dec(a) (((a)->counter)--)
-
-#define count_inc(a) ((*(a))++)
 
 static inline int waking_non_zero(struct semaphore *sem)
 {
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/stat.h linux/include/asm-cris/stat.h
--- v2.4.4/linux/include/asm-cris/stat.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/stat.h	Tue May  1 16:05:00 2001
@@ -1,7 +1,8 @@
 #ifndef _CRIS_STAT_H
 #define _CRIS_STAT_H
 
-/* verbatim copy of i386 version */
+/* Keep this a verbatim copy of i386 version; tweak CRIS-specific bits in
+   the kernel if necessary.  */
 
 struct __old_kernel_stat {
 	unsigned short st_dev;
@@ -47,7 +48,9 @@
 	unsigned short	st_dev;
 	unsigned char	__pad0[10];
 
-	unsigned long	st_ino;
+#define STAT64_HAS_BROKEN_ST_INO	1
+	unsigned long	__st_ino;
+
 	unsigned int	st_mode;
 	unsigned int	st_nlink;
 
@@ -72,8 +75,7 @@
 	unsigned long	st_ctime;
 	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
 
-	unsigned long	__unused1;
-	unsigned long	__unused2;
+	unsigned long long	st_ino;
 };
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/system.h linux/include/asm-cris/system.h
--- v2.4.4/linux/include/asm-cris/system.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/system.h	Tue May  1 16:05:00 2001
@@ -1,14 +1,11 @@
-/* $Id: system.h,v 1.3 2000/10/17 14:56:27 bjornw Exp $ */
+/* $Id: system.h,v 1.4 2001/03/20 19:46:00 bjornw Exp $ */
 
 #ifndef __ASM_CRIS_SYSTEM_H
 #define __ASM_CRIS_SYSTEM_H
 
-#include <asm/segment.h>
-
-/* I need a task-specific debug struct (and the define for #ifdef
-   RELOC_DEBUG) to kludge into task_struct. */
 #include <linux/config.h>
-#include <asm/eshlibld.h>
+
+#include <asm/segment.h>
 
 /* the switch_to macro calls resume, an asm function in entry.S which does the actual
  * task switching.
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/timex.h linux/include/asm-cris/timex.h
--- v2.4.4/linux/include/asm-cris/timex.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/timex.h	Tue May  1 16:05:00 2001
@@ -6,7 +6,7 @@
 #ifndef _ASM_CRIS_TIMEX_H
 #define _ASM_CRIS_TIMEX_H
 
-#define CLOCK_TICK_RATE 9600 /* Underlying frequency of the HZ timer */
+#define CLOCK_TICK_RATE 19200 /* Underlying frequency of the HZ timer */
 
 /*
  * We don't have a cycle-counter.. but we do not support SMP anyway where this is
diff -u --recursive --new-file v2.4.4/linux/include/asm-cris/unistd.h linux/include/asm-cris/unistd.h
--- v2.4.4/linux/include/asm-cris/unistd.h	Fri Apr  6 10:51:19 2001
+++ linux/include/asm-cris/unistd.h	Tue May  1 16:05:00 2001
@@ -57,7 +57,7 @@
 #define __NR_geteuid		 49
 #define __NR_getegid		 50
 #define __NR_acct		 51
-#define __NR_phys		 52
+#define __NR_umount2		 52
 #define __NR_lock		 53
 #define __NR_ioctl		 54
 #define __NR_fcntl		 55
diff -u --recursive --new-file v2.4.4/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h
--- v2.4.4/linux/include/asm-i386/bitops.h	Fri Apr 27 15:48:19 2001
+++ linux/include/asm-i386/bitops.h	Thu May 24 15:20:18 2001
@@ -79,6 +79,23 @@
 #define smp_mb__after_clear_bit()	barrier()
 
 /**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike change_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static __inline__ void __change_bit(int nr, volatile void * addr)
+{
+	__asm__ __volatile__(
+		"btcl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
+
+/**
  * change_bit - Toggle a bit in memory
  * @nr: Bit to clear
  * @addr: Address to start counting from
@@ -170,6 +187,18 @@
 		"btrl %2,%1\n\tsbbl %0,%0"
 		:"=r" (oldbit),"=m" (ADDR)
 		:"Ir" (nr));
+	return oldbit;
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
+{
+	int oldbit;
+
+	__asm__ __volatile__(
+		"btcl %2,%1\n\tsbbl %0,%0"
+		:"=r" (oldbit),"=m" (ADDR)
+		:"Ir" (nr) : "memory");
 	return oldbit;
 }
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-i386/mtrr.h linux/include/asm-i386/mtrr.h
--- v2.4.4/linux/include/asm-i386/mtrr.h	Fri Apr 27 15:48:21 2001
+++ linux/include/asm-i386/mtrr.h	Tue May 22 11:17:36 2001
@@ -88,6 +88,7 @@
 		     unsigned int type, char increment);
 extern int mtrr_del (int reg, unsigned long base, unsigned long size);
 extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
+extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
 #  else
 static __inline__ int mtrr_add (unsigned long base, unsigned long size,
 				unsigned int type, char increment)
@@ -109,6 +110,9 @@
 {
     return -ENODEV;
 }
+
+static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
+
 #  endif
 
 /*  The following functions are for initialisation: don't use them!  */
diff -u --recursive --new-file v2.4.4/linux/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- v2.4.4/linux/include/asm-i386/pci.h	Fri Apr 27 15:49:20 2001
+++ linux/include/asm-i386/pci.h	Tue May 22 11:18:24 2001
@@ -9,8 +9,9 @@
 
 #define pcibios_assign_all_busses()	0
 
+extern unsigned long pci_mem_start;
 #define PCIBIOS_MIN_IO		0x1000
-#define PCIBIOS_MIN_MEM		0x10000000
+#define PCIBIOS_MIN_MEM		(pci_mem_start)
 
 void pcibios_set_master(struct pci_dev *dev);
 void pcibios_penalize_isa_irq(int irq);
@@ -171,6 +172,16 @@
  */
 #define sg_dma_address(sg)	(virt_to_bus((sg)->address))
 #define sg_dma_len(sg)		((sg)->length)
+
+/* Return the index of the PCI controller for device. */
+static inline int pci_controller_num(struct pci_dev *dev)
+{
+	return 0;
+}
+
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			       enum pci_mmap_state mmap_state, int write_combine);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.4.4/linux/include/asm-i386/system.h	Fri Apr 27 15:48:21 2001
+++ linux/include/asm-i386/system.h	Tue May 22 11:17:36 2001
@@ -288,7 +288,7 @@
 
 /* interrupt control.. */
 #define __save_flags(x)		__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
-#define __restore_flags(x) 	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#define __restore_flags(x) 	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
 #define __cli() 		__asm__ __volatile__("cli": : :"memory")
 #define __sti()			__asm__ __volatile__("sti": : :"memory")
 /* used in the idle loop; sti takes one instruction cycle to complete */
diff -u --recursive --new-file v2.4.4/linux/include/asm-i386/unaligned.h linux/include/asm-i386/unaligned.h
--- v2.4.4/linux/include/asm-i386/unaligned.h	Sun May 19 05:47:57 1996
+++ linux/include/asm-i386/unaligned.h	Tue May 22 10:23:16 2001
@@ -9,8 +9,29 @@
  * architectures where unaligned accesses aren't as simple.
  */
 
+/**
+ * get_unaligned - get value from possibly mis-aligned location
+ * @ptr: pointer to value
+ *
+ * This macro should be used for accessing values larger in size than 
+ * single bytes at locations that are expected to be improperly aligned, 
+ * e.g. retrieving a u16 value from a location not u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
 #define get_unaligned(ptr) (*(ptr))
 
+/**
+ * put_unaligned - put value to a possibly mis-aligned location
+ * @val: value to place
+ * @ptr: pointer to location
+ *
+ * This macro should be used for placing values larger in size than 
+ * single bytes at locations that are expected to be improperly aligned, 
+ * e.g. writing a u16 value to a location not u16-aligned.
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
 #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/asm-ia64/pci.h linux/include/asm-ia64/pci.h
--- v2.4.4/linux/include/asm-ia64/pci.h	Thu Jan  4 15:25:55 2001
+++ linux/include/asm-ia64/pci.h	Wed May 16 10:31:27 2001
@@ -57,6 +57,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #define sg_dma_len(sg)		((sg)->length)
 
 #endif /* _ASM_IA64_PCI_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-m68k/pci.h linux/include/asm-m68k/pci.h
--- v2.4.4/linux/include/asm-m68k/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-m68k/pci.h	Wed May 16 10:31:27 2001
@@ -45,4 +45,7 @@
 	/* We don't do dynamic PCI IRQ allocation */
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* _ASM_M68K_PCI_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- v2.4.4/linux/include/asm-mips/pci.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-mips/pci.h	Wed May 16 10:31:27 2001
@@ -201,6 +201,9 @@
 #endif
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 /*
  * These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
diff -u --recursive --new-file v2.4.4/linux/include/asm-mips64/pci.h linux/include/asm-mips64/pci.h
--- v2.4.4/linux/include/asm-mips64/pci.h	Tue Nov 28 21:42:04 2000
+++ linux/include/asm-mips64/pci.h	Wed May 16 10:31:27 2001
@@ -196,6 +196,9 @@
 #endif
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 /*
  * These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
diff -u --recursive --new-file v2.4.4/linux/include/asm-parisc/pci.h linux/include/asm-parisc/pci.h
--- v2.4.4/linux/include/asm-parisc/pci.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/pci.h	Wed May 16 10:31:27 2001
@@ -212,4 +212,7 @@
 #define PCIBIOS_MIN_IO          0x10
 #define PCIBIOS_MIN_MEM         0x1000 /* NBPG - but pci/setup-res.c dies */
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* __ASM_PARISC_PCI_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/8xx_immap.h linux/include/asm-ppc/8xx_immap.h
--- v2.4.4/linux/include/asm-ppc/8xx_immap.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/8xx_immap.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.8xx_immap.h 1.5 05/17/01 18:14:24 cort
+ */
 
 /*
  * MPC8xx Internal Memory Map
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/a.out.h linux/include/asm-ppc/a.out.h
--- v2.4.4/linux/include/asm-ppc/a.out.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/a.out.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.a.out.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifndef __PPC_A_OUT_H__
 #define __PPC_A_OUT_H__
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/amigahw.h linux/include/asm-ppc/amigahw.h
--- v2.4.4/linux/include/asm-ppc/amigahw.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/amigahw.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.amigahw.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef __ASMPPC_AMIGAHW_H
 #define __ASMPPC_AMIGAHW_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/amigaints.h linux/include/asm-ppc/amigaints.h
--- v2.4.4/linux/include/asm-ppc/amigaints.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/amigaints.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.amigaints.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
 ** amigaints.h -- Amiga Linux interrupt handling structs and prototypes
 **
 ** Copyright 1992 by Greg Harp
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/amigappc.h linux/include/asm-ppc/amigappc.h
--- v2.4.4/linux/include/asm-ppc/amigappc.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/amigappc.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.amigappc.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
 ** asm-m68k/amigappc.h -- This header defines some values and pointers for
 **                        the Phase 5 PowerUp card.
 **
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/amigayle.h linux/include/asm-ppc/amigayle.h
--- v2.4.4/linux/include/asm-ppc/amigayle.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/amigayle.h	Mon May 21 15:02:06 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.amigayle.h 1.5 05/17/01 18:14:24 cort
+ */
 #include <asm-m68k/amigayle.h>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/amipcmcia.h linux/include/asm-ppc/amipcmcia.h
--- v2.4.4/linux/include/asm-ppc/amipcmcia.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/amipcmcia.h	Mon May 21 15:02:06 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.amipcmcia.h 1.5 05/17/01 18:14:24 cort
+ */
 #include <asm-m68k/amipcmcia.h>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/atomic.h linux/include/asm-ppc/atomic.h
--- v2.4.4/linux/include/asm-ppc/atomic.h	Mon Oct  2 11:54:51 2000
+++ linux/include/asm-ppc/atomic.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.atomic.h 1.8 05/17/01 18:14:24 cort
+ */
+/*
  * PowerPC atomic operations
  */
 
@@ -85,5 +88,27 @@
 #define atomic_inc(v)			((void) atomic_inc_return((v)))
 #define atomic_dec(v)			((void) atomic_dec_return((v)))
 #define atomic_dec_and_test(v)		(atomic_dec_return((v)) == 0)
+
+/*
+ * Atomically test *v and decrement if it is greater than 0.
+ * The function returns the old value of *v minus 1.
+ */
+static __inline__ int atomic_dec_if_positive(atomic_t *v)
+{
+	int t;
+
+	__asm__ __volatile__("\n"
+"1:	lwarx	%0,0,%2\n"
+"	addic.	%0,%0,-1\n"
+"	blt	2f\n"
+"	stwcx.	%0,0,%2\n"
+"	bne	1b\n"
+"2:"
+	: "=&r" (t), "=m" (v->counter)
+	: "r" (&v->counter), "m" (v->counter)
+	: "cc");
+
+	return t;
+}
 
 #endif /* _ASM_PPC_ATOMIC_H_ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/backlight.h linux/include/asm-ppc/backlight.h
--- v2.4.4/linux/include/asm-ppc/backlight.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/backlight.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.backlight.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * Routines for handling backlight control on PowerBooks
  * 
  * For now, implementation resides in arch/ppc/kernel/pmac_support.c
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- v2.4.4/linux/include/asm-ppc/bitops.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/bitops.h	Mon May 21 15:02:06 2001
@@ -1,5 +1,7 @@
 /*
- * $Id: bitops.h,v 1.12 2000/02/09 03:28:31 davem Exp $
+ * BK Id: SCCS/s.bitops.h 1.7 05/17/01 18:14:24 cort
+ */
+/*
  * bitops.h: Bit string operations on the ppc
  */
 
@@ -35,10 +37,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 	
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	or	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	or	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=m" (*p)
 	: "r" (mask), "r" (p), "m" (*p)
@@ -68,10 +70,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	andc	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=m" (*p)
 	: "r" (mask), "r" (p), "m" (*p)
@@ -84,10 +86,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	xor	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	xor	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=m" (*p)
 	: "r" (mask), "r" (p), "m" (*p)
@@ -103,10 +105,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	or	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	or	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -135,10 +137,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	andc	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	andc	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -167,10 +169,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	xor	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	xor	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/board.h linux/include/asm-ppc/board.h
--- v2.4.4/linux/include/asm-ppc/board.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/board.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.board.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/bootinfo.h linux/include/asm-ppc/bootinfo.h
--- v2.4.4/linux/include/asm-ppc/bootinfo.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/bootinfo.h	Thu May 24 15:03:05 2001
@@ -1,11 +1,13 @@
 /*
+ * BK Id: SCCS/s.bootinfo.h 1.7 05/23/01 00:38:42 cort
+ */
+/*
  * Non-machine dependent bootinfo structure.  Basic idea
  * borrowed from the m68k.
  *
  * Copyright (C) 1999 Cort Dougan <cort@ppc.kernel.org>
  */
 
-
 #ifdef __KERNEL__
 #ifndef _PPC_BOOTINFO_H
 #define _PPC_BOOTINFO_H
@@ -32,6 +34,27 @@
 
 #endif /* CONFIG_APUS */
 
-#endif /* _PPC_BOOTINFO_H */
+/*
+ * prom_init() is called very early on, before the kernel text
+ * and data have been mapped to KERNELBASE.  At this point the code
+ * is running at whatever address it has been loaded at, so
+ * references to extern and static variables must be relocated
+ * explicitly.  The procedure reloc_offset() returns the address
+ * we're currently running at minus the address we were linked at.
+ * (Note that strings count as static variables.)
+ *
+ * Because OF may have mapped I/O devices into the area starting at
+ * KERNELBASE, particularly on CHRP machines, we can't safely call
+ * OF once the kernel has been mapped to KERNELBASE.  Therefore all
+ * OF calls should be done within prom_init(), and prom_init()
+ * and all routines called within it must be careful to relocate
+ * references as necessary.
+ */
+#define PTRRELOC(x)   ((typeof(x))((unsigned long)(x) + offset))
+#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) - offset))
+#define RELOC(x)      (*PTRRELOC(&(x)))
 
+#endif /* _PPC_BOOTINFO_H */
 #endif /* __KERNEL__ */
+
+
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/bootx.h linux/include/asm-ppc/bootx.h
--- v2.4.4/linux/include/asm-ppc/bootx.h	Sun Sep 17 09:48:08 2000
+++ linux/include/asm-ppc/bootx.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.bootx.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * This file describes the structure passed from the BootX application
  * (for MacOS) when it is used to boot Linux.
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/bseip.h linux/include/asm-ppc/bseip.h
--- v2.4.4/linux/include/asm-ppc/bseip.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/bseip.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.bseip.h 1.7 05/17/01 18:14:24 cort
+ */
 
 /*
  * A collection of structures, addresses, and values associated with
@@ -8,6 +11,7 @@
 #ifndef __MACH_BSEIP_DEFS
 #define __MACH_BSEIP_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -29,6 +33,7 @@
 #define IMAP_SIZE		((uint)(64 * 1024))
 #define PCMCIA_MEM_ADDR		((uint)0x04000000)
 #define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#endif	/* !__ASSEMBLY__ */
 
 /* We don't use the 8259.
 */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/bugs.h linux/include/asm-ppc/bugs.h
--- v2.4.4/linux/include/asm-ppc/bugs.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/bugs.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.bugs.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * This file is included by 'init/main.c'
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h
--- v2.4.4/linux/include/asm-ppc/byteorder.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/byteorder.h	Mon May 21 15:02:06 2001
@@ -1,9 +1,8 @@
-#ifndef _PPC_BYTEORDER_H
-#define _PPC_BYTEORDER_H
-
 /*
- *  $Id: byteorder.h,v 1.14 1998/08/12 05:07:12 paulus Exp $
+ * BK Id: SCCS/s.byteorder.h 1.5 05/17/01 18:14:24 cort
  */
+#ifndef _PPC_BYTEORDER_H
+#define _PPC_BYTEORDER_H
 
 #include <asm/types.h>
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/cache.h linux/include/asm-ppc/cache.h
--- v2.4.4/linux/include/asm-ppc/cache.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/cache.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.cache.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * include/asm-ppc/cache.h
  */
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/checksum.h linux/include/asm-ppc/checksum.h
--- v2.4.4/linux/include/asm-ppc/checksum.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/checksum.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.checksum.h 1.8 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_CHECKSUM_H
 #define _PPC_CHECKSUM_H
@@ -83,11 +86,11 @@
 						   unsigned short proto,
 						   unsigned int sum) 
 {
-    __asm__("
-	addc %0,%0,%1
-	adde %0,%0,%2
-	adde %0,%0,%3
-	addze %0,%0
+    __asm__("\n\
+	addc %0,%0,%1 \n\
+	adde %0,%0,%2 \n\
+	adde %0,%0,%3 \n\
+	addze %0,%0 \n\
 	"
 	: "=r" (sum)
 	: "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/cpm_8260.h linux/include/asm-ppc/cpm_8260.h
--- v2.4.4/linux/include/asm-ppc/cpm_8260.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/cpm_8260.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.cpm_8260.h 1.7 05/17/01 18:14:24 cort
+ */
 
 /*
  * MPC8260 Communication Processor Module.
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/current.h linux/include/asm-ppc/current.h
--- v2.4.4/linux/include/asm-ppc/current.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/current.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.current.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_CURRENT_H
 #define _PPC_CURRENT_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/dbdma.h linux/include/asm-ppc/dbdma.h
--- v2.4.4/linux/include/asm-ppc/dbdma.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/dbdma.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.dbdma.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * Definitions for using the Apple Descriptor-Based DMA controller
  * in Power Macintosh computers.
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/delay.h linux/include/asm-ppc/delay.h
--- v2.4.4/linux/include/asm-ppc/delay.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/delay.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.delay.h 1.7 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_DELAY_H
 #define _PPC_DELAY_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/div64.h linux/include/asm-ppc/div64.h
--- v2.4.4/linux/include/asm-ppc/div64.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/div64.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.div64.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifndef __PPC_DIV64
 #define __PPC_DIV64
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h
--- v2.4.4/linux/include/asm-ppc/dma.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/dma.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
-/* $Id: dma.h,v 1.3 1997/03/16 06:20:39 cort Exp $
+/*
+ * BK Id: SCCS/s.dma.h 1.8 05/17/01 18:14:24 cort
+ */
+/*
  * linux/include/asm/dma.h: Defines for using and allocating dma channels.
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h
--- v2.4.4/linux/include/asm-ppc/elf.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/elf.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.elf.h 1.10 05/17/01 18:14:24 cort
+ */
 #ifndef __PPC_ELF_H
 #define __PPC_ELF_H
 
@@ -74,20 +77,39 @@
  * We need to put in some extra aux table entries to tell glibc what
  * the cache block size is, so it can use the dcbz instruction safely.
  */
-#define AT_DCACHEBSIZE		17
-#define AT_ICACHEBSIZE		18
-#define AT_UCACHEBSIZE		19
+#define AT_DCACHEBSIZE		19
+#define AT_ICACHEBSIZE		20
+#define AT_UCACHEBSIZE		21
+/* A special ignored type value for PPC, for glibc compatibility.  */
+#define AT_IGNOREPPC		22
 
 extern int dcache_bsize;
 extern int icache_bsize;
 extern int ucache_bsize;
 
-#define DLINFO_EXTRA_ITEMS	3
-#define EXTRA_DLINFO		do {			\
-	NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize);	\
-	NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize);	\
-	NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize);	\
-} while (0)
+/*
+ * The requirements here are:
+ * - keep the final alignment of sp (sp & 0xf)
+ * - make sure the 32-bit value at the first 16 byte aligned position of
+ *   AUXV is greater than 16 for glibc compatibility.
+ *   AT_IGNOREPPC is used for that.
+ * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+ *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+ */
+#define DLINFO_ARCH_ITEMS	3
+#define ARCH_DLINFO							\
+do {									\
+	sp -= DLINFO_ARCH_ITEMS * 2;					\
+	NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize);			\
+	NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize);			\
+	NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize);			\
+	/*								\
+	 * Now handle glibc compatibility.				\
+	 */								\
+	sp -= 2*2;							\
+	NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC);			\
+	NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC);			\
+ } while (0)
 
 #endif /* __KERNEL__ */
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/errno.h linux/include/asm-ppc/errno.h
--- v2.4.4/linux/include/asm-ppc/errno.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/errno.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.errno.h 1.7 05/17/01 18:14:24 cort
+ */
 #ifndef _PPC_ERRNO_H
 #define _PPC_ERRNO_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/est8260.h linux/include/asm-ppc/est8260.h
--- v2.4.4/linux/include/asm-ppc/est8260.h	Mon Jun 19 17:59:37 2000
+++ linux/include/asm-ppc/est8260.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.est8260.h 1.5 05/17/01 18:14:24 cort
+ */
 
 /* Board information for the EST8260, which should be generic for
  * all 8260 boards.  The IMMR is now given to us so the hard define
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/fads.h linux/include/asm-ppc/fads.h
--- v2.4.4/linux/include/asm-ppc/fads.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/fads.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.fads.h 1.8 05/17/01 18:14:24 cort
+ */
 
 /*
  * A collection of structures, addresses, and values associated with
@@ -8,6 +11,7 @@
 #ifndef __MACH_FADS_DEFS
 #define __MACH_FADS_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -16,24 +20,54 @@
 	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
 	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
 	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
 } bd_t;
 
 extern bd_t m8xx_board_info;
 
 /* Memory map is configured by the PROM startup.
  * I tried to follow the FADS manual, although the startup PROM
- * dictates this.
+ * dictates this and we simply have to move some of the physical
+ * addresses for Linux.
  */
-#define BCSR_ADDR		((uint)0x02100000)
+#define BCSR_ADDR		((uint)0xfe000000)
 #define BCSR_SIZE		((uint)(64 * 1024))
-#define	BCSR0			((uint)0x02100000)
-#define	BCSR1			((uint)0x02100004)
-#define	BCSR2			((uint)0x02100008)
-#define	BCSR3			((uint)0x0210000c)
-#define	BCSR4			((uint)0x02100010)
-#define IMAP_ADDR		((uint)0x02200000)
+#define	BCSR0			((uint)0xfe000000)
+#define	BCSR1			((uint)0xfe000004)
+#define	BCSR2			((uint)0xfe000008)
+#define	BCSR3			((uint)0xfe00000c)
+#define	BCSR4			((uint)0xfe000010)
+#define IMAP_ADDR		((uint)0xf0000000)
 #define IMAP_SIZE		((uint)(64 * 1024))
 #define PCMCIA_MEM_ADDR		((uint)0x04000000)
 #define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+ 
+/* Bits of interest in the BCSRs.
+ */
+#define BCSR1_ETHEN		((uint)0x20000000)
+#define BCSR1_RS232EN_1		((uint)0x01000000)
+#define BCSR1_RS232EN_2		((uint)0x00040000)
+#define BCSR4_ETHLOOP		((uint)0x80000000)	/* EEST Loopback */
+#define BCSR4_EEFDX		((uint)0x40000000)	/* EEST FDX enable */
+#define BCSR4_FETH_EN		((uint)0x08000000)	/* PHY enable */
+#define BCSR4_FETHCFG0		((uint)0x04000000)	/* PHY autoneg mode */
+#define BCSR4_FETHCFG1		((uint)0x00400000)	/* PHY autoneg mode */
+#define BCSR4_FETHFDE		((uint)0x02000000)	/* PHY FDX advertise */
+#define BCSR4_FETHRST		((uint)0x00200000)	/* PHY Reset */
+#endif /* !__ASSEMBLY__ */
+ 
+/* Interrupt level assignments.
+ */
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+#define PHY_INTERRUPT	SIU_IRQ2	/* PHY link change interrupt */
+
+/* We don't use the 8259.
+ */
+#define NR_8259_INTS	0
+ 
+/* Machine type
+ */
+#define _MACH_8xx (_MACH_fads)
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/fcntl.h linux/include/asm-ppc/fcntl.h
--- v2.4.4/linux/include/asm-ppc/fcntl.h	Fri Sep 22 14:21:20 2000
+++ linux/include/asm-ppc/fcntl.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.fcntl.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifndef _PPC_FCNTL_H
 #define _PPC_FCNTL_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/feature.h linux/include/asm-ppc/feature.h
--- v2.4.4/linux/include/asm-ppc/feature.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/feature.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.feature.h 1.9 05/17/01 18:14:24 cort
+ */
+/*
  * Definitions for accessing the Feature Control Register (FCR)
  * on Power Macintoshes and similar machines.  The FCR lets us
  * enable/disable, reset, and power up/down various peripherals.
@@ -75,25 +78,32 @@
 
 
 /*
- * Additional functions related to Core99 machines
+ * Additional functions related to Core99 machines. We should extend the
+ * feature mecanism to make those fit into it. For now, they are still
+ * separate functions.
  */
 extern void	feature_set_gmac_power(struct device_node* device, int power);
 
 	/* use constants in KeyLargo.h for the reset parameter */
-extern void	feature_set_gmac_phy_reset(struct device_node* device, int reset);
+extern void	feature_gmac_phy_reset(struct device_node* device);
 
 extern void	feature_set_usb_power(struct device_node* device, int power);
 
 extern void 	feature_set_firewire_power(struct device_node* device, int power);
+extern void 	feature_set_firewire_cable_power(struct device_node* device, int power);
 
-extern void	feature_core99_kick_cpu1(void);
+extern void	feature_set_airport_power(struct device_node* device, int power);
+
+extern void	feature_core99_kick_cpu(int cpu_nr);
 
 /*
- * Sleep related functions. At term, they should be high-priority notifiers
+ * Sleep related functions. At term, they should be high-priority notifiers,
+ * but this would require some changes to the current sleep scheme that won't
+ * be done in 2.4.
  */
 extern void	feature_prepare_for_sleep(void);
-
 extern void	feature_wake_up(void);
+extern int	feature_can_sleep(void);
 
 #endif /* __ASM_PPC_FEATURE_H */
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/floppy.h linux/include/asm-ppc/floppy.h
--- v2.4.4/linux/include/asm-ppc/floppy.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/floppy.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.floppy.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * Architecture specific parts of the Floppy driver
  *
  * This file is subject to the terms and conditions of the GNU General Public
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/gemini.h linux/include/asm-ppc/gemini.h
--- v2.4.4/linux/include/asm-ppc/gemini.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/gemini.h	Mon May 21 15:02:06 2001
@@ -0,0 +1,171 @@
+/*
+ * BK Id: SCCS/s.gemini.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
+ *  include/asm-ppc/gemini.h
+ *
+ *
+ *  Onboard registers and descriptions for Synergy Microsystems' 
+ *  "Gemini" boards.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/*  Registers  */
+
+#define GEMINI_SERIAL_B     (0xffeffb00)
+#define GEMINI_SERIAL_A     (0xffeffb08)
+#define GEMINI_USWITCH      (0xffeffd00)
+#define GEMINI_BREV         (0xffeffe00)
+#define GEMINI_BECO         (0xffeffe08)
+#define GEMINI_FEAT         (0xffeffe10)
+#define GEMINI_BSTAT        (0xffeffe18)
+#define GEMINI_CPUSTAT      (0xffeffe20)
+#define GEMINI_L2CFG        (0xffeffe30)
+#define GEMINI_MEMCFG       (0xffeffe38)
+#define GEMINI_FLROM        (0xffeffe40)
+#define GEMINI_P0PCI        (0xffeffe48)
+#define GEMINI_FLWIN        (0xffeffe50)
+#define GEMINI_P0INTMASK    (0xffeffe60)
+#define GEMINI_P0INTAP      (0xffeffe68)
+#define GEMINI_PCIERR       (0xffeffe70)
+#define GEMINI_LEDBASE      (0xffeffe80)
+#define GEMINI_RTC          (0xffe9fff8)
+#define GEMINI_LEDS         8
+#define GEMINI_SWITCHES     8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN      (1<<0)
+#define GEMINI_FLS_JMP      (1<<6)
+#define GEMINI_FLS_BOOT     (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK  0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN     (1<<0)
+#define GEMINI_TIMEB1_EN     (1<<1)
+#define GEMINI_TIMEB2_EN     (1<<2)
+#define GEMINI_TIMEB3_EN     (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK   0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED   (1<<4)
+#define GEMINI_CPU1_HALTED   (1<<5)
+#define GEMINI_CPU2_HALTED   (1<<6)
+#define GEMINI_CPU3_HALTED   (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL      (1<<0)   /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK  0x0c     /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH   (1<<1)
+#define GEMINI_FEAT_HAS_SCSI  (1<<2)
+#define GEMINI_FEAT_HAS_P0    (1<<3)
+#define GEMINI_FEAT_FAM_MASK  0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK       0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK       0x0f
+#define GEMINI_TYPE_MASK      0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE    1     /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7    /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL  0
+#define SGS_RTC_SECONDS  1
+#define SGS_RTC_MINUTES  2
+#define SGS_RTC_HOURS    3
+#define SGS_RTC_DAY      4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH    6
+#define SGS_RTC_YEAR     7
+
+#define SGS_RTC_SET  0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR  (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR  (0xfee00000)
+
+#define GEMINI_BOOT_INIT  (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync "
+  : /* no output */
+  : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+    "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+  unsigned long val;
+
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync "
+  : "=r" (val)
+  : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+    "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+  return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+  int val = 0;
+  if (led >= 0 && led < GEMINI_LEDS)
+    val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+  return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+  unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+  return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_prom_init(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
+#endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/gemini_serial.h linux/include/asm-ppc/gemini_serial.h
--- v2.4.4/linux/include/asm-ppc/gemini_serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/gemini_serial.h	Mon May 21 15:02:06 2001
@@ -0,0 +1,44 @@
+/*
+ * BK Id: SCCS/s.gemini_serial.h 1.5 05/17/01 18:14:24 cort
+ */
+#ifdef __KERNEL__
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <linux/config.h>
+#include <asm/gemini.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+        { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DEFNS \
+        PU32_SERIAL_PORT_DEFNS
+
+#endif
+#endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/gg2.h linux/include/asm-ppc/gg2.h
--- v2.4.4/linux/include/asm-ppc/gg2.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/gg2.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.gg2.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  *  asm-ppc/gg2.h -- VLSI VAS96011/12 `Golden Gate 2' register definitions
  *
  *  Copyright (C) 1997 Geert Uytterhoeven
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/hardirq.h linux/include/asm-ppc/hardirq.h
--- v2.4.4/linux/include/asm-ppc/hardirq.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/hardirq.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.hardirq.h 1.7 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/hdreg.h linux/include/asm-ppc/hdreg.h
--- v2.4.4/linux/include/asm-ppc/hdreg.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/hdreg.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.hdreg.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  *  linux/include/asm-ppc/hdreg.h
  *
  *  Copyright (C) 1994-1996  Linus Torvalds & authors
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/heathrow.h linux/include/asm-ppc/heathrow.h
--- v2.4.4/linux/include/asm-ppc/heathrow.h	Sun Sep 17 09:48:08 2000
+++ linux/include/asm-ppc/heathrow.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.heathrow.h 1.7 05/17/01 18:14:24 cort
+ */
+/*
  * heathrow.h: definitions for using the "Heathrow" I/O controller chip.
  *
  * Grabbed from Open Firmware definitions on a PowerBook G3 Series
@@ -6,14 +9,21 @@
  * Copyright (C) 1997 Paul Mackerras.
  */
 
+/* Front light color on Yikes/B&W G3. 32 bits */
+#define HEATHROW_FRONT_LIGHT		0x32 /* (set to 0 or 0xffffffff) */
+
+/* Brightness/contrast (gossamer iMac ?). 8 bits */
+#define HEATHROW_BRIGHTNESS_CNTL	0x32
+#define HEATHROW_CONTRAST_CNTL		0x33
+
 /* offset from ohare base for feature control register */
-#define HEATHROW_FEATURE_REG	0x38
+#define HEATHROW_FEATURE_REG		0x38
 
 /*
  * Bits in feature control register.
  * Bits postfixed with a _N are in inverse logic
  */
-#define HRW_RESET_SCC		0x00000001	/* Named in_use_led in OF ??? */
+#define HRW_RESET_SCC		0x00000001	/* actually controls transceiver... */
 #define HRW_BAY_POWER_N		0x00000002
 #define HRW_BAY_PCI_ENABLE	0x00000004
 #define HRW_BAY_IDE_ENABLE	0x00000008
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/highmem.h linux/include/asm-ppc/highmem.h
--- v2.4.4/linux/include/asm-ppc/highmem.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/highmem.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.highmem.h 1.7 05/17/01 18:14:24 cort
+ */
+/*
  * highmem.h: virtual kernel memory mappings for high memory
  *
  * PowerPC version, stolen from the i386 version.
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/hw_irq.h linux/include/asm-ppc/hw_irq.h
--- v2.4.4/linux/include/asm-ppc/hw_irq.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/hw_irq.h	Mon May 21 15:02:06 2001
@@ -1,37 +1,25 @@
 /*
- * $Id: irq_control.h,v 1.8 1999/09/15 23:58:48 cort Exp $
- *
+ * BK Id: SCCS/s.hw_irq.h 1.10 05/17/01 18:14:24 cort
+ */
+/*
  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
  */
 #ifdef __KERNEL__
 #ifndef _PPC_HW_IRQ_H
 #define _PPC_HW_IRQ_H
 
-struct int_control_struct
-{
-	void (*int_cli)(void);
-	void (*int_sti)(void);
-	void (*int_restore_flags)(unsigned long);
-	void (*int_save_flags)(unsigned long *);
-	void (*int_set_lost)(unsigned long);
-};
-extern struct int_control_struct int_control;
 extern unsigned long timer_interrupt_intercept;
 extern unsigned long do_IRQ_intercept;
 int timer_interrupt(struct pt_regs *);
 
-extern void __no_use_sti(void);
-extern void __no_use_cli(void);
-extern void __no_use_restore_flags(unsigned long);
-extern void __no_use_save_flags(unsigned long *);
-extern void __no_use_set_lost(unsigned long);
+extern void __sti(void);
+extern void __cli(void);
+extern void __restore_flags(unsigned long);
+extern void __save_flags_ptr(unsigned long *);
+extern unsigned long __sti_end, __cli_end, __restore_flags_end, __save_flags_ptr_end;
 
-#define __cli() int_control.int_cli()
-#define __sti() int_control.int_sti()
-#define __save_flags(flags) int_control.int_save_flags((unsigned long *)&flags)
-#define __restore_flags(flags) int_control.int_restore_flags((unsigned long)flags)
+#define __save_flags(flags) __save_flags_ptr((unsigned long *)&flags)
 #define __save_and_cli(flags) ({__save_flags(flags);__cli();})
-#define __set_lost(irq) ({ if ((unsigned long)int_control.int_set_lost) int_control.int_set_lost(irq); })
 
 extern void do_lost_interrupts(unsigned long);
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/hydra.h linux/include/asm-ppc/hydra.h
--- v2.4.4/linux/include/asm-ppc/hydra.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/hydra.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.hydra.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  *  asm-ppc/hydra.h -- Mac I/O `Hydra' definitions
  *
  *  Copyright (C) 1997 Geert Uytterhoeven
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.4.4/linux/include/asm-ppc/ide.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/ide.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ide.h 1.10 05/17/01 18:14:24 cort
+ */
+/*
  *  linux/include/asm-ppc/ide.h
  *
  *  Copyright (C) 1994-1996 Linus Torvalds & authors */
@@ -16,7 +19,7 @@
 #include <asm/processor.h>
 
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	4
+#define MAX_HWIFS	8
 #endif
 
 #include <asm/hdreg.h>
@@ -159,8 +162,13 @@
 	} b;
 } select_t;
 
+#if !defined(ide_request_irq)
 #define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#endif
+
+#if !defined(ide_free_irq)
 #define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#endif
 
 /*
  * The following are not needed for the non-m68k ports
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/immap_8260.h linux/include/asm-ppc/immap_8260.h
--- v2.4.4/linux/include/asm-ppc/immap_8260.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/immap_8260.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.immap_8260.h 1.5 05/17/01 18:14:24 cort
+ */
 
 /*
  * MPC8260 Internal Memory Map
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/init.h linux/include/asm-ppc/init.h
--- v2.4.4/linux/include/asm-ppc/init.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/init.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.init.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_INIT_H
 #define _PPC_INIT_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.4.4/linux/include/asm-ppc/io.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/io.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.io.h 1.7 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_IO_H
 #define _PPC_IO_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ioctl.h linux/include/asm-ppc/ioctl.h
--- v2.4.4/linux/include/asm-ppc/ioctl.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/ioctl.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ioctl.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifndef _PPC_IOCTL_H
 #define _PPC_IOCTL_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ioctls.h linux/include/asm-ppc/ioctls.h
--- v2.4.4/linux/include/asm-ppc/ioctls.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/ioctls.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ioctls.h 1.7 05/17/01 18:14:24 cort
+ */
 #ifndef _ASM_PPC_IOCTLS_H
 #define _ASM_PPC_IOCTLS_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ipc.h linux/include/asm-ppc/ipc.h
--- v2.4.4/linux/include/asm-ppc/ipc.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/ipc.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ipc.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifndef __PPC_IPC_H__
 #define __PPC_IPC_H__
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ipcbuf.h linux/include/asm-ppc/ipcbuf.h
--- v2.4.4/linux/include/asm-ppc/ipcbuf.h	Sat Nov 11 18:19:56 2000
+++ linux/include/asm-ppc/ipcbuf.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ipcbuf.h 1.5 05/17/01 18:14:24 cort
+ */
 #ifndef __PPC_IPCBUF_H__
 #define __PPC_IPCBUF_H__
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.4.4/linux/include/asm-ppc/irq.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/irq.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.irq.h 1.9 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ivms8.h linux/include/asm-ppc/ivms8.h
--- v2.4.4/linux/include/asm-ppc/ivms8.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/ivms8.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ivms8.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * A collection of structures, addresses, and values associated with
  * Speech Design Integrated Voicemail Systems (IVMS8) boards.
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/keyboard.h linux/include/asm-ppc/keyboard.h
--- v2.4.4/linux/include/asm-ppc/keyboard.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/keyboard.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.keyboard.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  *  linux/include/asm-ppc/keyboard.h
  *
  *  Created 3 Nov 1996 by Geert Uytterhoeven
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/keylargo.h linux/include/asm-ppc/keylargo.h
--- v2.4.4/linux/include/asm-ppc/keylargo.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/keylargo.h	Mon May 21 15:02:06 2001
@@ -1,8 +1,17 @@
 /*
+ * BK Id: SCCS/s.keylargo.h 1.9 05/17/01 18:14:24 cort
+ */
+/*
  * keylargo.h: definitions for using the "KeyLargo" I/O controller chip.
  *
  */
 
+/* "Pangea" chipset has keylargo device-id 0x25 while core99
+ * has device-id 0x22. The rev. of the pangea one is 0, so we
+ * fake an artificial rev. in keylargo_rev by oring 0x100
+ */
+#define KL_PANGEA_REV		0x100
+
 /* offset from base for feature control registers */
 #define KEYLARGO_MBCR		0x34	/* Media bay control/status */
 #define KEYLARGO_FCR0		0x38
@@ -18,25 +27,47 @@
 #define KEYLARGO_GPIO_EXTINT_CNT	18
 #define KEYLARGO_GPIO_0			0x6A
 #define KEYLARGO_GPIO_CNT		17
+#define KEYLARGO_GPIO_OUTPUT_ENABLE	0x04
+#define KEYLARGO_GPIO_OUTOUT_DATA	0x01
 
 /* Specific GPIO regs */
 
+#define KL_GPIO_MODEM_RESET		(KEYLARGO_GPIO_0+0x03) /* Pangea */
+#define KL_GPIO_MODEM_POWER		(KEYLARGO_GPIO_0+0x02) /* Pangea */
+
+#define KL_GPIO_FW_CABLE_POWER		(KEYLARGO_GPIO_0+0x09)
+
 #define KL_GPIO_ETH_PHY_RESET		(KEYLARGO_GPIO_0+0x10)
-#define KL_GPIO_ETH_PHY_RESET_ASSERT	0x04
-#define KL_GPIO_ETH_PHY_RESET_RELEASE	0x05
-#define KL_GPIO_ETH_PHY_RESET_TRISTATE	0x00
-
-#define KL_GPIO_KICK_CPU1		(KEYLARGO_GPIO_0+0x0a)
-#define KL_GPIO_KICK_CPU1_UP		0x04
-#define KL_GPIO_KICK_CPU1_DOWN		0x38
+
+#define KL_GPIO_EXTINT_CPU1		(KEYLARGO_GPIO_0+0x0a)
+#define KL_GPIO_EXTINT_CPU1_ASSERT	0x04
+#define KL_GPIO_EXTINT_CPU1_RELEASE	0x38
+
+#define KL_GPIO_RESET_CPU0		(KEYLARGO_GPIO_EXTINT_0+0x03)
+#define KL_GPIO_RESET_CPU1		(KEYLARGO_GPIO_EXTINT_0+0x04)
+#define KL_GPIO_RESET_CPU2		(KEYLARGO_GPIO_EXTINT_0+0x0f)
+#define KL_GPIO_RESET_CPU3		(KEYLARGO_GPIO_EXTINT_0+0x10)
 
 #define KL_GPIO_PMU_MESSAGE_IRQ		(KEYLARGO_GPIO_EXTINT_0+0x09)
 #define KL_GPIO_PMU_MESSAGE_BIT		0x02
 
+#define KL_GPIO_AIRPORT_0		(KEYLARGO_GPIO_EXTINT_0+0x0a)
+#define KL_GPIO_AIRPORT_1		(KEYLARGO_GPIO_EXTINT_0+0x0d)
+#define KL_GPIO_AIRPORT_2		(KEYLARGO_GPIO_0+0x0d)
+#define KL_GPIO_AIRPORT_3		(KEYLARGO_GPIO_0+0x0e)
+#define KL_GPIO_AIRPORT_4		(KEYLARGO_GPIO_0+0x0f)
+
 /*
  * Bits in feature control register
  */
-#define KL_MBCR_MBDEV_ENABLE		0x00001000
+#define KL_MBCR_MB0_DEV_ENABLE		0x00001000
+#define KL_MBCR_MB0_DEV_POWER		0x00000400
+#define KL_MBCR_MB0_DEV_RESET		0x00000200
+#define KL_MBCR_MB0_ENABLE		0x00000100
+#define KL_MBCR_MB1_DEV_ENABLE		0x10000000
+#define KL_MBCR_MB1_DEV_POWER		0x04000000
+#define KL_MBCR_MB1_DEV_RESET		0x02000000
+#define KL_MBCR_MB1_ENABLE		0x01000000
 
 #define KL0_SCC_B_INTF_ENABLE		0x00000001	/* ??? */
 #define KL0_SCC_A_INTF_ENABLE		0x00000002	/* ??? */
@@ -45,16 +76,27 @@
 #define KL0_SCCA_ENABLE			0x00000010
 #define KL0_SCCB_ENABLE			0x00000020
 #define KL0_SCC_CELL_ENABLE		0x00000040
-#define KL0_IRDA_ENABLE			0x00008000
-#define KL0_IRDA_CLK32_ENABLE		0x00010000
-#define KL0_IRDA_CLK19_ENABLE		0x00020000
 #define KL0_USB0_PAD_SUSPEND0		0x00040000
 #define KL0_USB0_PAD_SUSPEND1		0x00080000
 #define KL0_USB0_CELL_ENABLE		0x00100000
 #define KL0_USB1_PAD_SUSPEND0		0x00400000
 #define KL0_USB1_PAD_SUSPEND1		0x00800000
 #define KL0_USB1_CELL_ENABLE		0x01000000
+/* KL id 0x22 only */
 #define KL0_USB_REF_SUSPEND		0x10000000
+#define KL0_IRDA_ENABLE			0x00008000
+#define KL0_IRDA_CLK32_ENABLE		0x00010000
+#define KL0_IRDA_CLK19_ENABLE		0x00020000
+/* KL id 0x25 (pangea) only */
+#define KL0_USB1_PAD_SUSPEND_SEL	0x00020000
+#define KL0_USB1_REF_SUSPEND		0x00010000
+#define KL0_USB1_REF_SUSPEND_SEL	0x00008000
+#define KL0_USB1_PMI			0x00004000
+#define KL0_USB0_PAD_SUSPEND_SEL	0x00002000
+#define KL0_USB0_REF_SUSPEND		0x00001000
+#define KL0_USB0_REF_SUSPEND_SEL	0x00000800
+#define KL0_USB0_PMI			0x00000400
+
 
 #define KL0_SERIAL_ENABLE		(KL0_SCC_B_INTF_ENABLE | \
 					KL0_SCC_SLOWPCLK | \
@@ -102,11 +144,11 @@
 #define KL3_STOPPING33_ENABLED		0x00080000
 
 /* Port 0,1 : bus 0, port 2,3 : bus 1 */
-#define KL4_SET_PORT_ENABLE(p)		(0x00000008 << (p<<3))
-#define KL4_SET_PORT_RESUME(p)		(0x00000004 << (p<<3))
-#define KL4_SET_PORT_CONNECT(p)		(0x00000002 << (p<<3))
-#define KL4_SET_PORT_DISCONNECT(p)	(0x00000001 << (p<<3))
-#define KL4_GET_PORT_RESUME(p)		(0x00000040 << (p<<3))
-#define KL4_GET_PORT_CONNECT(p)		(0x00000020 << (p<<3))
-#define KL4_GET_PORT_DISCONNECT(p)	(0x00000010 << (p<<3))
+#define KL4_SET_PORT_ENABLE(p)		(0x00000008 << ((p)<<3))
+#define KL4_SET_PORT_RESUME(p)		(0x00000004 << ((p)<<3))
+#define KL4_SET_PORT_CONNECT(p)		(0x00000002 << ((p)<<3))
+#define KL4_SET_PORT_DISCONNECT(p)	(0x00000001 << ((p)<<3))
+#define KL4_GET_PORT_RESUME(p)		(0x00000040 << ((p)<<3))
+#define KL4_GET_PORT_CONNECT(p)		(0x00000020 << ((p)<<3))
+#define KL4_GET_PORT_DISCONNECT(p)	(0x00000010 << ((p)<<3))
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/kgdb.h linux/include/asm-ppc/kgdb.h
--- v2.4.4/linux/include/asm-ppc/kgdb.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/kgdb.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
-/* $Id: kgdb.h,v 1.2 1998/04/11 17:29:07 geert Exp $
+/*
+ * BK Id: SCCS/s.kgdb.h 1.5 05/17/01 18:14:24 cort
+ */
+/*
  * kgdb.h: Defines and declarations for serial line source level
  *         remote debugging of the Linux kernel using gdb.
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/kmap_types.h linux/include/asm-ppc/kmap_types.h
--- v2.4.4/linux/include/asm-ppc/kmap_types.h	Thu Apr 12 12:11:39 2001
+++ linux/include/asm-ppc/kmap_types.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.kmap_types.h 1.6 05/17/01 18:14:24 cort
+ */
 #ifdef __KERNEL__
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h
--- v2.4.4/linux/include/asm-ppc/linux_logo.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/linux_logo.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.linux_logo.h 1.7 05/17/01 18:14:24 cort
+ */
+/*
  * include/asm-ppc/linux_logo.h: A linux logo to be displayed on boot
  * (pinched from the sparc port).
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/m48t35.h linux/include/asm-ppc/m48t35.h
--- v2.4.4/linux/include/asm-ppc/m48t35.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/m48t35.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.m48t35.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  *  Registers for the SGS-Thomson M48T35 Timekeeper RAM chip
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- v2.4.4/linux/include/asm-ppc/machdep.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/machdep.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.machdep.h 1.11 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_MACHDEP_H
 #define _PPC_MACHDEP_H
@@ -22,7 +25,6 @@
 	unsigned int	(*irq_cannonicalize)(unsigned int irq);
 	void		(*init_IRQ)(void);
 	int		(*get_irq)(struct pt_regs *);
-	void		(*post_irq)( struct pt_regs *, int );
 	
 	/* A general init function, called by ppc_init in init/main.c.
 	   May be NULL. */
@@ -41,6 +43,7 @@
 	unsigned long	heartbeat_reset;
 	unsigned long	heartbeat_count;
 
+	unsigned long	(*find_end_of_memory)(void);
   	void		(*progress)(char *, unsigned short);
 
 	unsigned char 	(*nvram_read_val)(int addr);
@@ -79,6 +82,11 @@
 		 * Returns 0 to allow assignement/enabling of the device
 		 */
 	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
+
+		/* Called at then very end of pcibios_init()
+		 */
+	void (*pcibios_after_init)(void);
+		 
 
 	/* this is for modules, since _machine can be a define -- Cort */
 	int ppc_machine;
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mbx.h linux/include/asm-ppc/mbx.h
--- v2.4.4/linux/include/asm-ppc/mbx.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/mbx.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mbx.h 1.8 05/17/01 18:14:25 cort
+ */
+/*
  * A collection of structures, addresses, and values associated with
  * the Motorola MBX boards.  This was originally created for the
  * MBX860, and probably needs revisions for other boards (like the 821).
@@ -11,6 +14,7 @@
 #ifndef __MACH_MBX_DEFS
 #define __MACH_MBX_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * EPPC-Bug starts it up.
  */
@@ -25,7 +29,13 @@
 	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
 	unsigned int	bi_clun;	/* Boot device controller */
 	unsigned int	bi_dlun;	/* Boot device logical dev */
-	unsigned int	bi_baudrate;	/* ...to be like everyone else */
+
+	/* These fields are not part of the board information structure
+	 * provided by the boot rom.  They are filled in by embed_config.c
+	 * so we have the information consistent with other platforms.
+	 */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
 } bd_t;
 
 /* Memory map for the MBX as configured by EPPC-Bug.  We could reprogram
@@ -78,6 +88,7 @@
 #define ISA_BRIDGE_INT	SIU_IRQ3	/* All those PC things */
 #define COMM_L_INT	SIU_IRQ6	/* MBX Comm expansion connector pin */
 #define STOP_ABRT_INT	SIU_IRQ7	/* Stop/Abort header pin */
+#endif /* !__ASSEMBLY__ */
 
 /* The MBX uses the 8259.
 */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mc146818rtc.h linux/include/asm-ppc/mc146818rtc.h
--- v2.4.4/linux/include/asm-ppc/mc146818rtc.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/mc146818rtc.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mc146818rtc.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * Machine dependent access functions for RTC registers.
  */
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/md.h linux/include/asm-ppc/md.h
--- v2.4.4/linux/include/asm-ppc/md.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/md.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
-/* $Id: md.h,v 1.1 1997/12/15 15:12:15 jj Exp $
+/*
+ * BK Id: SCCS/s.md.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * md.h: High speed xor_block operation for RAID4/5 
  *
  */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mediabay.h linux/include/asm-ppc/mediabay.h
--- v2.4.4/linux/include/asm-ppc/mediabay.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/mediabay.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mediabay.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * mediabay.h: definitions for using the media bay
  * on PowerBook 3400 and similar computers.
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mk48t59.h linux/include/asm-ppc/mk48t59.h
--- v2.4.4/linux/include/asm-ppc/mk48t59.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/mk48t59.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mk48t59.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * Registers for the mk48t59 real-time-clock
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mman.h linux/include/asm-ppc/mman.h
--- v2.4.4/linux/include/asm-ppc/mman.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/mman.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.mman.h 1.7 05/17/01 18:14:25 cort
+ */
 #ifndef __PPC_MMAN_H__
 #define __PPC_MMAN_H__
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h
--- v2.4.4/linux/include/asm-ppc/mmu.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/mmu.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.mmu.h 1.7 05/17/01 18:14:25 cort
+ */
+/*
  * PowerPC memory management structures
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- v2.4.4/linux/include/asm-ppc/mmu_context.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/mmu_context.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.mmu_context.h 1.9 05/17/01 18:14:25 cort
+ */
 #include <linux/config.h>
 
 #ifdef __KERNEL__
@@ -18,6 +21,12 @@
    of any task that makes a kernel entry.  Shared does not mean they
    are not protected, just that the ASID comparison is not performed.
         -- Dan
+
+   The IBM4xx has 256 contexts, so we can just rotate through these
+   as a way of "switching" contexts.  If the TID of the TLB is zero,
+   the PID/TID comparison is disabled, so we can use a TID of zero
+   to represent all kernel pages as shared among all contexts.
+   	-- Dan
  */
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
@@ -26,12 +35,22 @@
 #ifdef CONFIG_8xx
 #define NO_CONTEXT      	16
 #define LAST_CONTEXT    	15
+#define BASE_CONTEXT		(-1)
+#define MUNGE_CONTEXT(n)        (n)
+#define flush_hash_segments(X, Y)	do { } while (0)
+
+#elif CONFIG_4xx
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define BASE_CONTEXT		(0)
 #define MUNGE_CONTEXT(n)        (n)
+#define flush_hash_segments(X, Y)	do { } while (0)
 
 #else
 
 /* PPC 6xx, 7xx CPUs */
 #define NO_CONTEXT      	0
+#define BASE_CONTEXT		(0)
 #define LAST_CONTEXT    	0xfffff
 
 /*
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/module.h linux/include/asm-ppc/module.h
--- v2.4.4/linux/include/asm-ppc/module.h	Tue Nov  7 10:46:04 2000
+++ linux/include/asm-ppc/module.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.module.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _ASM_PPC_MODULE_H
 #define _ASM_PPC_MODULE_H
 /*
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mpc8260.h linux/include/asm-ppc/mpc8260.h
--- v2.4.4/linux/include/asm-ppc/mpc8260.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/mpc8260.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.mpc8260.h 1.5 05/17/01 18:14:25 cort
+ */
 
 /* This is the single file included by all MPC8260 build options.
  * Since there are many different boards and no standard configuration,
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/mpc8xx.h linux/include/asm-ppc/mpc8xx.h
--- v2.4.4/linux/include/asm-ppc/mpc8xx.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/mpc8xx.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.mpc8xx.h 1.10 05/17/01 18:14:25 cort
+ */
 
 /* This is the single file included by all MPC8xx build options.
  * Since there are many different boards and no standard configuration,
@@ -63,11 +66,14 @@
 #define PCI_DRAM_OFFSET 0
 #endif
 #else
+#if !defined(_IO_BASE)  /* defined in board specific header */
 #define _IO_BASE        0
+#endif
 #define _ISA_MEM_BASE   0
 #define PCI_DRAM_OFFSET 0
 #endif
 
+#ifndef __ASSEMBLY__
 extern unsigned long isa_io_base;
 extern unsigned long isa_mem_base;
 extern unsigned long pci_dram_offset;
@@ -82,6 +88,7 @@
 		       unsigned long flags, 
 		       const char *device,
 		       void *dev_id);
+#endif /* !__ASSEMBLY__ */
 #endif /* CONFIG_8xx */
 #endif
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/msgbuf.h linux/include/asm-ppc/msgbuf.h
--- v2.4.4/linux/include/asm-ppc/msgbuf.h	Sat Nov 11 18:19:56 2000
+++ linux/include/asm-ppc/msgbuf.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.msgbuf.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_MSGBUF_H
 #define _PPC_MSGBUF_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/namei.h linux/include/asm-ppc/namei.h
--- v2.4.4/linux/include/asm-ppc/namei.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/namei.h	Mon May 21 15:02:06 2001
@@ -1,5 +1,7 @@
-/* $Id: namei.h,v 1.4 1998/10/28 08:13:33 jj Exp $
- * linux/include/asm-ppc/namei.h
+/*
+ * BK Id: SCCS/s.namei.h 1.5 05/17/01 18:14:25 cort
+ */
+/* linux/include/asm-ppc/namei.h
  * Adapted from linux/include/asm-alpha/namei.h
  *
  * Included from linux/fs/namei.c
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/nvram.h linux/include/asm-ppc/nvram.h
--- v2.4.4/linux/include/asm-ppc/nvram.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/nvram.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.nvram.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * PreP compliant NVRAM access
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/oak.h linux/include/asm-ppc/oak.h
--- v2.4.4/linux/include/asm-ppc/oak.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/oak.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.oak.h 1.7 05/17/01 18:14:25 cort
+ */
+/*
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
@@ -65,6 +68,11 @@
 #ifdef __cplusplus
 }
 #endif
+
+/* Generic 4xx type
+*/
+#define _MACH_4xx (_MACH_oak)
+
 
 #endif /* __OAK_H__ */
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ohare.h linux/include/asm-ppc/ohare.h
--- v2.4.4/linux/include/asm-ppc/ohare.h	Wed Feb  9 19:43:47 2000
+++ linux/include/asm-ppc/ohare.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.ohare.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * ohare.h: definitions for using the "O'Hare" I/O controller chip.
  *
  * Copyright (C) 1997 Paul Mackerras.
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h
--- v2.4.4/linux/include/asm-ppc/page.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/page.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.page.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_PAGE_H
 #define _PPC_PAGE_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/param.h linux/include/asm-ppc/param.h
--- v2.4.4/linux/include/asm-ppc/param.h	Sat Nov 11 18:19:56 2000
+++ linux/include/asm-ppc/param.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.param.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _ASM_PPC_PARAM_H
 #define _ASM_PPC_PARAM_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/parport.h linux/include/asm-ppc/parport.h
--- v2.4.4/linux/include/asm-ppc/parport.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/parport.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.parport.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * parport.h: platform-specific PC-style parport initialisation
  *
  * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/pci-bridge.h linux/include/asm-ppc/pci-bridge.h
--- v2.4.4/linux/include/asm-ppc/pci-bridge.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/pci-bridge.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pci-bridge.h 1.11 05/21/01 01:31:30 cort
+ */
 #ifdef __KERNEL__
 #ifndef _ASM_PCI_BRIDGE_H
 #define _ASM_PCI_BRIDGE_H
@@ -27,10 +30,16 @@
 extern struct pci_controller*
 pci_find_hose_for_OF_device(struct device_node* node);
 
+/* Fill up host controller resources from the OF node */
+extern void
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			   struct device_node *dev, int primary);
+
 /*
  * Structure of a PCI controller (host bridge)
  */
 struct pci_controller {
+	int index;			/* used for pci_controller_num */
 	struct pci_controller *next;
         struct pci_bus *bus;
 	void *arch_data;
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- v2.4.4/linux/include/asm-ppc/pci.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/pci.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pci.h 1.12 05/21/01 01:31:30 cort
+ */
 #ifndef __PPC_PCI_H
 #define __PPC_PCI_H
 #ifdef __KERNEL__
@@ -109,6 +112,16 @@
 {
 	return 1;
 }
+
+/* Return the index of the PCI controller for device PDEV. */
+extern int pci_controller_num(struct pci_dev *pdev);
+
+/* Map a range of PCI memory or I/O space for a device into user space */
+int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine);
+
+/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
+#define HAVE_PCI_MMAP	1
 
 #define sg_dma_address(sg)	(virt_to_bus((sg)->address))
 #define sg_dma_len(sg)		((sg)->length)
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/pgalloc.h linux/include/asm-ppc/pgalloc.h
--- v2.4.4/linux/include/asm-ppc/pgalloc.h	Mon Apr 23 15:28:07 2001
+++ linux/include/asm-ppc/pgalloc.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pgalloc.h 1.9 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_PGALLOC_H
 #define _PPC_PGALLOC_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.4.4/linux/include/asm-ppc/pgtable.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/pgtable.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pgtable.h 1.9 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_PGTABLE_H
 #define _PPC_PGTABLE_H
@@ -418,11 +421,11 @@
 {
 	unsigned long old, tmp;
 	
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	andc	%1,%0,%4
-	or	%1,%1,%5
-	stwcx.	%1,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%1,%0,%4 \n\
+	or	%1,%1,%5 \n\
+	stwcx.	%1,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=&r" (tmp), "=m" (*p)
 	: "r" (p), "r" (clr), "r" (set), "m" (*p)
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/pnp.h linux/include/asm-ppc/pnp.h
--- v2.4.4/linux/include/asm-ppc/pnp.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/pnp.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.pnp.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 /* 11/02/95                                                                   */
 /*----------------------------------------------------------------------------*/
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/poll.h linux/include/asm-ppc/poll.h
--- v2.4.4/linux/include/asm-ppc/poll.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/poll.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.poll.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef __PPC_POLL_H
 #define __PPC_POLL_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/posix_types.h linux/include/asm-ppc/posix_types.h
--- v2.4.4/linux/include/asm-ppc/posix_types.h	Mon Jun 19 17:59:37 2000
+++ linux/include/asm-ppc/posix_types.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.posix_types.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_POSIX_TYPES_H
 #define _PPC_POSIX_TYPES_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ppc4xx.h linux/include/asm-ppc/ppc4xx.h
--- v2.4.4/linux/include/asm-ppc/ppc4xx.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/ppc4xx.h	Mon May 21 15:02:06 2001
@@ -0,0 +1,285 @@
+/*
+ * BK Id: SCCS/s.ppc4xx.h 1.3 05/17/01 18:14:25 cort
+ */
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: ppc4xx.h
+ *
+ *    Description:
+ *	A generic include file which pulls in appropriate include files
+ *      for specific board types based on configuration settings.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC4XX_H__
+#define	__PPC4XX_H__
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_OAK)
+#include <asm/oak.h>
+#endif
+
+#if defined(CONFIG_WALNUT)
+#include <asm/walnut.h>
+#endif
+
+/* IO_BASE is for PCI I/O.
+ * ISA not supported, just here to resolve copilation.
+ */
+
+#define _IO_BASE	0xe8000000	/* The PCI address window */
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+extern unsigned long isa_io_base;
+
+/*
+ * The "residual" board information structure the boot loader passes
+ * into the kernel.
+ */
+extern unsigned char __res[];
+
+/* I don't know if this is general to 4xx, or unique to a specific
+ * processor or board.  In any case it is easy to move.
+ */
+#define PPC4xx_PCI_IO_ADDR	((uint)0xe8000000)
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_ADDR	((uint)0xeec00000)
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_ADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_ADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+#endif /* __ASSEMBLY__ */
+
+/* Device Control Registers unique to 4xx */
+
+#define	DCRN_BEAR	0x090	/* Bus Error Address Register */
+#define	DCRN_BESR	0x091	/* Bus Error Syndrome Register */
+#define	  BESR_DSES    	0x80000000	/* Data-Side Error Status */
+#define	  BESR_DMES	0x40000000	/* DMA Error Status */
+#define	  BESR_RWS	0x20000000	/* Read/Write Status */
+#define	  BESR_ETMASK	0x1C000000	/* Error Type */
+#define	    ET_PROT	0
+#define	    ET_PARITY	1
+#define	    ET_NCFG	2
+#define	    ET_BUSERR	4
+#define	    ET_BUSTO	6
+#define DCRN_CHCR0	0x0B1	/* Chip Control Register 1                    */
+#define DCRN_CHCR1	0x0B2	/* Chip Control Register 2                    */
+#define DCRN_CHPSR	0x0B4	/* Chip Pin Strapping                         */
+#define DCRN_CPMER	0x0B9	/* CPM Enable                                 */
+#define DCRN_CPMFR	0x0BA	/* CPM Force                                  */
+#define   CPM_IIC	0x80000000  /* IIC interface                          */
+#define   CPM_PCI	0x40000000  /* PCI bridge                             */
+#define   CPM_CPU	0x20000000  /* processor core                         */
+#define   CPM_DMA	0x10000000  /* DMA controller                         */
+#define   CPM_BRG	0x08000000  /* PLB to OPB bridge                      */
+#define   CPM_DCP	0x04000000  /* CodePack                               */
+#define   CPM_EBC	0x02000000  /* ROM/SRAM peripheral controller         */
+#define   CPM_SDRAM	0x01000000  /* SDRAM memory controller                */
+#define   CPM_PLB	0x00800000  /* PLB bus arbiter                        */
+#define   CPM_GPIO	0x00400000  /* General Purpose IO (??)                */
+#define   CPM_UART0	0x00200000  /* serial port 0                          */
+#define   CPM_UART1	0x00100000  /* serial port 1                          */
+#define   CPM_UIC	0x00080000  /* Universal Interrupt Controller         */
+#define   CPM_TMRCLK	0x00040000  /* CPU timers                             */
+#define   CPM_EMAC_MM	0x00020000  /* on-chip ethernet MM unit               */
+#define   CPM_EMAC_RM	0x00010000  /* on-chip ethernet RM unit               */
+#define   CPM_EMAC_TM	0x00008000  /* on-chip ethernet TM unit               */
+#define DCRN_CPMSR	0x0B8	/* CPM Status                                 */
+
+#define	DCRN_DMACR0	0x100	/* DMA Channel Control Register 0             */
+#define	DCRN_DMACT0	0x101	/* DMA Count Register 0                       */
+#define	DCRN_DMADA0	0x102	/* DMA Destination Address Register 0         */
+#define	DCRN_DMASA0	0x103	/* DMA Source Address Register 0              */
+#define DCRN_ASG0	0x104	/* DMA Scatter/Gather Descriptor Addr 0       */
+
+#define	DCRN_DMACR1	0x108	/* DMA Channel Control Register 1             */
+#define	DCRN_DMACT1	0x109	/* DMA Count Register 1                       */
+#define	DCRN_DMADA1	0x10A	/* DMA Destination Address Register 1         */
+#define	DCRN_DMASA1	0x10B	/* DMA Source Address Register 1              */
+#define DCRN_ASG1	0x10C	/* DMA Scatter/Gather Descriptor Addr 1       */
+
+#define	DCRN_DMACR2	0x110	/* DMA Channel Control Register 2             */
+#define	DCRN_DMACT2	0x111	/* DMA Count Register 2                       */
+#define	DCRN_DMADA2	0x112	/* DMA Destination Address Register 2         */
+#define	DCRN_DMASA2	0x113	/* DMA Source Address Register 2              */
+#define DCRN_ASG2	0x114	/* DMA Scatter/Gather Descriptor Addr 2       */
+
+#define	DCRN_DMACR3	0x118	/* DMA Channel Control Register 3             */
+#define	DCRN_DMACT3	0x119	/* DMA Count Register 3                       */
+#define	DCRN_DMADA3	0x11A	/* DMA Destination Address Register 3         */
+#define	DCRN_DMASA3	0x11B	/* DMA Source Address Register 3              */
+#define DCRN_ASG3	0x11C	/* DMA Scatter/Gather Descriptor Addr 3       */
+
+#define	DCRN_DMASR	0x120	/* DMA Status Register                        */
+#define DCRN_ASGC	0x123	/* DMA Scatter/Gather Command                 */
+#define DCRN_ADR	0x124	/* DMA Address Decode                         */
+
+#define DCRN_SLP        0x125   /* DMA Sleep Register                         */
+#define DCRN_POL        0x126   /* DMA Polarity Register                      */
+
+
+#define DCRN_EBCCFGADR	0x012	/* Peripheral Controller Address              */
+#define DCRN_EBCCFGDATA	0x013	/* Peripheral Controller Data                 */
+#define	DCRN_EXISR	0x040    /* External Interrupt Status Register */
+#define	DCRN_EXIER	0x042    /* External Interrupt Enable Register */
+#define	  EXIER_CIE	0x80000000	/* Critical Interrupt Enable */
+#define	  EXIER_SRIE	0x08000000	/* Serial Port Rx Int. Enable */
+#define	  EXIER_STIE	0x04000000	/* Serial Port Tx Int. Enable */
+#define	  EXIER_JRIE	0x02000000	/* JTAG Serial Port Rx Int. Enable */
+#define	  EXIER_JTIE	0x01000000	/* JTAG Serial Port Tx Int. Enable */
+#define	  EXIER_D0IE	0x00800000	/* DMA Channel 0 Interrupt Enable */
+#define	  EXIER_D1IE	0x00400000	/* DMA Channel 1 Interrupt Enable */
+#define	  EXIER_D2IE	0x00200000	/* DMA Channel 2 Interrupt Enable */
+#define	  EXIER_D3IE	0x00100000	/* DMA Channel 3 Interrupt Enable */
+#define	  EXIER_E0IE	0x00000010	/* External Interrupt 0 Enable */
+#define	  EXIER_E1IE	0x00000008	/* External Interrupt 1 Enable */
+#define	  EXIER_E2IE	0x00000004	/* External Interrupt 2 Enable */
+#define	  EXIER_E3IE	0x00000002	/* External Interrupt 3 Enable */
+#define	  EXIER_E4IE	0x00000001	/* External Interrupt 4 Enable */
+#define	DCRN_IOCR	0x0A0    /* Input/Output Configuration Register */
+#define	  IOCR_E0TE	0x80000000
+#define	  IOCR_E0LP	0x40000000
+#define	  IOCR_E1TE	0x20000000
+#define	  IOCR_E1LP	0x10000000
+#define	  IOCR_E2TE	0x08000000
+#define	  IOCR_E2LP	0x04000000
+#define	  IOCR_E3TE	0x02000000
+#define	  IOCR_E3LP	0x01000000
+#define	  IOCR_E4TE	0x00800000
+#define	  IOCR_E4LP	0x00400000
+#define	  IOCR_EDT     	0x00080000
+#define	  IOCR_SOR     	0x00040000
+#define	  IOCR_EDO	0x00008000
+#define	  IOCR_2XC	0x00004000
+#define	  IOCR_ATC	0x00002000
+#define	  IOCR_SPD	0x00001000
+#define	  IOCR_BEM	0x00000800
+#define	  IOCR_PTD	0x00000400
+#define	  IOCR_ARE	0x00000080
+#define	  IOCR_DRC	0x00000020
+#define	  IOCR_RDM(x)	(((x) & 0x3) << 3)
+#define	  IOCR_TCS	0x00000004
+#define	  IOCR_SCS	0x00000002
+#define	  IOCR_SPC	0x00000001
+#define DCRN_KIAR	0x014	/* Decompression Controller Address           */
+#define DCRN_KIDR	0x015	/* Decompression Controller Data              */
+#define DCRN_MALCR	0x180	/* MAL Configuration                          */
+#define   MALCR_MMSR    0x80000000    /* MAL Software reset                   */
+#define   MALCR_PLBP_1  0x00400000    /* MAL reqest priority:                 */
+#define   MALCR_PLBP_2  0x00800000    /*   lowsest is 00                      */
+#define   MALCR_PLBP_3  0x00C00000    /*   highest                            */
+#define   MALCR_GA      0x00200000    /* Guarded Active Bit                   */
+#define   MALCR_OA      0x00100000    /* Ordered Active Bit                   */
+#define   MALCR_PLBLE   0x00080000    /* PLB Lock Error Bit                   */
+#define   MALCR_PLBLT_1 0x00040000    /* PLB Latency Timer                    */
+#define   MALCR_PLBLT_2 0x00020000
+#define   MALCR_PLBLT_3 0x00010000
+#define   MALCR_PLBLT_4 0x00008000
+#define   MALCR_PLBLT_DEFAULT 0x00078000 /* JSP: Is this a valid default??    */
+#define   MALCR_PLBB    0x00004000    /* PLB Burst Deactivation Bit           */
+#define   MALCR_OPBBL   0x00000080    /* OPB Lock Bit                         */
+#define   MALCR_EOPIE   0x00000004    /* End Of Packet Interrupt Enable       */
+#define   MALCR_LEA     0x00000002    /* Locked Error Active                  */
+#define   MALCR_MSD     0x00000001    /* MAL Scroll Descriptor Bit            */
+#define DCRN_MALDBR     0x183   /* Debug Register                             */
+#define DCRN_MALESR	0x181	/* Error Status                               */
+#define   MALESR_EVB    0x80000000    /* Error Valid Bit                      */
+#define   MALESR_CID    0x40000000    /* Channel ID Bit  for channel 0        */
+#define   MALESR_DE     0x00100000    /* Descriptor Error                     */
+#define   MALESR_OEN    0x00080000    /* OPB Non-Fullword Error               */
+#define   MALESR_OTE    0x00040000    /* OPB Timeout Error                    */
+#define   MALESR_OSE    0x00020000    /* OPB Slave Error                      */
+#define   MALESR_PEIN   0x00010000    /* PLB Bus Error Indication             */
+#define   MALESR_DEI    0x00000010    /* Descriptor Error Interrupt           */
+#define   MALESR_ONEI   0x00000008    /* OPB Non-Fullword Error Interrupt     */
+#define   MALESR_OTEI   0x00000004    /* OPB Timeout Error Interrupt          */
+#define   MALESR_OSEI   0x00000002    /* OPB Slace Error Interrupt            */
+#define   MALESR_PBEI   0x00000001    /* PLB Bus Error Interrupt              */
+#define DCRN_MALIER	0x182	/* Interrupt Enable                           */
+#define   MALIER_DE     0x00000010    /* Descriptor Error Interrupt Enable    */
+#define   MALIER_NE     0x00000008    /* OPB Non-word Transfer Int Enable     */
+#define   MALIER_TE     0x00000004    /* OPB Time Out Error Interrupt Enable  */
+#define   MALIER_OPBE   0x00000002    /* OPB Slave Error Interrupt Enable     */
+#define   MALIER_PLBE   0x00000001    /* PLB Error Interrupt Enable           */
+#define DCRN_MALTXCARR  0x185   /* TX Channed Active Reset Register           */
+#define DCRN_MALTXCASR  0x184   /* TX Channel Active Set Register             */
+#define DCRN_MALTXDEIR	0x187	/* Tx Descriptor Error Interrupt              */
+#define DCRN_MALTXEOBISR    0x186   /* Tx End of Buffer Interrupt Status      */
+#define   MALOBISR_CH0  0x80000000    /* EOB channel 1 bit                    */
+#define   MALOBISR_CH2  0x40000000    /* EOB channel 2 bit                    */
+#define DCRN_MALRXCARR  0x191   /* RX Channed Active Reset Register           */
+#define DCRN_MALRXCASR  0x190   /* RX Channel Active Set Register             */
+#define DCRN_MALRXDEIR	0x193	/* Rx Descriptor Error Interrupt              */
+#define DCRN_MALRXEOBISR    0x192   /* Rx End of Buffer Interrupt Status      */
+#define DCRN_MALRXCTP0R	0x1C0	/* Channel Rx 0 Channel Table Pointer         */
+#define DCRN_MALTXCTP0R	0x1A0	/* Channel Tx 0 Channel Table Pointer         */
+#define DCRN_MALTXCTP1R	0x1A1	/* Channel Tx 1 Channel Table Pointer         */
+#define DCRN_MALRCBS0	0x1E0	/* Channel Rx 0 Channel Buffer Size           */
+#define DCRN_MEMCFGADR	0x010	/* Memory Controller Address                  */
+#define DCRN_MEMCFGDATA	0x011	/* Memory Controller Data                     */
+#define DCRN_OCMISARC	0x018	/* OCM Instr Side Addr Range Compare          */
+#define DCRN_OCMISCR	0x019	/* OCM Instr Side Control                     */
+#define DCRN_OCMDSARC	0x01A	/* OCM Data Side Addr Range Compare           */
+#define DCRN_OCMDSCR	0x01B	/* OCM Data Side Control                      */
+#define DCRN_PLB0_ACR	0x087	/* PLB Arbiter Control                        */
+#define DCRN_PLB0_BEAR	0x086	/* PLB Error Address                          */
+#define DCRN_PLB0_BESR	0x084	/* PLB Error Status                           */
+#define DCRN_PLLMR	0x0B0	/* PLL Mode                                   */
+#define DCRN_POB0_BEAR	0x0A2	/* PLB to OPB Error Address                   */
+#define DCRN_POB0_BESR0	0x0A0	/* PLB to OPB Error Status Register 1         */
+#define DCRN_POB0_BESR1	0x0A4	/* PLB to OPB Error Status Register 1         */
+#define DCRN_UICCR	0x0C3	/* UIC Critical                               */
+#define DCRN_UICER	0x0C2	/* UIC Enable                                 */
+#define DCRN_UICPR	0x0C4	/* UIC Polarity                               */
+#define DCRN_UICSR	0x0C0	/* UIC Status                                 */
+#define DCRN_UICTR	0x0C5	/* UIC Triggering                             */
+#define DCRN_UICMSR	0x0C6	/* UIC Masked Status                          */
+#define DCRN_UICVR	0x0C7	/* UIC Vector                                 */
+#define DCRN_UICVCR	0x0C8	/* UIC Vector Configuration                   */
+#define   UIC_U0	0x80000000  /* UART0                                  */
+#define   UIC_U1	0x40000000  /* UART1                                  */
+#define   UIC_IIC	0x20000000  /* IIC                                    */
+#define   UIC_EM	0x10000000  /* External Master                        */
+#define   UIC_PCI	0x08000000  /* PCI                                    */
+#define   UIC_D0	0x04000000  /* DMA Channel 0                          */
+#define   UIC_D1	0x02000000  /* DMA Channel 1                          */
+#define   UIC_D2	0x01000000  /* DMA Channel 2                          */
+#define   UIC_D3	0x00800000  /* DMA Channel 3                          */
+#define   UIC_EW	0x00400000  /* Ethernet Wake-up                       */
+#define   UIC_MS	0x00200000  /* MAL SERR                               */
+#define   UIC_MTE	0x00100000  /* MAL TX EOB                             */
+#define   UIC_MRE	0x00080000  /* MAL RX EOB                             */
+#define   UIC_MTD	0x00040000  /* MAL TX DE                              */
+#define   UIC_MRD	0x00020000  /* MAL RX DE                              */
+#define   UIC_E		0x00010000  /* Ethernet                               */
+#define   UIC_EPS	0x00008000  /* External PCI SERR                      */
+#define   UIC_EC	0x00004000  /* ECC Correctable Error                  */
+#define   UIC_PPM	0x00002000  /* PCI Power Management                   */
+/*
+**			0x00001000  reserved
+**			0x00000800  reserved
+**			0x00000400  reserved
+**			0x00000200  reserved
+**			0x00000100  reserved
+**			0x00000080  reserved
+*/
+#define   UIC_EIR0	0x00000040  /* External IRQ 0                         */
+#define   UIC_EIR1	0x00000020  /* External IRQ 0                         */
+#define   UIC_EIR2	0x00000010  /* External IRQ 0                         */
+#define   UIC_EIR3	0x00000008  /* External IRQ 0                         */
+#define   UIC_EIR4	0x00000004  /* External IRQ 0                         */
+#define   UIC_EIR5	0x00000002  /* External IRQ 0                         */
+#define   UIC_EIR6	0x00000001  /* External IRQ 0                         */
+
+#endif /* __PPC4XX_H__ */
+#endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ppc4xx_serial.h linux/include/asm-ppc/ppc4xx_serial.h
--- v2.4.4/linux/include/asm-ppc/ppc4xx_serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/ppc4xx_serial.h	Mon May 21 15:02:06 2001
@@ -0,0 +1,104 @@
+/*
+ * BK Id: SCCS/s.ppc4xx_serial.h 1.3 05/17/01 18:14:25 cort
+ */
+/*
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405GP modifications
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *
+ *    Module name: ppc405_serial.h
+ *
+ *    Description:
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      405 on-chip serial port devices.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASMPPC_PPC4xx_SERIAL_H
+#define __ASMPPC_PPC4xx_SERIAL_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE	4
+#endif
+
+#define PPC405GP_UART0_INT	0
+#define PPC405GP_UART1_INT	1
+
+/*
+** 405GP UARTs are *not* PCI devices, so need to specify a non-pci memory
+** address and an io_type of SERIAL_IO_MEM.
+*/
+
+#define PPC405GP_UART0_IO_BASE	(u8 *) 0xef600300
+#define PPC405GP_UART1_IO_BASE	(u8 *) 0xef600400
+
+/*
+**  - there is no config option for this
+**  - this name could be more informative
+**  - also see arch/ppc/kernel/ppc405_serial.c
+**
+** #define CONFIG_PPC405GP_INTERNAL_CLOCK
+*/
+#ifdef	CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD		691200
+#endif
+
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF)
+#endif
+
+
+#ifdef CONFIG_STB03XXX
+
+#define UART0_IO_BASE 0x40040000
+#define UART0_INT     20
+
+#define STD_SERIAL_PORT_DFNS \
+    /* ttyS0 */ \
+    { 0, BASE_BAUD, 0, UART0_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    UART0_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },
+
+#elif defined(CONFIG_UART1_DFLT_CONSOLE)
+
+#define STD_SERIAL_PORT_DFNS \
+    /* ttyS1 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART1_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART1_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },        \
+    /* ttyS0 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART0_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART0_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },
+
+#else
+
+#define STD_SERIAL_PORT_DFNS \
+    /* ttyS0 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART0_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART0_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },        \
+    /* ttyS1 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART1_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART1_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },
+
+#endif
+
+
+#define SERIAL_PORT_DFNS     \
+	STD_SERIAL_PORT_DFNS \
+	{}
+
+
+
+#endif	/* __ASMPPC_PPC4xx_SERIAL_H */
+#endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/prep_nvram.h linux/include/asm-ppc/prep_nvram.h
--- v2.4.4/linux/include/asm-ppc/prep_nvram.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/prep_nvram.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.prep_nvram.h 1.7 05/17/01 18:14:25 cort
+ */
+/*
  * PreP compliant NVRAM access
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.4.4/linux/include/asm-ppc/processor.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/processor.h	Thu May 24 15:03:05 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.processor.h 1.19 05/18/01 08:18:10 patch
+ */
 #ifdef __KERNEL__
 #ifndef __ASM_PPC_PROCESSOR_H
 #define __ASM_PPC_PROCESSOR_H
@@ -12,6 +15,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/types.h>
+#include <asm/mpc8xx.h>
 
 /* Machine State Register (MSR) Fields */
 
@@ -31,6 +35,7 @@
 #define MSR_ME		(1<<12)		/* Machine Check Enable */
 #define MSR_FE0		(1<<11)		/* Floating Exception mode 0 */
 #define MSR_SE		(1<<10)		/* Single Step */
+#define MSR_DWE		(1<<10)		/* Debug Wait Enable (4xx) */
 #define MSR_BE		(1<<9)		/* Branch Trace */
 #define MSR_DE		(1<<9) 		/* Debug Exception Enable */
 #define MSR_FE1		(1<<8)		/* Floating Exception mode 1 */
@@ -82,6 +87,7 @@
 
 /* Special Purpose Registers (SPRNs)*/
 
+#define	SPRN_CCR0	0x3B3	/* Core Configuration Register (4xx) */
 #define	SPRN_CDBCR	0x3D7	/* Cache Debug Control Register */
 #define	SPRN_CTR	0x009	/* Count Register */
 #define	SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
@@ -132,6 +138,8 @@
 #define	SPRN_DBCR0	0x3F2	/* Debug Control Register 0 */
 #define	SPRN_DBCR1	0x3BD	/* Debug Control Register 1 */
 #define	SPRN_DBSR	0x3F0	/* Debug Status Register */
+#define   DBSR_IC	    0x80000000	/* Instruction Completion             */
+#define   DBSR_TIE	    0x10000000	/* Trap Instruction debug Event       */
 #define	SPRN_DCCR	0x3FA	/* Data Cache Cacheability Register */
 #define	  DCCR_NOCACHE		0	/* Noncacheable */
 #define	  DCCR_CACHE		1	/* Cacheable */
@@ -141,6 +149,26 @@
 #define	  DCWR_WRITE		1	/* Write-through */
 #define	SPRN_DEAR	0x3D5	/* Data Error Address Register */
 #define	SPRN_DEC	0x016	/* Decrement Register */
+#define	SPRN_DER	0x095	/* Debug Enable Regsiter */
+#define   DER_RSTE	0x40000000	/* Reset Interrupt */
+#define   DER_CHSTPE	0x20000000	/* Check Stop */
+#define   DER_MCIE	0x10000000	/* Machine Check Interrupt */
+#define   DER_EXTIE	0x02000000	/* External Interrupt */
+#define   DER_ALIE	0x01000000	/* Alignment Interrupt */
+#define   DER_PRIE	0x00800000	/* Program Interrupt */
+#define   DER_FPUVIE	0x00400000	/* FP Unavailable Interrupt */
+#define   DER_DECIE	0x00200000	/* Decrementer Interrupt */
+#define   DER_SYSIE	0x00040000	/* System Call Interrupt */
+#define   DER_TRE	0x00020000	/* Trace Interrupt */
+#define   DER_SEIE	0x00004000	/* FP SW Emulation Interrupt */
+#define   DER_ITLBMSE	0x00002000	/* Imp. Spec. Instruction TLB Miss */
+#define   DER_ITLBERE	0x00001000	/* Imp. Spec. Instruction TLB Error */
+#define   DER_DTLBMSE	0x00000800	/* Imp. Spec. Data TLB Miss */
+#define   DER_DTLBERE	0x00000400	/* Imp. Spec. Data TLB Error */
+#define   DER_LBRKE	0x00000008	/* Load/Store Breakpoint Interrupt */
+#define   DER_IBRKE	0x00000004	/* Instruction Breakpoint Interrupt */
+#define   DER_EBRKE	0x00000002	/* External Breakpoint Interrupt */
+#define   DER_DPIE	0x00000001	/* Dev. Port Nonmaskable Request */
 #define	SPRN_DMISS	0x3D0	/* Data TLB Miss Register */
 #define	SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
 #define	SPRN_EAR	0x11A	/* External Address Register */
@@ -178,6 +206,7 @@
 #define   HID0_SPD	(1<<9)		/* Speculative disable */
 #define   HID0_SGE	(1<<7)		/* Store Gathering Enable */
 #define	  HID0_SIED	(1<<7)		/* Serial Instr. Execution [Disable] */
+#define	  HID0_DFCA	(1<<6)		/* Data Cache Flush Assist */
 #define   HID0_BTIC	(1<<5)		/* Branch Target Instruction Cache Enable */
 #define   HID0_ABE	(1<<3)		/* Address Broadcast Enable */
 #define	  HID0_BHTE	(1<<2)		/* Branch History Table Enable */
@@ -203,12 +232,35 @@
 #define	SPRN_IMISS	0x3D4	/* Instruction TLB Miss Register */
 #define	SPRN_IMMR	0x27E  	/* Internal Memory Map Register */
 #define	SPRN_L2CR	0x3F9	/* Level 2 Cache Control Regsiter */
-#define   L2CR_PIPE_LATEWR   (0x01800000)   /* late-write SRAM */
-#define   L2CR_L2CTL         (0x00100000)   /* RAM control */
-#define   L2CR_INST_DISABLE  (0x00400000)   /* disable for insn's */
-#define   L2CR_L2I           (0x00200000)   /* global invalidate */
-#define   L2CR_L2E           (0x80000000)   /* enable */
-#define   L2CR_L2WT          (0x00080000)   /* write-through */
+#define L2CR_L2E		0x80000000	/* L2 enable */
+#define L2CR_L2PE		0x40000000	/* L2 parity enable */
+#define	L2CR_L2SIZ_MASK		0x30000000	/* L2 size mask */
+#define L2CR_L2SIZ_256KB	0x10000000	/* L2 size 256KB */
+#define L2CR_L2SIZ_512KB	0x20000000	/* L2 size 512KB */
+#define L2CR_L2SIZ_1MB		0x30000000	/* L2 size 1MB */
+#define L2CR_L2CLK_MASK		0x0e000000	/* L2 clock mask */
+#define L2CR_L2CLK_DISABLED	0x00000000	/* L2 clock disabled */
+#define L2CR_L2CLK_DIV1		0x02000000	/* L2 clock / 1 */
+#define L2CR_L2CLK_DIV1_5	0x04000000	/* L2 clock / 1.5 */
+#define L2CR_L2CLK_DIV2		0x08000000	/* L2 clock / 2 */
+#define L2CR_L2CLK_DIV2_5	0x0a000000	/* L2 clock / 2.5 */
+#define L2CR_L2CLK_DIV3		0x0c000000	/* L2 clock / 3 */
+#define L2CR_L2RAM_MASK		0x01800000	/* L2 RAM type mask */
+#define L2CR_L2RAM_FLOW		0x00000000	/* L2 RAM flow through */
+#define L2CR_L2RAM_PIPE		0x01000000	/* L2 RAM pipelined */
+#define L2CR_L2RAM_PIPE_LW	0x01800000	/* L2 RAM pipelined latewr */
+#define	L2CR_L2DO		0x00400000	/* L2 data only */
+#define L2CR_L2I		0x00200000	/* L2 global invalidate */
+#define L2CR_L2CTL		0x00100000	/* L2 RAM control */
+#define L2CR_L2WT		0x00080000	/* L2 write-through */
+#define L2CR_L2TS		0x00040000	/* L2 test support */
+#define L2CR_L2OH_MASK		0x00030000	/* L2 output hold mask */
+#define L2CR_L2OH_0_5		0x00000000	/* L2 output hold 0.5 ns */
+#define L2CR_L2OH_1_0		0x00010000	/* L2 output hold 1.0 ns */
+#define L2CR_L2SL		0x00008000	/* L2 DLL slow */
+#define L2CR_L2DF		0x00004000	/* L2 differential clock */
+#define L2CR_L2BYP		0x00002000	/* L2 DLL bypass */
+#define L2CR_L2IP		0x00000001	/* L2 GI in progress */
 #define	SPRN_LR		0x008	/* Link Register */
 #define	SPRN_MMCR0	0x3B8	/* Monitor Mode Control Register 0 */
 #define	SPRN_MMCR1	0x3BC	/* Monitor Mode Control Register 1 */
@@ -235,6 +287,10 @@
 #define	SPRN_SPRG1	0x111	/* Special Purpose Register General 1 */
 #define	SPRN_SPRG2	0x112	/* Special Purpose Register General 2 */
 #define	SPRN_SPRG3	0x113	/* Special Purpose Register General 3 */
+#define	SPRN_SPRG4	0x114	/* Special Purpose Register General 4 (4xx) */
+#define	SPRN_SPRG5	0x115	/* Special Purpose Register General 5 (4xx) */
+#define	SPRN_SPRG6	0x116	/* Special Purpose Register General 6 (4xx) */
+#define	SPRN_SPRG7	0x117	/* Special Purpose Register General 7 (4xx) */
 #define	SPRN_SRR0	0x01A	/* Save/Restore Register 0 */
 #define	SPRN_SRR1	0x01B	/* Save/Restore Register 1 */
 #define	SPRN_SRR2	0x3DE	/* Save/Restore Register 2 */
@@ -243,10 +299,6 @@
 #define	SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
 #define	SPRN_TBWL	0x11C	/* Time Base Lower Register (supervisor, R/W) */
 #define	SPRN_TBWU	0x11D	/* Time Base Upper Register (supervisor, R/W) */
-#define	SPRN_TBHI	0x3DC	/* Time Base High (4xx) */
-#define	SPRN_TBHU	0x3CC	/* Time Base High User-mode (4xx) */
-#define	SPRN_TBLO	0x3DD	/* Time Base Low (4xx) */
-#define	SPRN_TBLU	0x3CD	/* Time Base Low User-mode (4xx) */
 #define	SPRN_TCR	0x3DA	/* Timer Control Register */
 #define	  TCR_WP(x)		(((x)&0x3)<<30)	/* WDT Period */
 #define	    WP_2_17		0		/* 2^17 clocks */
@@ -343,10 +395,18 @@
 #define	SPR1	SPRN_SPRG1
 #define	SPR2	SPRN_SPRG2
 #define	SPR3	SPRN_SPRG3
+#define	SPR4	SPRN_SPRG4	/* Supervisor Private Registers (4xx) */
+#define	SPR5	SPRN_SPRG5
+#define	SPR6	SPRN_SPRG6
+#define	SPR7	SPRN_SPRG7
 #define	SPRG0   SPRN_SPRG0
 #define	SPRG1   SPRN_SPRG1
 #define	SPRG2   SPRN_SPRG2
 #define	SPRG3   SPRN_SPRG3
+#define	SPRG4   SPRN_SPRG4
+#define	SPRG5   SPRN_SPRG5
+#define	SPRG6   SPRN_SPRG6
+#define	SPRG7   SPRN_SPRG7
 #define	SRR0	SPRN_SRR0	/* Save and Restore Register 0 */
 #define	SRR1	SPRN_SRR1	/* Save and Restore Register 1 */
 #define	TBRL	SPRN_TBRL	/* Time Base Read Lower Register */
@@ -359,84 +419,6 @@
 #define	THRM3	SPRN_THRM3	/* Thermal Management Register 3 */
 #define	XER	SPRN_XER
 
-
-/* Device Control Registers */
-
-#define	DCRN_BEAR	0x090	/* Bus Error Address Register */
-#define	DCRN_BESR	0x091	/* Bus Error Syndrome Register */
-#define	  BESR_DSES    	0x80000000	/* Data-Side Error Status */
-#define	  BESR_DMES	0x40000000	/* DMA Error Status */
-#define	  BESR_RWS	0x20000000	/* Read/Write Status */
-#define	  BESR_ETMASK	0x1C000000	/* Error Type */
-#define	    ET_PROT	0
-#define	    ET_PARITY	1
-#define	    ET_NCFG	2
-#define	    ET_BUSERR	4
-#define	    ET_BUSTO	6
-#define	DCRN_DMACC0	0x0C4	/* DMA Chained Count Register 0 */
-#define	DCRN_DMACC1	0x0CC	/* DMA Chained Count Register 1 */
-#define	DCRN_DMACC2	0x0D4	/* DMA Chained Count Register 2 */
-#define	DCRN_DMACC3	0x0DC    /* DMA Chained Count Register 3 */
-#define	DCRN_DMACR0	0x0C0    /* DMA Channel Control Register 0 */
-#define	DCRN_DMACR1	0x0C8    /* DMA Channel Control Register 1 */
-#define	DCRN_DMACR2	0x0D0    /* DMA Channel Control Register 2 */
-#define	DCRN_DMACR3	0x0D8    /* DMA Channel Control Register 3 */
-#define	DCRN_DMACT0	0x0C1    /* DMA Count Register 0 */
-#define	DCRN_DMACT1	0x0C9    /* DMA Count Register 1 */
-#define	DCRN_DMACT2	0x0D1    /* DMA Count Register 2 */
-#define	DCRN_DMACT3	0x0D9    /* DMA Count Register 3 */
-#define	DCRN_DMADA0	0x0C2    /* DMA Destination Address Register 0 */
-#define	DCRN_DMADA1	0x0CA    /* DMA Destination Address Register 1 */
-#define	DCRN_DMADA2	0x0D2    /* DMA Destination Address Register 2 */
-#define	DCRN_DMADA3	0x0DA    /* DMA Destination Address Register 3 */
-#define	DCRN_DMASA0	0x0C3    /* DMA Source Address Register 0 */
-#define	DCRN_DMASA1	0x0CB    /* DMA Source Address Register 1 */
-#define	DCRN_DMASA2	0x0D3    /* DMA Source Address Register 2 */
-#define	DCRN_DMASA3	0x0DB    /* DMA Source Address Register 3 */
-#define	DCRN_DMASR	0x0E0    /* DMA Status Register */
-#define	DCRN_EXIER	0x042    /* External Interrupt Enable Register */
-#define	  EXIER_CIE	0x80000000	/* Critical Interrupt Enable */
-#define	  EXIER_SRIE	0x08000000	/* Serial Port Rx Int. Enable */
-#define	  EXIER_STIE	0x04000000	/* Serial Port Tx Int. Enable */
-#define	  EXIER_JRIE	0x02000000	/* JTAG Serial Port Rx Int. Enable */
-#define	  EXIER_JTIE	0x01000000	/* JTAG Serial Port Tx Int. Enable */
-#define	  EXIER_D0IE	0x00800000	/* DMA Channel 0 Interrupt Enable */
-#define	  EXIER_D1IE	0x00400000	/* DMA Channel 1 Interrupt Enable */
-#define	  EXIER_D2IE	0x00200000	/* DMA Channel 2 Interrupt Enable */
-#define	  EXIER_D3IE	0x00100000	/* DMA Channel 3 Interrupt Enable */
-#define	  EXIER_E0IE	0x00000010	/* External Interrupt 0 Enable */
-#define	  EXIER_E1IE	0x00000008	/* External Interrupt 1 Enable */
-#define	  EXIER_E2IE	0x00000004	/* External Interrupt 2 Enable */
-#define	  EXIER_E3IE	0x00000002	/* External Interrupt 3 Enable */
-#define	  EXIER_E4IE	0x00000001	/* External Interrupt 4 Enable */
-#define	DCRN_EXISR	0x040    /* External Interrupt Status Register */
-#define	DCRN_IOCR	0x0A0    /* Input/Output Configuration Register */
-#define	  IOCR_E0TE	0x80000000
-#define	  IOCR_E0LP	0x40000000
-#define	  IOCR_E1TE	0x20000000
-#define	  IOCR_E1LP	0x10000000
-#define	  IOCR_E2TE	0x08000000
-#define	  IOCR_E2LP	0x04000000
-#define	  IOCR_E3TE	0x02000000
-#define	  IOCR_E3LP	0x01000000
-#define	  IOCR_E4TE	0x00800000
-#define	  IOCR_E4LP	0x00400000
-#define	  IOCR_EDT     	0x00080000
-#define	  IOCR_SOR     	0x00040000
-#define	  IOCR_EDO	0x00008000
-#define	  IOCR_2XC	0x00004000
-#define	  IOCR_ATC	0x00002000
-#define	  IOCR_SPD	0x00001000
-#define	  IOCR_BEM	0x00000800
-#define	  IOCR_PTD	0x00000400
-#define	  IOCR_ARE	0x00000080
-#define	  IOCR_DRC	0x00000020
-#define	  IOCR_RDM(x)	(((x) & 0x3) << 3)
-#define	  IOCR_TCS	0x00000004
-#define	  IOCR_SCS	0x00000002
-#define	  IOCR_SPC	0x00000001
-
-
 /* Processor Version Register */
 
 /* Processor Version Register (PVR) field extraction */
@@ -509,15 +491,15 @@
 #define _MACH_rpxlite	0x00000040	/* RPCG RPX-Lite 8xx board */
 #define _MACH_bseip	0x00000080	/* Bright Star Engineering ip-Engine */
 #define _MACH_unused0	0x00000100	/* Now free to be used */
-#define _MACH_unused1	0x00000200	/* Now free to be used */
+#define _MACH_gemini	0x00000200      /* Synergy Microsystems gemini board */
 #define _MACH_classic	0x00000400	/* RPCG RPX-Classic 8xx board */
 #define _MACH_oak	0x00000800	/* IBM "Oak" 403 eval. board */
 #define _MACH_walnut	0x00001000	/* IBM "Walnut" 405GP eval. board */
 #define _MACH_8260	0x00002000	/* Generic 8260 */
 #define _MACH_tqm860	0x00004000	/* TQM860/L */
 #define _MACH_tqm8xxL	0x00008000	/* TQM8xxL */
-#define _MACH_spd8xxL	0x00010000	/* SPD8xx */
-#define _MACH_ibms8	0x00020000	/* IVMS8 */
+#define _MACH_spd8xx	0x00010000	/* SPD8xx */
+#define _MACH_ivms8	0x00020000	/* IVMS8 */
 
 /* see residual.h for these */
 #define _PREP_Motorola 0x01  /* motorola prep */
@@ -572,10 +554,10 @@
 #define SR15	15
 
 #ifndef __ASSEMBLY__
-#ifndef CONFIG_MACH_SPECIFIC
+#if defined(CONFIG_ALL_PPC)
 extern int _machine;
 extern int have_of;
-#endif /* CONFIG_MACH_SPECIFIC */
+#endif /* CONFIG_ALL_PPC */
 
 /* what kind of prep workstation we are */
 extern int _prep_type;
@@ -699,26 +681,24 @@
 
 #endif /* ndef ASSEMBLY*/
 
-#ifdef CONFIG_MACH_SPECIFIC
-#if defined(CONFIG_8xx)
-#define _machine _MACH_8xx
-#define have_of 0
+#ifndef CONFIG_ALL_PPC
+#if defined(CONFIG_APUS)
+#define _machine _MACH_apus
+#elif defined(CONFIG_GEMINI)
+#define _machine _MACH_gemini
 #elif defined(CONFIG_OAK)
 #define _machine _MACH_oak
-#define have_of	0
 #elif defined(CONFIG_WALNUT)
 #define _machine _MACH_walnut
-#define have_of 0
-#elif defined(CONFIG_APUS)
-#define _machine _MACH_apus
-#define have_of 0
+#elif defined(CONFIG_8xx)
+#define _machine _MACH_8xx
 #elif defined(CONFIG_8260)
 #define _machine _MACH_8260
-#define have_of 0
 #else
 #error "Machine not defined correctly"
 #endif
-#endif /* CONFIG_MACH_SPECIFIC */
+#define have_of 0
+#endif /* !CONFIG_ALL_PPC */
 
 #endif /* __ASM_PPC_PROCESSOR_H */
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h
--- v2.4.4/linux/include/asm-ppc/prom.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/prom.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.prom.h 1.11 05/18/01 08:18:10 patch
+ */
+/*
  * Definitions for talking to the Open Firmware PROM on
  * Power Macintosh computers.
  *
@@ -15,7 +18,7 @@
 
 extern char *prom_display_paths[];
 extern unsigned int prom_num_displays;
-#ifndef CONFIG_MACH_SPECIFIC
+#ifdef CONFIG_ALL_PPC
 extern int have_of;
 #endif
 
@@ -35,13 +38,6 @@
 	unsigned int size;
 };
 
-struct translation_property {
-	unsigned int virt;
-	unsigned int size;
-	unsigned int phys;
-	unsigned int flags;
-};
-
 struct property {
 	char	*name;
 	int	length;
@@ -64,6 +60,10 @@
 	struct	device_node *sibling;
 	struct	device_node *next;	/* next device of same type */
 	struct	device_node *allnext;	/* next in list of all nodes */
+#if 0 /* Don't change this structure for now or you'll break BootX ! */
+	int	n_addr_cells;
+	int	n_size_cells;
+#endif	
 };
 
 struct prom_args;
@@ -88,6 +88,8 @@
 				   int *lenp);
 extern void prom_add_property(struct device_node* np, struct property* prop);
 extern void prom_get_irq_senses(unsigned char *, int, int);
+extern int prom_n_addr_cells(struct device_node* np);
+extern int prom_n_size_cells(struct device_node* np);
 
 extern void print_properties(struct device_node *node);
 extern int call_rtas(const char *service, int nargs, int nret,
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ptrace.h linux/include/asm-ppc/ptrace.h
--- v2.4.4/linux/include/asm-ppc/ptrace.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/ptrace.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ptrace.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_PTRACE_H
 #define _PPC_PTRACE_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/raven.h linux/include/asm-ppc/raven.h
--- v2.4.4/linux/include/asm-ppc/raven.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/raven.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.raven.h 1.7 05/17/01 18:14:25 cort
+ */
+/*
  *  asm-ppc/raven.h -- Raven MPIC chip.
  *
  *  Copyright (C) 1998 Johnnie Peters
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/residual.h linux/include/asm-ppc/residual.h
--- v2.4.4/linux/include/asm-ppc/residual.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/residual.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.residual.h 1.5 05/17/01 18:14:25 cort
+ */
 /* 7/18/95                                                                    */
 /*----------------------------------------------------------------------------*/
 /*      Residual Data header definitions and prototypes                       */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/resource.h linux/include/asm-ppc/resource.h
--- v2.4.4/linux/include/asm-ppc/resource.h	Fri Sep 22 14:21:21 2000
+++ linux/include/asm-ppc/resource.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.resource.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_RESOURCE_H
 #define _PPC_RESOURCE_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/rpxclassic.h linux/include/asm-ppc/rpxclassic.h
--- v2.4.4/linux/include/asm-ppc/rpxclassic.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/rpxclassic.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.rpxclassic.h 1.8 05/17/01 18:14:25 cort
+ */
 
 /*
  * A collection of structures, addresses, and values associated with
@@ -11,6 +14,7 @@
 
 #include <linux/config.h>
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -60,19 +64,37 @@
 #define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)	/* CLLF */
 #define BCSR0_PCMCIA5VOLT	((uint)0x00060000)	/* CLLF */
 
+#define BCSR1_IPB5SEL           ((uint)0x00100000)
+#define BCSR1_PCVCTL4           ((uint)0x00080000)
+#define BCSR1_PCVCTL5           ((uint)0x00040000)
+#define BCSR1_PCVCTL6           ((uint)0x00020000)
+#define BCSR1_PCVCTL7           ((uint)0x00010000)
+
 #define BCSR2_EN232XCVR		((uint)0x00008000)
 #define BCSR2_QSPACESEL		((uint)0x00004000)
 #define BCSR2_FETHLEDMODE	((uint)0x00000800)	/* CLLF */
 
-#if defined(CONFIG_RPXLCD) || defined(CONFIG_HTDMSOUND)
-/* HIOX Expansion card.
-*/
-#include <asm/rpx_hiox.h>
+#if defined(CONFIG_HTDMSOUND)
+#include <asm/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia, CLLF only */
+#if !defined(CONFIG_PCI)
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+/* for pcmcia sandisk */
+#ifdef CONFIG_IDE
+#define MAX_HWIFS 1
+#define ide_request_irq(irq,hand,flg,dev,id)    request_8xxirq((irq),(hand),(flg),(dev),(id))
+#endif
 #endif
 
 /* Interrupt level assignments.
 */
 #define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+
+#endif /* !__ASSEMBLY__ */
 
 /* We don't use the 8259.
 */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/rpxhiox.h linux/include/asm-ppc/rpxhiox.h
--- v2.4.4/linux/include/asm-ppc/rpxhiox.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/rpxhiox.h	Mon May 21 15:02:06 2001
@@ -0,0 +1,45 @@
+/*
+ * BK Id: SCCS/s.rpxhiox.h 1.3 05/17/01 18:14:25 cort
+ */
+
+/*
+ * The Embedded Planet HIOX expansion card definitions.
+ * There were a few different versions of these cards, but only
+ * the one that escaped real production is defined here.
+ *
+ * Copyright (c) 2000 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_RPX_HIOX_DEFS
+#define __MACH_RPX_HIOX_DEFS
+
+#define HIOX_CSR_ADDR		((uint)0xfac00000)
+#define HIOX_CSR_SIZE		((uint)(4 * 1024))
+#define HIOX_CSR0_ADDR		HIOX_CSR_ADDR
+#define HIOX_CSR4_ADDR		((uint)0xfac00004)
+
+#define HIOX_CSR0_DEFAULT	((uint)0x380f3c00)
+#define HIOX_CSR0_ENSCC2	((uint)0x80000000)
+#define HIOX_CSR0_ENSMC2	((uint)0x04000000)
+#define HIOX_CSR0_ENVDOCLK	((uint)0x02000000)
+#define HIOX_CSR0_VDORST_HL	((uint)0x01000000)
+#define HIOX_CSR0_RS232SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SCC3SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SMC1SEL	((uint)0x00008000)
+#define HIOX_CSR0_SCC1SEL	((uint)0x00004000)
+#define HIOX_CSR0_ENTOUCH	((uint)0x00000080)
+#define HIOX_CSR0_PDOWN100	((uint)0x00000060)
+#define HIOX_CSR0_PDOWN10	((uint)0x00000040)
+#define HIOX_CSR0_PDOWN1	((uint)0x00000020)
+#define HIOX_CSR0_TSELSPI	((uint)0x00000010)
+#define HIOX_CSR0_TIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_DEFAULT	((uint)0x00000000)
+#define HIOX_CSR4_ENTIRQ2	((uint)0x20000000)
+#define HIOX_CSR4_ENTIRQ3	((uint)0x10000000)
+#define HIOX_CSR4_ENAUDIO	((uint)0x00000080)
+#define HIOX_CSR4_RSTAUDIO	((uint)0x00000040)	/* 0 == reset */
+#define HIOX_CSR4_AUDCLKHI	((uint)0x00000020)
+#define HIOX_CSR4_AUDSPISEL	((uint)0x00000010)
+#define HIOX_CSR4_AUDIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_AUDCLKSEL	((uint)0x00000007)
+
+#endif
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/rpxlite.h linux/include/asm-ppc/rpxlite.h
--- v2.4.4/linux/include/asm-ppc/rpxlite.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/rpxlite.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.rpxlite.h 1.8 05/17/01 18:14:25 cort
+ */
 
 /*
  * A collection of structures, addresses, and values associated with
@@ -9,6 +12,9 @@
 #ifndef __MACH_RPX_DEFS
 #define __MACH_RPX_DEFS
 
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -31,8 +37,6 @@
 #define RPX_CSR_SIZE		((uint)(4 * 1024))
 #define IMAP_ADDR		((uint)0xfa200000)
 #define IMAP_SIZE		((uint)(64 * 1024))
-#define HIOX_CSR_ADDR		((uint)0xfac00000)
-#define HIOX_CSR_SIZE		((uint)(4 * 1024))
 #define PCMCIA_MEM_ADDR		((uint)0x04000000)
 #define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
 #define PCMCIA_IO_ADDR		((uint)0x04400000)
@@ -52,10 +56,25 @@
 #define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)
 #define BCSR0_PCMCIA5VOLT	((uint)0x00060000)
 
-/* HIO Expansion card.
-*/
-#define HIOX_CSR_ENAUDIO	((uint)0x00000200)
-#define HIOX_CSR_RSTAUDIO	((uint)0x00000100)	/* 0 == reset */
+#define BCSR1_IPB5SEL          ((uint)0x00100000)
+#define BCSR1_PCVCTL4          ((uint)0x00080000)
+#define BCSR1_PCVCTL5          ((uint)0x00040000)
+#define BCSR1_PCVCTL6          ((uint)0x00020000)
+#define BCSR1_PCVCTL7          ((uint)0x00010000)
+
+#if defined(CONFIG_HTDMSOUND)
+#include <asm/rpxhiox.h>
+#endif
+#endif /* !__ASSEMBLY__ */
+
+/* define IO_BASE for pcmcia */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+#ifdef CONFIG_IDE
+#define MAX_HWIFS 1
+#define ide_request_irq(irq,hand,flg,dev,id)    request_8xxirq((irq),(hand),(flg),(dev),(id))
+#endif
 
 /* We don't use the 8259.
 */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/rwsem.h linux/include/asm-ppc/rwsem.h
--- v2.4.4/linux/include/asm-ppc/rwsem.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/rwsem.h	Mon May 21 15:02:06 2001
@@ -0,0 +1,137 @@
+/*
+ * BK Id: SCCS/s.rwsem.h 1.6 05/17/01 18:14:25 cort
+ */
+/*
+ * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff
+ * in lib/rwsem.c.  Adapted largely from include/asm-i386/rwsem.h
+ * by Paul Mackerras <paulus@samba.org>.
+ */
+
+#ifndef _PPC_RWSEM_H
+#define _PPC_RWSEM_H
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+	/* XXX this should be able to be an atomic_t  -- paulus */
+	signed long		count;
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		(-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if RWSEM_DEBUG
+	int			debug;
+#endif
+};
+
+/*
+ * initialisation
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name)		\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+	sem->count = RWSEM_UNLOCKED_VALUE;
+	spin_lock_init(&sem->wait_lock);
+	INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+	sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+	if (atomic_inc_return((atomic_t *)(&sem->count)) >= 0)
+		smp_wmb();
+	else
+		rwsem_down_read_failed(sem);
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+				(atomic_t *)(&sem->count));
+	if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
+		smp_wmb();
+	else
+		rwsem_down_write_failed(sem);
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_dec_return((atomic_t *)(&sem->count));
+	if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+	smp_wmb();
+	if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+			      (atomic_t *)(&sem->count)) < 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+	atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+	smp_mb();
+	return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+#endif /* __KERNEL__ */
+#endif /* _PPC_RWSEM_XADD_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/scatterlist.h linux/include/asm-ppc/scatterlist.h
--- v2.4.4/linux/include/asm-ppc/scatterlist.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/scatterlist.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.scatterlist.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_SCATTERLIST_H
 #define _PPC_SCATTERLIST_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/segment.h linux/include/asm-ppc/segment.h
--- v2.4.4/linux/include/asm-ppc/segment.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/segment.h	Mon May 21 15:02:06 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.segment.h 1.7 05/17/01 18:14:25 cort
+ */
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/semaphore-helper.h linux/include/asm-ppc/semaphore-helper.h
--- v2.4.4/linux/include/asm-ppc/semaphore-helper.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/semaphore-helper.h	Wed Dec 31 16:00:00 1969
@@ -1,109 +0,0 @@
-#ifdef __KERNEL__
-#ifndef _PPC_SEMAPHORE_HELPER_H
-#define _PPC_SEMAPHORE_HELPER_H
-
-/*
- * SMP- and interrupt-safe semaphores..
- *
- * (C) Copyright 1996 Linus Torvalds
- * Adapted for PowerPC by Gary Thomas and Paul Mackerras
- */
-
-#include <asm/atomic.h>
-
-/*
- * These two (wake_one_more and waking_non_zero) _must_ execute
- * atomically wrt each other.
- *
- * This is trivially done with load with reservation and
- * store conditional on the ppc.
- */
-
-static inline void wake_one_more(struct semaphore * sem)
-{
-	atomic_inc(&sem->waking);
-}
-
-static inline int waking_non_zero(struct semaphore *sem)
-{
-	int ret, tmp;
-
-	/* Atomic decrement sem->waking iff it is > 0 */
-	__asm__ __volatile__(
-		"1:	lwarx %1,0,%2\n"	/* tmp = sem->waking */
-		"	cmpwi 0,%1,0\n"		/* test tmp */
-		"	addic %1,%1,-1\n"	/* --tmp */
-		"	ble- 2f\n"		/* exit if tmp was <= 0 */
-		"	stwcx. %1,0,%2\n"	/* update sem->waking */
-		"	bne- 1b\n"		/* try again if update failed*/
-		"	li %0,1\n"		/* ret = 1 */
-		"2:"
-		: "=r" (ret), "=&r" (tmp)
-		: "r" (&sem->waking), "0" (0)
-		: "cr0", "memory");
-
-	return ret;
-}
-/*
- * waking_non_zero_interruptible:
- *	1	got the lock
- *	0	go to sleep
- *	-EINTR	interrupted
- */
-static inline int waking_non_zero_interruptible(struct semaphore *sem,
-						struct task_struct *tsk)
-{
-	int ret, tmp;
-
-	/* Atomic decrement sem->waking iff it is > 0 */
-	__asm__ __volatile__(
-		"1:	lwarx %1,0,%2\n"	/* tmp = sem->waking */
-		"	cmpwi 0,%1,0\n"		/* test tmp */
-		"	addic %1,%1,-1\n"	/* --tmp */
-		"	ble- 2f\n"		/* exit if tmp was <= 0 */
-		"	stwcx. %1,0,%2\n"	/* update sem->waking */
-		"	bne- 1b\n"		/* try again if update failed*/
-		"	li %0,1\n"		/* ret = 1 */
-		"2:"
-		: "=r" (ret), "=&r" (tmp)
-		: "r" (&sem->waking), "0" (0)
-		: "cr0", "memory");
-
-	if (ret == 0 && signal_pending(tsk)) {
-		atomic_inc(&sem->count);
-		ret = -EINTR;
-	}
-	return ret;
-}
-
-/*
- * waking_non_zero_trylock:
- *	1	failed to lock
- *	0	got the lock
- */
-static inline int waking_non_zero_trylock(struct semaphore *sem)
-{
-	int ret, tmp;
-
-	/* Atomic decrement sem->waking iff it is > 0 */
-	__asm__ __volatile__(
-		"1:	lwarx %1,0,%2\n"	/* tmp = sem->waking */
-		"	cmpwi 0,%1,0\n"		/* test tmp */
-		"	addic %1,%1,-1\n"	/* --tmp */
-		"	ble- 2f\n"		/* exit if tmp was <= 0 */
-		"	stwcx. %1,0,%2\n"	/* update sem->waking */
-		"	bne- 1b\n"		/* try again if update failed*/
-		"	li %0,0\n"		/* ret = 0 */
-		"2:"
-		: "=r" (ret), "=&r" (tmp)
-		: "r" (&sem->waking), "0" (1)
-		: "cr0", "memory");
-
-	if (ret)
-		atomic_inc(&sem->count);
-
-	return ret;
-}
-
-#endif /* _PPC_SEMAPHORE_HELPER_H */
-#endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- v2.4.4/linux/include/asm-ppc/semaphore.h	Tue Apr 17 17:19:31 2001
+++ linux/include/asm-ppc/semaphore.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.semaphore.h 1.15 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_SEMAPHORE_H
 #define _PPC_SEMAPHORE_H
 
@@ -7,6 +10,11 @@
  *
  * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
  * -- Ani Joshi (ajoshi@unixbox.com)
+ *
+ * Remove spinlock-based RW semaphores; RW semaphore definitions are
+ * now in rwsem.h and we use the the generic lib/rwsem.c implementation.
+ * Rework semaphores to use atomic_dec_if_positive.
+ * -- Paul Mackerras (paulus@samba.org)
  */
 
 #ifdef __KERNEL__
@@ -17,8 +25,12 @@
 #include <linux/rwsem.h>
 
 struct semaphore {
+	/*
+	 * Note that any negative value of count is equivalent to 0,
+	 * but additionally indicates that some process(es) might be
+	 * sleeping on `wait'.
+	 */
 	atomic_t count;
-	atomic_t waking;
 	wait_queue_head_t wait;
 #if WAITQUEUE_DEBUG
 	long __magic;
@@ -32,23 +44,23 @@
 # define __SEM_DEBUG_INIT(name)
 #endif
 
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, count) \
+	{ ATOMIC_INIT(count), \
+	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	  __SEM_DEBUG_INIT(name) }
 
 #define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
+	__SEMAPHORE_INITIALIZER(name, 1)
 
-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX_LOCKED(name)	__DECLARE_SEMAPHORE_GENERIC(name, 0)
 
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
 {
 	atomic_set(&sem->count, val);
-	atomic_set(&sem->waking, 0);
 	init_waitqueue_head(&sem->wait);
 #if WAITQUEUE_DEBUG
 	sem->__magic = (long)&sem->__magic;
@@ -67,46 +79,59 @@
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
-extern int  __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
 extern inline void down(struct semaphore * sem)
 {
-	if (atomic_dec_return(&sem->count) >= 0)
-		wmb();
-	else
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	/*
+	 * Try to get the semaphore, take the slow path if we fail.
+	 */
+	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
+	smp_wmb();
 }
 
 extern inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
-	if (atomic_dec_return(&sem->count) >= 0)
-		wmb();
-	else
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
+	smp_wmb();
 	return ret;
 }
 
 extern inline int down_trylock(struct semaphore * sem)
 {
-	int ret = 0;
+	int ret;
 
-	if (atomic_dec_return(&sem->count) >= 0)
-		wmb();
-	else
-		ret = __down_trylock(sem);
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	ret = atomic_dec_if_positive(&sem->count) < 0;
+	smp_wmb();
 	return ret;
 }
 
 extern inline void up(struct semaphore * sem)
 {
-	mb();
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	smp_wmb();
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}	
-
+}
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/sembuf.h linux/include/asm-ppc/sembuf.h
--- v2.4.4/linux/include/asm-ppc/sembuf.h	Sat Nov 11 18:19:56 2000
+++ linux/include/asm-ppc/sembuf.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.sembuf.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_SEMBUF_H
 #define _PPC_SEMBUF_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/serial.h linux/include/asm-ppc/serial.h
--- v2.4.4/linux/include/asm-ppc/serial.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/serial.h	Mon May 21 15:02:06 2001
@@ -1,10 +1,19 @@
 /*
+ * BK Id: SCCS/s.serial.h 1.12 05/17/01 18:14:25 cort
+ */
+/*
  * include/asm-ppc/serial.h
  */
 
 #ifdef __KERNEL__
 #include <linux/config.h>
 
+#ifdef CONFIG_GEMINI
+#include <asm/gemini_serial.h>
+#elif defined(CONFIG_4xx)
+#include <asm/ppc4xx_serial.h>
+#else
+
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
@@ -123,4 +132,5 @@
 	HUB6_SERIAL_PORT_DFNS		\
 	MCA_SERIAL_PORT_DFNS
 
+#endif /* !CONFIG_GEMINI and others */
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/setup.h linux/include/asm-ppc/setup.h
--- v2.4.4/linux/include/asm-ppc/setup.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/setup.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.setup.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_SETUP_H
 #define _PPC_SETUP_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/shmbuf.h linux/include/asm-ppc/shmbuf.h
--- v2.4.4/linux/include/asm-ppc/shmbuf.h	Sat Nov 11 18:19:56 2000
+++ linux/include/asm-ppc/shmbuf.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.shmbuf.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_SHMBUF_H
 #define _PPC_SHMBUF_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/shmparam.h linux/include/asm-ppc/shmparam.h
--- v2.4.4/linux/include/asm-ppc/shmparam.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/shmparam.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.shmparam.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_SHMPARAM_H
 #define _PPC_SHMPARAM_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/sigcontext.h linux/include/asm-ppc/sigcontext.h
--- v2.4.4/linux/include/asm-ppc/sigcontext.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/sigcontext.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.sigcontext.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _ASM_PPC_SIGCONTEXT_H
 #define _ASM_PPC_SIGCONTEXT_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/siginfo.h linux/include/asm-ppc/siginfo.h
--- v2.4.4/linux/include/asm-ppc/siginfo.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/siginfo.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.siginfo.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _PPC_SIGINFO_H
 #define _PPC_SIGINFO_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/signal.h linux/include/asm-ppc/signal.h
--- v2.4.4/linux/include/asm-ppc/signal.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/signal.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.signal.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _ASMPPC_SIGNAL_H
 #define _ASMPPC_SIGNAL_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/smp.h linux/include/asm-ppc/smp.h
--- v2.4.4/linux/include/asm-ppc/smp.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/smp.h	Mon May 21 15:02:06 2001
@@ -1,8 +1,14 @@
+/*
+ * BK Id: SCCS/s.smp.h 1.9 05/17/01 18:14:25 cort
+ */
 /* smp.h: PPC specific SMP stuff.
  *
- * Taken from asm-sparc/smp.h
+ * Original was a copy of sparc smp.h.  Now heavily modified
+ * for PPC.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996-2001 Cort Dougan <cort@fsmlabs.com>
  */
-
 #ifdef __KERNEL__
 #ifndef _PPC_SMP_H
 #define _PPC_SMP_H
@@ -21,9 +27,11 @@
 	unsigned long *pte_cache;
 	unsigned long pgtable_cache_sz;
 };
-extern struct cpuinfo_PPC cpu_data[NR_CPUS];
 
+extern struct cpuinfo_PPC cpu_data[NR_CPUS];
+extern unsigned long cpu_online_map;
 extern unsigned long smp_proc_in_lock[NR_CPUS];
+extern volatile unsigned long cpu_callin_map[NR_CPUS];
 
 extern void smp_store_cpu_info(int id);
 extern void smp_send_tlb_invalidate(int);
@@ -37,7 +45,6 @@
 /* 1 to 1 mapping on PPC -- Cort */
 #define cpu_logical_map(cpu) (cpu)
 #define cpu_number_map(x) (x)
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
 
 #define smp_processor_id() (current->processor)
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/smplock.h linux/include/asm-ppc/smplock.h
--- v2.4.4/linux/include/asm-ppc/smplock.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/smplock.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.smplock.h 1.7 05/17/01 18:14:25 cort
+ */
+/*
  * <asm/smplock.h>
  *
  * Default SMP lock implementation
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/socket.h linux/include/asm-ppc/socket.h
--- v2.4.4/linux/include/asm-ppc/socket.h	Sat Feb  3 11:26:44 2001
+++ linux/include/asm-ppc/socket.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.socket.h 1.6 05/17/01 18:14:25 cort
+ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/sockios.h linux/include/asm-ppc/sockios.h
--- v2.4.4/linux/include/asm-ppc/sockios.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/sockios.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.sockios.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifndef _ASM_PPC_SOCKIOS_H
 #define _ASM_PPC_SOCKIOS_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/softirq.h linux/include/asm-ppc/softirq.h
--- v2.4.4/linux/include/asm-ppc/softirq.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/softirq.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.softirq.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef __ASM_SOFTIRQ_H
 #define __ASM_SOFTIRQ_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/spd8xx.h linux/include/asm-ppc/spd8xx.h
--- v2.4.4/linux/include/asm-ppc/spd8xx.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/spd8xx.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.spd8xx.h 1.5 05/17/01 18:14:25 cort
+ */
+/*
  * A collection of structures, addresses, and values associated with
  * Speech Design SPD8xxTS boards.
  *
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/spinlock.h linux/include/asm-ppc/spinlock.h
--- v2.4.4/linux/include/asm-ppc/spinlock.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/spinlock.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.spinlock.h 1.5 05/17/01 18:14:25 cort
+ */
 #ifdef __KERNEL__
 #ifndef __ASM_SPINLOCK_H
 #define __ASM_SPINLOCK_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/stat.h linux/include/asm-ppc/stat.h
--- v2.4.4/linux/include/asm-ppc/stat.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/stat.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.stat.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _PPC_STAT_H
 #define _PPC_STAT_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/statfs.h linux/include/asm-ppc/statfs.h
--- v2.4.4/linux/include/asm-ppc/statfs.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/statfs.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.statfs.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _PPC_STATFS_H
 #define _PPC_STATFS_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/string.h linux/include/asm-ppc/string.h
--- v2.4.4/linux/include/asm-ppc/string.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/string.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.string.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _PPC_STRING_H_
 #define _PPC_STRING_H_
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- v2.4.4/linux/include/asm-ppc/system.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/system.h	Mon May 21 15:02:06 2001
@@ -1,9 +1,9 @@
 /*
- * $Id: system.h,v 1.49 1999/09/11 18:37:54 cort Exp $
- *
+ * BK Id: SCCS/s.system.h 1.10 05/17/01 18:14:26 cort
+ */
+/*
  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
  */
-#ifdef __KERNEL__
 #ifndef __PPC_SYSTEM_H
 #define __PPC_SYSTEM_H
 
@@ -47,6 +47,7 @@
 #define smp_wmb()	__asm__ __volatile__("": : :"memory")
 #endif /* CONFIG_SMP */
 
+#ifdef __KERNEL__
 extern void xmon_irq(int, void *, struct pt_regs *);
 extern void xmon(struct pt_regs *excp);
 extern void print_backtrace(unsigned long *);
@@ -115,6 +116,8 @@
 #define local_irq_save(flags)		__save_and_cli(flags)
 #define local_irq_restore(flags)	__restore_flags(flags)
 
+#endif /* __KERNEL__ */
+
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 static __inline__ unsigned long
@@ -122,9 +125,9 @@
 {
 	unsigned long prev;
 
-	__asm__ __volatile__ ("
-1:	lwarx	%0,0,%2
-	stwcx.	%3,0,%2
+	__asm__ __volatile__ ("\n\
+1:	lwarx	%0,0,%2 \n\
+	stwcx.	%3,0,%2 \n\
 	bne-	1b"
 	: "=&r" (prev), "=m" (*(volatile unsigned long *)p)
 	: "r" (p), "r" (val), "m" (*(volatile unsigned long *)p)
@@ -171,11 +174,11 @@
 {
 	int prev;
 
-	__asm__ __volatile__ ("
-1:	lwarx	%0,0,%2
-	cmpw	0,%0,%3
-	bne	2f
-	stwcx.	%4,0,%2
+	__asm__ __volatile__ ("\n\
+1:	lwarx	%0,0,%2 \n\
+	cmpw	0,%0,%3 \n\
+	bne	2f \n\
+	stwcx.	%4,0,%2 \n\
 	bne-	1b\n"
 #ifdef CONFIG_SMP
 "	sync\n"
@@ -216,4 +219,3 @@
   })
 
 #endif /* __PPC_SYSTEM_H */
-#endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/termbits.h linux/include/asm-ppc/termbits.h
--- v2.4.4/linux/include/asm-ppc/termbits.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/termbits.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.termbits.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _PPC_TERMBITS_H
 #define _PPC_TERMBITS_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h
--- v2.4.4/linux/include/asm-ppc/termios.h	Sat Feb  3 20:00:45 2001
+++ linux/include/asm-ppc/termios.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.termios.h 1.8 05/17/01 18:14:26 cort
+ */
 #ifndef _PPC_TERMIOS_H
 #define _PPC_TERMIOS_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/time.h linux/include/asm-ppc/time.h
--- v2.4.4/linux/include/asm-ppc/time.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/time.h	Mon May 21 15:02:06 2001
@@ -1,5 +1,7 @@
 /*
- * $Id: time.h,v 1.12 1999/08/27 04:21:23 cort Exp $
+ * BK Id: SCCS/s.time.h 1.10 05/17/01 18:14:26 cort
+ */
+/*
  * Common time prototypes and such for all ppc machines.
  *
  * Written by Cort Dougan (cort@fsmlabs.com) to merge
@@ -9,6 +11,7 @@
 #ifdef __KERNEL__
 #include <linux/config.h>
 #include <linux/mc146818rtc.h>
+#include <linux/threads.h>
 
 #include <asm/processor.h>
 
@@ -23,7 +26,12 @@
 
 int via_calibrate_decr(void);
 
-/* Accessor functions for the decrementer register. */
+/* Accessor functions for the decrementer register.
+ * The 4xx doesn't even have a decrementer.  I tried to use the
+ * generic timer interrupt code, which seems OK, with the 4xx PIT
+ * in auto-reload mode.  The problem is PIT stops counting when it
+ * hits zero.  If it would wrap, we could use it just like a decrementer.
+ */
 static __inline__ unsigned int get_dec(void)
 {
 #if defined(CONFIG_4xx)
@@ -36,14 +44,12 @@
 static __inline__ void set_dec(unsigned int val)
 {
 #if defined(CONFIG_4xx)
-	mtspr(SPRN_PIT, val);
-#else
-#ifdef CONFIG_8xx_CPU6
+	return;		/* Have to let it auto-reload */
+#elif defined(CONFIG_8xx_CPU6)
 	set_dec_cpu6(val);
 #else
 	mtspr(SPRN_DEC, val);
 #endif
-#endif
 }
 
 /* Accessor functions for the timebase (RTC on 601) registers. */
@@ -59,6 +65,12 @@
 extern __inline__ unsigned long get_tbl(void) {
 	unsigned long tbl;
 	asm volatile("mftb %0" : "=r" (tbl));
+	return tbl;
+}
+
+extern __inline__ unsigned long get_tbu(void) {
+	unsigned long tbl;
+	asm volatile("mftbu %0" : "=r" (tbl));
 	return tbl;
 }
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/timex.h linux/include/asm-ppc/timex.h
--- v2.4.4/linux/include/asm-ppc/timex.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/timex.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.timex.h 1.5 05/17/01 18:14:26 cort
+ */
+/*
  * linux/include/asm-ppc/timex.h
  *
  * ppc architecture timex specifications
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/tlb.h linux/include/asm-ppc/tlb.h
--- v2.4.4/linux/include/asm-ppc/tlb.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/tlb.h	Mon May 21 15:02:06 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.tlb.h 1.5 05/17/01 18:14:26 cort
+ */
 #include <asm-generic/tlb.h>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/tqm8xx.h linux/include/asm-ppc/tqm8xx.h
--- v2.4.4/linux/include/asm-ppc/tqm8xx.h	Thu Apr 12 12:16:36 2001
+++ linux/include/asm-ppc/tqm8xx.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.tqm8xx.h 1.6 05/17/01 18:14:26 cort
+ */
+/*
  * A collection of structures, addresses, and values associated with
  * the TQ Systems TQM8xx(L) modules.  This was originally created for the
  * MBX860, and probably needs revisions for other boards (like the 821).
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/traps.h linux/include/asm-ppc/traps.h
--- v2.4.4/linux/include/asm-ppc/traps.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/traps.h	Mon May 21 15:02:06 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.traps.h 1.5 05/17/01 18:14:26 cort
+ */
 #include <asm-m68k/traps.h>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/types.h linux/include/asm-ppc/types.h
--- v2.4.4/linux/include/asm-ppc/types.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/types.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.types.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _PPC_TYPES_H
 #define _PPC_TYPES_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/uaccess.h linux/include/asm-ppc/uaccess.h
--- v2.4.4/linux/include/asm-ppc/uaccess.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/uaccess.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.uaccess.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_UACCESS_H
 #define _PPC_UACCESS_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/ucontext.h linux/include/asm-ppc/ucontext.h
--- v2.4.4/linux/include/asm-ppc/ucontext.h	Thu Jul 13 09:42:51 2000
+++ linux/include/asm-ppc/ucontext.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.ucontext.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _ASMPPC_UCONTEXT_H
 #define _ASMPPC_UCONTEXT_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/unaligned.h linux/include/asm-ppc/unaligned.h
--- v2.4.4/linux/include/asm-ppc/unaligned.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/unaligned.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.unaligned.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifdef __KERNEL__
 #ifndef __PPC_UNALIGNED_H
 #define __PPC_UNALIGNED_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/uninorth.h linux/include/asm-ppc/uninorth.h
--- v2.4.4/linux/include/asm-ppc/uninorth.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/uninorth.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.uninorth.h 1.7 05/17/01 18:14:26 cort
+ */
+/*
  * uninorth.h: definitions for using the "UniNorth" host bridge chip
  *             from Apple. This chip is used on "Core99" machines
  *
@@ -42,13 +45,13 @@
 /* Version of the UniNorth chip */
 #define UNI_N_VERSION			0x0000		/* Known versions: 3,7 and 8 */
  
-/* This register is used to enable/disable various parts */
+/* This register is used to enable/disable various clocks */
 #define UNI_N_CLOCK_CNTL		0x0020
-#define UNI_N_CLOCK_CNTL_PCI		0x00000001	/* guess ? */
-#define UNI_N_CLOCK_CNTL_GMAC		0x00000002
-#define UNI_N_CLOCK_CNTL_FW		0x00000004	/* guess ? */
+#define UNI_N_CLOCK_CNTL_PCI		0x00000001	/* PCI2 clock control */
+#define UNI_N_CLOCK_CNTL_GMAC		0x00000002	/* GMAC clock control */
+#define UNI_N_CLOCK_CNTL_FW		0x00000004	/* FireWire clock control */
 
-/* Power Management control ? (from Darwin) */
+/* Power Management control */
 #define UNI_N_POWER_MGT			0x0030
 #define UNI_N_POWER_MGT_NORMAL		0x00
 #define UNI_N_POWER_MGT_IDLE2		0x01
@@ -79,5 +82,7 @@
  * CPU has started and will enter it's sleep loop with IP=0
  */
 #define UNI_N_HWINIT_STATE_CPU1_FLAG	0x10000000
+
+/* Uninorth 1.5 rev. has additional perf. monitor registers at 0xf00-0xf50 */
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h
--- v2.4.4/linux/include/asm-ppc/unistd.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/unistd.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.unistd.h 1.7 05/17/01 18:14:26 cort
+ */
 #ifndef _ASM_PPC_UNISTD_H_
 #define _ASM_PPC_UNISTD_H_
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/user.h linux/include/asm-ppc/user.h
--- v2.4.4/linux/include/asm-ppc/user.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/user.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.user.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifdef __KERNEL__
 #ifndef _PPC_USER_H
 #define _PPC_USER_H
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/vc_ioctl.h linux/include/asm-ppc/vc_ioctl.h
--- v2.4.4/linux/include/asm-ppc/vc_ioctl.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/vc_ioctl.h	Mon May 21 15:02:06 2001
@@ -1,3 +1,6 @@
+/*
+ * BK Id: SCCS/s.vc_ioctl.h 1.5 05/17/01 18:14:26 cort
+ */
 #ifndef _LINUX_VC_IOCTL_H
 #define _LINUX_VC_IOCTL_H
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/vga.h linux/include/asm-ppc/vga.h
--- v2.4.4/linux/include/asm-ppc/vga.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/vga.h	Mon May 21 15:02:06 2001
@@ -1,4 +1,7 @@
 /*
+ * BK Id: SCCS/s.vga.h 1.5 05/17/01 18:14:26 cort
+ */
+/*
  *	Access to VGA videoram
  *
  *	(c) 1998 Martin Mares <mj@ucw.cz>
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/walnut.h linux/include/asm-ppc/walnut.h
--- v2.4.4/linux/include/asm-ppc/walnut.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/walnut.h	Mon May 21 15:02:06 2001
@@ -1,13 +1,25 @@
 /*
+ * BK Id: SCCS/s.walnut.h 1.7 05/17/01 18:14:26 cort
+ */
+/*
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
- *    Module name: walnut.h
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405 modifications
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *
+ *    Module name: ppc405.h
  *
  *    Description:
- *	Macros, definitions, and data structures specific to the IBM PowerPC
- *      405GP "Walnut" evaluation board. Anything specific to the processor
- *      itself is defined elsewhere.
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      based boards.
+ *
+ *      This includes:
+ *
+ *         405GP "Walnut" evaluation board
  *
  */
 
@@ -19,12 +31,37 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Walnut" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
 
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_procfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_plb_busfreq;	/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
 
+/* Memory map for the IBM "Walnut" 405GP evaluation board.
+ * Generic 4xx plus RTC.
+ */
+#define WALNUT_RTC_ADDR		((uint)0xf0001000)
+#define WALNUT_RTC_SIZE		((uint)4*1024)
 
 #ifdef __cplusplus
 }
 #endif
+
+/* Generic 4xx type
+*/
+#define _MACH_4xx (_MACH_walnut)
 
 #endif /* __WALNUT_H__ */
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.4/linux/include/asm-ppc/xor.h linux/include/asm-ppc/xor.h
--- v2.4.4/linux/include/asm-ppc/xor.h	Sun Nov 12 19:39:51 2000
+++ linux/include/asm-ppc/xor.h	Mon May 21 15:02:06 2001
@@ -1 +1,4 @@
+/*
+ * BK Id: SCCS/s.xor.h 1.5 05/17/01 18:14:26 cort
+ */
 #include <asm-generic/xor.h>
diff -u --recursive --new-file v2.4.4/linux/include/asm-sh/hd64465_gpio.h linux/include/asm-sh/hd64465_gpio.h
--- v2.4.4/linux/include/asm-sh/hd64465_gpio.h	Wed Apr 11 21:24:52 2001
+++ linux/include/asm-sh/hd64465_gpio.h	Sun May 20 12:11:39 2001
@@ -11,7 +11,6 @@
  * by Greg Banks <gbanks@pocketpenguins.com>
  * (c) 2000 PocketPenguins Inc.
  */
-#include <linux/config.h>
 #include <asm/hd64465.h>
 
 /* Macro to construct a portpin number (used in all
diff -u --recursive --new-file v2.4.4/linux/include/asm-sh/pci.h linux/include/asm-sh/pci.h
--- v2.4.4/linux/include/asm-sh/pci.h	Wed Apr 11 21:24:52 2001
+++ linux/include/asm-sh/pci.h	Wed May 16 10:31:27 2001
@@ -160,7 +160,8 @@
 	return 1;
 }
 
-
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
 
 /* These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc/pci.h linux/include/asm-sparc/pci.h
--- v2.4.4/linux/include/asm-sparc/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-sparc/pci.h	Wed May 16 10:31:27 2001
@@ -113,6 +113,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* __KERNEL__ */
 
 #endif /* __SPARC_PCI_H */
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- v2.4.4/linux/include/asm-sparc64/floppy.h	Sun Mar 25 18:14:21 2001
+++ linux/include/asm-sparc64/floppy.h	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.29 2001/03/24 00:07:23 davem Exp $
+/* $Id: floppy.h,v 1.30 2001/05/11 07:05:38 davem Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -173,11 +173,6 @@
 unsigned long pdma_areasize;
 
 /* Common routines to all controller types on the Sparc. */
-static __inline__ void virtual_dma_init(void)
-{
-	/* nothing... */
-}
-
 static void sun_fd_disable_dma(void)
 {
 	doing_pdma = 0;
@@ -231,7 +226,7 @@
 		once = 1;
 
 		error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, 
-					SA_INTERRUPT, "floppy", NULL);
+					 SA_INTERRUPT, "floppy", NULL);
 
 		return ((error == 0) ? 0 : -1);
 	}
@@ -267,6 +262,7 @@
 
 #ifdef CONFIG_PCI
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #include <asm/ns87303.h>
 
 static struct linux_ebus_dma *sun_pci_fd_ebus_dma;
@@ -583,6 +579,83 @@
 }
 #endif
 
+#ifdef CONFIG_PCI
+#undef ISA_FLOPPY_WORKS
+
+#ifdef ISA_FLOPPY_WORKS
+static unsigned long __init isa_floppy_init(void)
+{
+	struct isa_bridge *isa_br;
+	struct isa_device *isa_dev = NULL;
+
+	for_each_isa(isa_br) {
+		for_each_isadev(isa_dev, isa_br) {
+			if (!strcmp(isa_dev->prom_name, "dma")) {
+				struct isa_device *child = isa_dev->child;
+
+				while (child) {
+					if (!strcmp(child->prom_name, "floppy")) {
+						isa_dev = child;
+						goto isa_done;
+					}
+					child = child->next;
+				}
+			}
+		}
+	}
+isa_done:
+	if (!isa_dev)
+		return 0;
+
+	/* We could use DMA on devices behind the ISA bridge, but...
+	 *
+	 * There is a slight problem.  Normally on x86 kit the x86 processor
+	 * delays I/O port instructions when the ISA bus "dma in progress"
+	 * signal is active.  Well, sparc64 systems do not monitor this
+	 * signal thus we would need to block all I/O port accesses in software
+	 * when a dma transfer is active for some device.
+	 */
+
+	sun_fdc = (struct sun_flpy_controller *)isa_dev->resource.start;
+	FLOPPY_IRQ = isa_dev->irq;
+
+	sun_fdops.fd_inb = sun_pci_fd_inb;
+	sun_fdops.fd_outb = sun_pci_fd_outb;
+
+	can_use_virtual_dma = use_virtual_dma = 1;
+	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+	sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+	sun_fdops.fd_enable_irq = sun_fd_enable_irq;
+	sun_fdops.fd_disable_irq = sun_fd_disable_irq;
+	sun_fdops.fd_request_irq = sun_fd_request_irq;
+	sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+	/* Floppy eject is manual.   Actually, could determine this
+	 * via presence of 'manual' property in OBP node.
+	 */
+	sun_fdops.fd_eject = sun_pci_fd_eject;
+
+        fdc_status = (unsigned long) &sun_fdc->status_82077;
+	FLOPPY_MOTOR_MASK = 0xf0;
+
+	allowed_drive_mask = 0;
+	sun_floppy_types[0] = 0;
+	sun_floppy_types[1] = 4;
+
+	sun_pci_broken_drive = 1;
+	sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+
+	return sun_floppy_types[0];
+}
+#endif /* ISA_FLOPPY_WORKS */
+
+#endif
+
 static unsigned long __init sun_floppy_init(void)
 {
 	char state[128];
@@ -615,8 +688,13 @@
 			}
 		}
 	ebus_done:
-		if (!edev)
+		if (!edev) {
+#ifdef ISA_FLOPPY_WORKS
+			return isa_floppy_init();
+#else
 			return 0;
+#endif
+		}
 
 		prom_getproperty(edev->prom_node, "status",
 				 state, sizeof(state));
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/isa.h linux/include/asm-sparc64/isa.h
--- v2.4.4/linux/include/asm-sparc64/isa.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/isa.h	Wed May 16 10:31:27 2001
@@ -0,0 +1,47 @@
+/* $Id: isa.h,v 1.1 2001/05/11 04:31:55 davem Exp $
+ * isa.h: Sparc64 layer for PCI to ISA bridge devices.
+ *
+ * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __SPARC64_ISA_H
+#define __SPARC64_ISA_H
+
+#include <asm/pbm.h>
+#include <asm/oplib.h>
+
+struct isa_device {
+	struct isa_device	*next;
+	struct isa_device	*child;
+	struct isa_bridge	*bus;
+	int			prom_node;
+	char			prom_name[64];
+	char			compatible[64];
+	struct resource		resource;
+	unsigned int		irq;
+};
+
+struct isa_bridge {
+	struct isa_bridge	*next;
+	struct isa_device	*devices;
+	struct pci_pbm_info	*parent;
+	struct pci_dev		*self;
+	int			index;
+	int			prom_node;
+	char			prom_name[64];
+#define linux_prom_isa_ranges linux_prom_ebus_ranges
+	struct linux_prom_isa_ranges	isa_ranges[PROMREG_MAX];
+	int			num_isa_ranges;
+};
+
+extern struct isa_bridge	*isa_chain;
+
+extern void isa_init(void);
+
+#define for_each_isa(bus)						\
+        for((bus) = isa_chain; (bus); (bus) = (bus)->next)
+
+#define for_each_isadev(dev, bus)					\
+        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+
+#endif /* !(__SPARC64_ISA_H) */
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/parport.h linux/include/asm-sparc64/parport.h
--- v2.4.4/linux/include/asm-sparc64/parport.h	Sun Mar 25 18:14:21 2001
+++ linux/include/asm-sparc64/parport.h	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: parport.h,v 1.10 2001/03/24 00:18:57 davem Exp $
+/* $Id: parport.h,v 1.11 2001/05/11 07:54:24 davem Exp $
  * parport.h: sparc64 specific parport initialization and dma.
  *
  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
@@ -8,6 +8,7 @@
 #define _ASM_SPARC64_PARPORT_H 1
 
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #include <asm/ns87303.h>
 
 #define PARPORT_PC_MAX_PORTS	PARPORT_MAX
@@ -118,6 +119,43 @@
 	return 0;
 }
 
+static int parport_isa_probe(int count)
+{
+	struct isa_bridge *isa_br;
+	struct isa_device *isa_dev;
+
+	for_each_isa(isa_br) {
+		for_each_isadev(isa_dev, isa_br) {
+			struct isa_device *child;
+			unsigned long base;
+
+			if (strcmp(isa_dev->prom_name, "dma"))
+				continue;
+
+			child = isa_dev->child;
+			while (child) {
+				if (!strcmp(child->prom_name, "parallel"))
+					break;
+				child = child->next;
+			}
+			if (!child)
+				continue;
+
+			base = child->resource.start;
+
+			/* No DMA, see commentary in
+			 * asm-sparc64/floppy.h:isa_floppy_init()
+			 */
+			if (parport_pc_probe_port(base, base + 0x400,
+						  child->irq, PARPORT_DMA_NOFIFO,
+						  child->bus->self))
+				count++;
+		}
+	}
+
+	return count;
+}
+
 static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
 	struct linux_ebus *ebus;
@@ -159,6 +197,8 @@
 			}
 		}
 	}
+
+	count = parport_isa_probe(count);
 
 	return count;
 }
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h
--- v2.4.4/linux/include/asm-sparc64/pbm.h	Tue Mar  6 22:44:16 2001
+++ linux/include/asm-sparc64/pbm.h	Wed May 16 10:31:27 2001
@@ -1,4 +1,4 @@
-/* $Id: pbm.h,v 1.25 2001/02/28 03:28:55 davem Exp $
+/* $Id: pbm.h,v 1.26 2001/05/15 08:54:30 davem Exp $
  * pbm.h: UltraSparc PCI controller software state.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -177,6 +177,9 @@
 	 * error logging purposes.
 	 */
 	int				index;
+
+	/* Do the PBMs both exist in the same PCI domain? */
+	int				pbms_same_domain;
 
 	/* The PCI bus modules controlled by us. */
 	struct pci_pbm_info		pbm_A;
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/pci.h linux/include/asm-sparc64/pci.h
--- v2.4.4/linux/include/asm-sparc64/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-sparc64/pci.h	Wed May 16 10:31:27 2001
@@ -3,6 +3,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/fs.h>
+#include <linux/mm.h>
+
 /* Can be used to override the logic in pci_scan_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
@@ -109,6 +112,20 @@
  * you would pass 0x00ffffff as the mask to this function.
  */
 extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask);
+
+/* Return the index of the PCI controller for device PDEV. */
+
+extern int pci_controller_num(struct pci_dev *pdev);
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+#define HAVE_PCI_MMAP
+#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+#define get_pci_unmapped_area get_fb_unmapped_area
+
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			       enum pci_mmap_state mmap_state,
+			       int write_combine);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/semaphore-helper.h linux/include/asm-sparc64/semaphore-helper.h
--- v2.4.4/linux/include/asm-sparc64/semaphore-helper.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/semaphore-helper.h	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-#ifndef _SPARC64_SEMAPHORE_HELPER_H
-#define _SPARC64_SEMAPHORE_HELPER_H
-
-/*
- * SMP- and interrupt-safe semaphore helper functions, sparc64 version.
- *
- * (C) Copyright 1999 David S. Miller (davem@redhat.com)
- * (C) Copyright 1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-#define wake_one_more(__sem)      atomic_inc(&((__sem)->waking));
-#define waking_non_zero(__sem)				\
-({	int __ret;					\
-	__asm__ __volatile__(				\
-"1:	ldsw		[%1], %%g5\n\t"			\
-	"brlez,pt	%%g5, 2f\n\t"			\
-	" mov		0, %0\n\t"			\
-	"sub		%%g5, 1, %%g7\n\t"		\
-	"cas		[%1], %%g5, %%g7\n\t"		\
-	"cmp		%%g5, %%g7\n\t"			\
-	"bne,pn		%%icc, 1b\n\t"			\
-	" mov		1, %0\n"			\
-"2:"	: "=&r" (__ret)					\
-	: "r" (&((__sem)->waking))			\
-	: "g5", "g7", "cc", "memory");			\
-	__ret;						\
-})
-
-#define waking_non_zero_interruptible(__sem, __tsk)	\
-({	int __ret;					\
-	__asm__ __volatile__(				\
-"1:	ldsw		[%1], %%g5\n\t"			\
-	"brlez,pt	%%g5, 2f\n\t"			\
-	" mov		0, %0\n\t"			\
-	"sub		%%g5, 1, %%g7\n\t"		\
-	"cas		[%1], %%g5, %%g7\n\t"		\
-	"cmp		%%g5, %%g7\n\t"			\
-	"bne,pn		%%icc, 1b\n\t"			\
-	" mov		1, %0\n"			\
-"2:"	: "=&r" (__ret)					\
-	: "r" (&((__sem)->waking))			\
-	: "g5", "g7", "cc", "memory");			\
-	if(__ret == 0 && signal_pending(__tsk)) {	\
-		atomic_inc(&((__sem)->count));		\
-		__ret = -EINTR;				\
-	}						\
-	__ret;						\
-})
-
-#define waking_non_zero_trylock(__sem)			\
-({	int __ret;					\
-	__asm__ __volatile__(				\
-"1:	ldsw		[%1], %%g5\n\t"			\
-	"brlez,pt	%%g5, 2f\n\t"			\
-	" mov		1, %0\n\t"			\
-	"sub		%%g5, 1, %%g7\n\t"		\
-	"cas		[%1], %%g5, %%g7\n\t"		\
-	"cmp		%%g5, %%g7\n\t"			\
-	"bne,pn		%%icc, 1b\n\t"			\
-	" mov		0, %0\n"			\
-"2:"	: "=&r" (__ret)					\
-	: "r" (&((__sem)->waking))			\
-	: "g5", "g7", "cc", "memory");			\
-	if(__ret == 1)					\
-		atomic_inc(&((__sem)->count));		\
-	__ret;						\
-})
-
-#endif /* !(_SPARC64_SEMAPHORE_HELPER_H) */
diff -u --recursive --new-file v2.4.4/linux/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h
--- v2.4.4/linux/include/asm-sparc64/semaphore.h	Thu Apr 26 22:17:26 2001
+++ linux/include/asm-sparc64/semaphore.h	Sun May 20 11:32:08 2001
@@ -1,52 +1,40 @@
 #ifndef _SPARC64_SEMAPHORE_H
 #define _SPARC64_SEMAPHORE_H
 
-/* These are actually reasonable on the V9. */
+/* These are actually reasonable on the V9.
+ *
+ * See asm-ppc/semaphore.h for implementation commentary,
+ * only sparc64 specific issues are commented here.
+ */
 #ifdef __KERNEL__
 
 #include <asm/atomic.h>
-#include <asm/bitops.h>
 #include <asm/system.h>
 #include <linux/wait.h>
 #include <linux/rwsem.h>
 
 struct semaphore {
 	atomic_t count;
-	atomic_t waking;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, count) \
+	{ ATOMIC_INIT(count), \
+	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
 
 #define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
+	__SEMAPHORE_INITIALIZER(name, 1)
 
-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX_LOCKED(name)	__DECLARE_SEMAPHORE_GENERIC(name, 0)
 
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
 {
 	atomic_set(&sem->count, val);
-	atomic_set(&sem->waking, 0);
 	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -61,143 +49,179 @@
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
-extern int  __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
-extern __inline__ void down(struct semaphore * sem)
+static __inline__ void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__asm__ __volatile__(
-"	1:	lduw	[%0], %%g5\n"
-"		sub	%%g5, 1, %%g7\n"
-"		cas	[%0], %%g5, %%g7\n"
-"		cmp	%%g5, %%g7\n"
-"		bne,pn	%%icc, 1b\n"
-"		 cmp	%%g7, 1\n"
-"		bl,pn	%%icc, 3f\n"
-"		 membar	#StoreStore\n"
-"	2:\n"
-"		.subsection 2\n"
-"	3:	mov	%0, %%g5\n"
-"		save	%%sp, -160, %%sp\n"
-"		mov	%%g1, %%l1\n"
-"		mov	%%g2, %%l2\n"
-"		mov	%%g3, %%l3\n"
-"		call	%1\n"
-"		 mov	%%g5, %%o0\n"
-"		mov	%%l1, %%g1\n"
-"		mov	%%l2, %%g2\n"
-"		ba,pt	%%xcc, 2b\n"
-"		 restore %%l3, %%g0, %%g3\n"
-"		.previous\n"
+	/* This atomically does:
+	 * 	old_val = sem->count;
+	 *	new_val = sem->count - 1;
+	 *	sem->count = new_val;
+	 *	if (old_val < 1)
+	 *		__down(sem);
+	 *
+	 * The (old_val < 1) test is equivalent to
+	 * the more straightforward (new_val < 0),
+	 * but it is easier to test the former because
+	 * of how the CAS instruction works.
+	 */
+
+	__asm__ __volatile__("\n"
+"	! down sem(%0)\n"
+"1:	lduw	[%0], %%g5\n"
+"	sub	%%g5, 1, %%g7\n"
+"	cas	[%0], %%g5, %%g7\n"
+"	cmp	%%g5, %%g7\n"
+"	bne,pn	%%icc, 1b\n"
+"	 cmp	%%g7, 1\n"
+"	bl,pn	%%icc, 3f\n"
+"	 membar	#StoreStore\n"
+"2:\n"
+"	.subsection 2\n"
+"3:	mov	%0, %%g5\n"
+"	save	%%sp, -160, %%sp\n"
+"	mov	%%g1, %%l1\n"
+"	mov	%%g2, %%l2\n"
+"	mov	%%g3, %%l3\n"
+"	call	%1\n"
+"	 mov	%%g5, %%o0\n"
+"	mov	%%l1, %%g1\n"
+"	mov	%%l2, %%g2\n"
+"	ba,pt	%%xcc, 2b\n"
+"	 restore %%l3, %%g0, %%g3\n"
+"	.previous\n"
 	: : "r" (sem), "i" (__down)
 	: "g5", "g7", "memory", "cc");
 }
 
-extern __inline__ int down_interruptible(struct semaphore *sem)
+static __inline__ int down_interruptible(struct semaphore *sem)
 {
 	int ret = 0;
 	
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__asm__ __volatile__(
-"	1:	lduw	[%2], %%g5\n"
-"		sub	%%g5, 1, %%g7\n"
-"		cas	[%2], %%g5, %%g7\n"
-"		cmp	%%g5, %%g7\n"
-"		bne,pn	%%icc, 1b\n"
-"		 cmp	%%g7, 1\n"
-"		bl,pn	%%icc, 3f\n"
-"		 membar	#StoreStore\n"
-"	2:\n"
-"		.subsection 2\n"
-"	3:	mov	%2, %%g5\n"
-"		save	%%sp, -160, %%sp\n"
-"		mov	%%g1, %%l1\n"
-"		mov	%%g2, %%l2\n"
-"		mov	%%g3, %%l3\n"
-"		call	%3\n"
-"		 mov	%%g5, %%o0\n"
-"		mov	%%l1, %%g1\n"
-"		mov	%%l2, %%g2\n"
-"		mov	%%l3, %%g3\n"
-"		ba,pt	%%xcc, 2b\n"
-"		 restore %%o0, %%g0, %0\n"
-"		.previous\n"
+	/* This atomically does:
+	 * 	old_val = sem->count;
+	 *	new_val = sem->count - 1;
+	 *	sem->count = new_val;
+	 *	if (old_val < 1)
+	 *		ret = __down_interruptible(sem);
+	 *
+	 * The (old_val < 1) test is equivalent to
+	 * the more straightforward (new_val < 0),
+	 * but it is easier to test the former because
+	 * of how the CAS instruction works.
+	 */
+
+	__asm__ __volatile__("\n"
+"	! down_interruptible sem(%2) ret(%0)\n"
+"1:	lduw	[%2], %%g5\n"
+"	sub	%%g5, 1, %%g7\n"
+"	cas	[%2], %%g5, %%g7\n"
+"	cmp	%%g5, %%g7\n"
+"	bne,pn	%%icc, 1b\n"
+"	 cmp	%%g7, 1\n"
+"	bl,pn	%%icc, 3f\n"
+"	 membar	#StoreStore\n"
+"2:\n"
+"	.subsection 2\n"
+"3:	mov	%2, %%g5\n"
+"	save	%%sp, -160, %%sp\n"
+"	mov	%%g1, %%l1\n"
+"	mov	%%g2, %%l2\n"
+"	mov	%%g3, %%l3\n"
+"	call	%3\n"
+"	 mov	%%g5, %%o0\n"
+"	mov	%%l1, %%g1\n"
+"	mov	%%l2, %%g2\n"
+"	mov	%%l3, %%g3\n"
+"	ba,pt	%%xcc, 2b\n"
+"	 restore %%o0, %%g0, %0\n"
+"	.previous\n"
 	: "=r" (ret)
 	: "0" (ret), "r" (sem), "i" (__down_interruptible)
 	: "g5", "g7", "memory", "cc");
 	return ret;
 }
 
-extern inline int down_trylock(struct semaphore *sem)
+static __inline__ int down_trylock(struct semaphore *sem)
 {
-	int ret = 0;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__asm__ __volatile__(
-"	1:	lduw	[%2], %%g5\n"
-"		sub	%%g5, 1, %%g7\n"
-"		cas	[%2], %%g5, %%g7\n"
-"		cmp	%%g5, %%g7\n"
-"		bne,pn	%%icc, 1b\n"
-"		 cmp	%%g7, 1\n"
-"		bl,pn	%%icc, 3f\n"
-"		 membar	#StoreStore\n"
-"	2:\n"
-"		.subsection 2\n"
-"	3:	mov	%2, %%g5\n"
-"		save	%%sp, -160, %%sp\n"
-"		mov	%%g1, %%l1\n"
-"		mov	%%g2, %%l2\n"
-"		mov	%%g3, %%l3\n"
-"		call	%3\n"
-"		 mov	%%g5, %%o0\n"
-"		mov	%%l1, %%g1\n"
-"		mov	%%l2, %%g2\n"
-"		mov	%%l3, %%g3\n"
-"		ba,pt	%%xcc, 2b\n"
-"		 restore %%o0, %%g0, %0\n"
-"		.previous\n"
-	: "=r" (ret)
-	: "0" (ret), "r" (sem), "i" (__down_trylock)
+	int ret;
+
+	/* This atomically does:
+	 * 	old_val = sem->count;
+	 *	new_val = sem->count - 1;
+	 *	if (old_val < 1) {
+	 *		ret = 1;
+	 *	} else {
+	 *		sem->count = new_val;
+	 *		ret = 0;
+	 *	}
+	 *
+	 * The (old_val < 1) test is equivalent to
+	 * the more straightforward (new_val < 0),
+	 * but it is easier to test the former because
+	 * of how the CAS instruction works.
+	 */
+
+	__asm__ __volatile__("\n"
+"	! down_trylock sem(%1) ret(%0)\n"
+"1:	lduw	[%1], %%g5\n"
+"	sub	%%g5, 1, %%g7\n"
+"	cmp	%%g5, 1\n"
+"	bl,pn	%%icc, 2f\n"
+"	 mov	1, %0\n"
+"	cas	[%1], %%g5, %%g7\n"
+"	cmp	%%g5, %%g7\n"
+"	bne,pn	%%icc, 1b\n"
+"	 mov	0, %0\n"
+"	membar	#StoreStore\n"
+"2:\n"
+	: "=&r" (ret)
+	: "r" (sem)
 	: "g5", "g7", "memory", "cc");
+
 	return ret;
 }
 
-extern __inline__ void up(struct semaphore * sem)
+static __inline__ void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__asm__ __volatile__(
-"		membar	#StoreLoad | #LoadLoad\n"
-"	1:	lduw	[%0], %%g5\n"
-"		add	%%g5, 1, %%g7\n"
-"		cas	[%0], %%g5, %%g7\n"
-"		cmp	%%g5, %%g7\n"
-"		bne,pn	%%icc, 1b\n"
-"		 addcc	%%g7, 1, %%g0\n"
-"		ble,pn	%%icc, 3f\n"
-"		 nop\n"
-"	2:\n"
-"		.subsection 2\n"
-"	3:	mov	%0, %%g5\n"
-"		save	%%sp, -160, %%sp\n"
-"		mov	%%g1, %%l1\n"
-"		mov	%%g2, %%l2\n"
-"		mov	%%g3, %%l3\n"
-"		call	%1\n"
-"		 mov	%%g5, %%o0\n"
-"		mov	%%l1, %%g1\n"
-"		mov	%%l2, %%g2\n"
-"		ba,pt	%%xcc, 2b\n"
-"		 restore %%l3, %%g0, %%g3\n"
-"		.previous\n"
+	/* This atomically does:
+	 * 	old_val = sem->count;
+	 *	new_val = sem->count + 1;
+	 *	sem->count = new_val;
+	 *	if (old_val < 0)
+	 *		__up(sem);
+	 *
+	 * The (old_val < 0) test is equivalent to
+	 * the more straightforward (new_val <= 0),
+	 * but it is easier to test the former because
+	 * of how the CAS instruction works.
+	 */
+
+	__asm__ __volatile__("\n"
+"	! up sem(%0)\n"
+"	membar	#StoreLoad | #LoadLoad\n"
+"1:	lduw	[%0], %%g5\n"
+"	add	%%g5, 1, %%g7\n"
+"	cas	[%0], %%g5, %%g7\n"
+"	cmp	%%g5, %%g7\n"
+"	bne,pn	%%icc, 1b\n"
+"	 addcc	%%g7, 1, %%g0\n"
+"	ble,pn	%%icc, 3f\n"
+"	 nop\n"
+"2:\n"
+"	.subsection 2\n"
+"3:	mov	%0, %%g5\n"
+"	save	%%sp, -160, %%sp\n"
+"	mov	%%g1, %%l1\n"
+"	mov	%%g2, %%l2\n"
+"	mov	%%g3, %%l3\n"
+"	call	%1\n"
+"	 mov	%%g5, %%o0\n"
+"	mov	%%l1, %%g1\n"
+"	mov	%%l2, %%g2\n"
+"	ba,pt	%%xcc, 2b\n"
+"	 restore %%l3, %%g0, %%g3\n"
+"	.previous\n"
 	: : "r" (sem), "i" (__up)
 	: "g5", "g7", "memory", "cc");
 }
diff -u --recursive --new-file v2.4.4/linux/include/linux/b1lli.h linux/include/linux/b1lli.h
--- v2.4.4/linux/include/linux/b1lli.h	Mon Mar 26 15:38:19 2001
+++ linux/include/linux/b1lli.h	Sat May 19 17:54:14 2001
@@ -1,77 +1,9 @@
 /*
- * $Id: b1lli.h,v 1.8.8.1 2001/03/15 09:58:30 kai Exp $
+ * $Id: b1lli.h,v 1.8.8.2 2001/05/17 20:41:52 kai Exp $
  *
  * ISDN lowlevel-module for AVM B1-card.
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- * $Log: b1lli.h,v $
- * Revision 1.8.8.1  2001/03/15 09:58:30  kai
- * spelling fix
- *
- * Revision 1.8  1999/07/01 15:26:54  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
- *
- * Revision 1.7  1999/06/21 15:24:25  calle
- * extend information in /proc.
- *
- * Revision 1.6  1999/04/15 19:49:36  calle
- * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
- *
- * Revision 1.5  1998/10/25 14:50:28  fritz
- * Backported from MIPS (Cobalt).
- *
- * Revision 1.4  1998/03/29 16:05:02  calle
- * changes from 2.0 tree merged.
- *
- * Revision 1.1.2.9  1998/03/20 14:30:02  calle
- * added cardnr to detect if you try to add same T1 to different io address.
- * change number of nccis depending on number of channels.
- *
- * Revision 1.1.2.8  1998/03/04 17:32:33  calle
- * Changes for T1.
- *
- * Revision 1.1.2.7  1998/02/27 15:38:29  calle
- * T1 running with slow link.
- *
- * Revision 1.1.2.6  1998/02/24 17:57:36  calle
- * changes for T1.
- *
- * Revision 1.3  1998/01/31 10:54:37  calle
- * include changes for PCMCIA cards from 2.0 version
- *
- * Revision 1.2  1997/12/10 19:38:42  calle
- * get changes from 2.0 tree
- *
- * Revision 1.1.2.2  1997/11/26 16:57:26  calle
- * more changes for B1/M1/T1.
- *
- * Revision 1.1.2.1  1997/11/26 10:47:01  calle
- * prepared for M1 (Mobile) and T1 (PMX) cards.
- * prepared to set configuration after load to support other D-channel
- * protocols, point-to-point and leased lines.
- *
- * Revision 1.1  1997/03/04 21:27:32  calle
- * First version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
  *
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/b1pcmcia.h linux/include/linux/b1pcmcia.h
--- v2.4.4/linux/include/linux/b1pcmcia.h	Thu Aug 12 09:42:33 1999
+++ linux/include/linux/b1pcmcia.h	Sat May 19 17:54:14 2001
@@ -1,27 +1,10 @@
 /*
- * $Id: b1pcmcia.h,v 1.1 1999/07/01 15:26:56 calle Exp $
+ * $Id: b1pcmcia.h,v 1.1.8.1 2001/05/17 20:41:52 kai Exp $
  *
  * Exported functions of module b1pcmcia to be called by
  * avm_cs card services module.
  *
  * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
- *
- * $Log: b1pcmcia.h,v $
- * Revision 1.1  1999/07/01 15:26:56  calle
- * complete new version (I love it):
- * + new hardware independed "capi_driver" interface that will make it easy to:
- *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
- *   - write a CAPI-2.0 for the passive cards
- *   - support serial link CAPI-2.0 boxes.
- * + wrote "capi_driver" for all supported cards.
- * + "capi_driver" (supported cards) now have to be configured with
- *   make menuconfig, in the past all supported cards where included
- *   at once.
- * + new and better informations in /proc/capi/
- * + new ioctl to switch trace of capi messages per controller
- *   using "avmcapictrl trace [contr] on|off|...."
- * + complete testcircle with all supported cards and also the
- *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
  *
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/cciss_ioctl.h linux/include/linux/cciss_ioctl.h
--- v2.4.4/linux/include/linux/cciss_ioctl.h	Mon Dec 11 12:50:40 2000
+++ linux/include/linux/cciss_ioctl.h	Tue May  1 16:05:00 2001
@@ -80,25 +80,28 @@
 
 #define CISS_MAX_LUN	16	
 
+#define LEVEL2LUN   1   // index into Target(x) structure, due to byte swapping
+#define LEVEL3LUN   0
+
 #pragma pack(1)
 
 //Command List Structure
 typedef union _SCSI3Addr_struct {
    struct {
+    BYTE Dev;
     BYTE Bus:6;
     BYTE Mode:2;        // b00
-    BYTE Dev;
   } PeripDev;
    struct {
+    BYTE DevLSB;
     BYTE DevMSB:6;
     BYTE Mode:2;        // b01
-    BYTE DevLSB;
   } LogDev;
    struct {
-    BYTE Targ:6;
-    BYTE Mode:2;        // b10
     BYTE Dev:5;
     BYTE Bus:3;
+    BYTE Targ:6;
+    BYTE Mode:2;        // b10
   } LogUnit;
 } SCSI3Addr_struct;
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/compiler.h linux/include/linux/compiler.h
--- v2.4.4/linux/include/linux/compiler.h	Sun Apr 22 19:10:53 2001
+++ linux/include/linux/compiler.h	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-#ifndef __LINUX_COMPILER_H
-#define __LINUX_COMPILER_H
-
-/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
-   a mechanism by which the user can annotate likely branch directions and
-   expect the blocks to be reordered appropriately.  Define __builtin_expect
-   to nothing for earlier compilers.  */
-
-#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
-#define __builtin_expect(x, expected_value) (x)
-#endif
-
-#endif /* __LINUX_COMPILER_H */
diff -u --recursive --new-file v2.4.4/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.4.4/linux/include/linux/fs.h	Fri Apr 27 15:48:28 2001
+++ linux/include/linux/fs.h	Thu May 24 15:02:06 2001
@@ -121,6 +121,12 @@
 #define MS_RMT_MASK	(MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|\
 			MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME)
 
+/*
+ * Old magic mount flag and mask
+ */
+#define MS_MGC_VAL 0xC0ED0000
+#define MS_MGC_MSK 0xffff0000
+
 /* Inode flags - they have nothing to superblock flags now */
 
 #define S_SYNC		1	/* Writes are synced at once */
@@ -378,6 +384,14 @@
 	int			gfp_mask;	/* how to allocate the pages */
 };
 
+struct char_device {
+	struct list_head	hash;
+	atomic_t		count;
+	dev_t			dev;
+	atomic_t		openers;
+	struct semaphore	sem;
+};
+
 struct block_device {
 	struct list_head	bd_hash;
 	atomic_t		bd_count;
@@ -420,8 +434,10 @@
 	struct address_space	*i_mapping;
 	struct address_space	i_data;	
 	struct dquot		*i_dquot[MAXQUOTAS];
+	/* These three should probably be a union */
 	struct pipe_inode_info	*i_pipe;
 	struct block_device	*i_bdev;
+	struct char_device	*i_cdev;
 
 	unsigned long		i_dnotify_mask; /* Directory notify events */
 	struct dnotify_struct	*i_dnotify; /* for directory notifications */
@@ -646,7 +662,6 @@
 	kdev_t			s_dev;
 	unsigned long		s_blocksize;
 	unsigned char		s_blocksize_bits;
-	unsigned char		s_lock;
 	unsigned char		s_dirt;
 	unsigned long long	s_maxbytes;	/* Max file size */
 	struct file_system_type	*s_type;
@@ -656,7 +671,7 @@
 	unsigned long		s_magic;
 	struct dentry		*s_root;
 	struct rw_semaphore	s_umount;
-	wait_queue_head_t	s_wait;
+	struct semaphore	s_lock;
 
 	struct list_head	s_dirty;	/* dirty inodes */
 	struct list_head	s_locked_inodes;/* inodes being synced */
@@ -893,10 +908,10 @@
 extern int register_filesystem(struct file_system_type *);
 extern int unregister_filesystem(struct file_system_type *);
 extern struct vfsmount *kern_mount(struct file_system_type *);
-extern void kern_umount(struct vfsmount *);
 extern int may_umount(struct vfsmount *);
 extern long do_mount(char *, char *, char *, unsigned long, void *);
 
+#define kern_umount mntput
 
 extern int vfs_statfs(struct super_block *, struct statfs *);
 
@@ -977,6 +992,8 @@
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern void bdput(struct block_device *);
+extern struct char_device *cdget(dev_t);
+extern void cdput(struct char_device *);
 extern int blkdev_open(struct inode *, struct file *);
 extern struct file_operations def_blk_fops;
 extern struct file_operations def_fifo_fops;
@@ -1086,6 +1103,7 @@
 extern void balance_dirty(kdev_t);
 extern int check_disk_change(kdev_t);
 extern int invalidate_inodes(struct super_block *);
+extern int invalidate_device(kdev_t, int);
 extern void invalidate_inode_pages(struct inode *);
 extern void invalidate_inode_buffers(struct inode *);
 #define invalidate_buffers(dev)	__invalidate_buffers((dev), 0)
@@ -1198,7 +1216,7 @@
 extern void path_release(struct nameidata *);
 extern int follow_down(struct vfsmount **, struct dentry **);
 extern int follow_up(struct vfsmount **, struct dentry **);
-extern struct dentry * lookup_one(const char *, struct dentry *);
+extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
 #define user_path_walk(name,nd)	 __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
 #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
@@ -1272,6 +1290,7 @@
 int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
 
+extern int waitfor_one_page(struct page*);
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
@@ -1294,6 +1313,15 @@
 extern struct file_system_type *get_fs_type(const char *name);
 extern struct super_block *get_super(kdev_t);
 extern void put_super(kdev_t);
+static inline int is_mounted(kdev_t dev)
+{
+	struct super_block *sb = get_super(dev);
+	if (sb) {
+		/* drop_super(sb); will go here */
+		return 1;
+	}
+	return 0;
+}
 unsigned long generate_cluster(kdev_t, int b[], int);
 unsigned long generate_cluster_swab32(kdev_t, int b[], int);
 extern kdev_t ROOT_DEV;
diff -u --recursive --new-file v2.4.4/linux/include/linux/hysdn_if.h linux/include/linux/hysdn_if.h
--- v2.4.4/linux/include/linux/hysdn_if.h	Mon Mar 26 15:38:19 2001
+++ linux/include/linux/hysdn_if.h	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: hysdn_if.h,v 1.1.8.1 2001/03/13 16:17:10 kai Exp $
+/* $Id: hysdn_if.h,v 1.1.8.2 2001/05/17 20:41:52 kai Exp $
 
  * Linux driver for HYSDN cards, ioctl definitions shared by hynetmgr and driver.
  * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
@@ -18,15 +18,6 @@
  * 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.
- *
- * $Log: hysdn_if.h,v $
- * Revision 1.1.8.1  2001/03/13 16:17:10  kai
- * spelling fixes from 2.4.3-pre
- *
- * Revision 1.1  2000/02/10 19:47:50  werner
- *
- * Initial release
- *
  *
  */
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/i2o.h linux/include/linux/i2o.h
--- v2.4.4/linux/include/linux/i2o.h	Mon Dec 11 13:20:00 2000
+++ linux/include/linux/i2o.h	Tue May  1 16:17:18 2001
@@ -69,6 +69,7 @@
 
 	struct i2o_controller *controller;	/* Controlling IOP */
 	struct i2o_device *next;	/* Chain */
+	struct i2o_device *prev;
 	char dev_name[8];		/* linux /dev name if available */
 };
 
@@ -78,6 +79,9 @@
 struct i2o_pci
 {
 	int irq;
+	int queue_buggy:1;	/* Don't send a lot of messages */
+	int short_req:1;	/* Use small block sizes	*/
+	int dpt:1;		/* Don't quiesce		*/
 #ifdef CONFIG_MTRR
 	int mtrr_reg0;
 	int mtrr_reg1;
@@ -120,6 +124,8 @@
 
 	u32 mem_offset;				/* MFA offset */
 	u32 mem_phys;				/* MFA physical */
+	
+	int battery:1;				/* Has a battery backup */
 
 	struct proc_dir_entry* proc_entry;	/* /proc dir */
 
@@ -295,6 +301,7 @@
 
 extern int i2o_post_this(struct i2o_controller *, u32 *, int);
 extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int);
+extern int i2o_post_wait_mem(struct i2o_controller *, u32 *, int, int, void *, void *);
 
 extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *, int);
 extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *, int);
diff -u --recursive --new-file v2.4.4/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.4.4/linux/include/linux/ide.h	Fri Apr 27 15:48:56 2001
+++ linux/include/linux/ide.h	Tue May 22 11:18:52 2001
@@ -648,6 +648,7 @@
 extern	ide_module_t	*ide_modules;
 extern	ide_module_t	*ide_probe;
 #endif
+extern int noautodma;
 
 /*
  * We need blk.h, but we replace its end_request by our own version.
diff -u --recursive --new-file v2.4.4/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.4.4/linux/include/linux/inetdevice.h	Mon Aug 23 10:01:02 1999
+++ linux/include/linux/inetdevice.h	Wed May 16 10:21:45 2001
@@ -17,6 +17,7 @@
 	int	forwarding;
 	int	mc_forwarding;
 	int	tag;
+	int     arp_filter;
 	void	*sysctl;
 };
 
@@ -53,6 +54,8 @@
 	  (ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \
 	 || (!IN_DEV_FORWARD(in_dev) && \
 	  (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
+
+#define IN_DEV_ARPFILTER(in_dev)	(ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
 
 struct in_ifaddr
 {
diff -u --recursive --new-file v2.4.4/linux/include/linux/init.h linux/include/linux/init.h
--- v2.4.4/linux/include/linux/init.h	Fri Apr 27 15:48:19 2001
+++ linux/include/linux/init.h	Tue May 22 11:17:35 2001
@@ -34,6 +34,8 @@
  * Don't forget to initialize data not at file scope, i.e. within a function,
  * as gcc otherwise puts the data into the bss section and not into the init
  * section.
+ * 
+ * Also note, that this data cannot be "const".
  */
 
 #ifndef MODULE
diff -u --recursive --new-file v2.4.4/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.4.4/linux/include/linux/isdn.h	Thu Apr 19 22:30:09 2001
+++ linux/include/linux/isdn.h	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.111.6.5 2001/04/20 02:40:48 keil Exp $
+/* $Id: isdn.h,v 1.111.6.6 2001/05/17 21:15:34 kai Exp $
 
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -22,55 +22,11 @@
  *
  */
 
-#ifndef isdn_h
-#define isdn_h
+#ifndef __ISDN_H__
+#define __ISDN_H__
 
-#ifdef __KERNEL__
-#include <linux/config.h>
-#endif
 #include <linux/ioctl.h>
 
-#define ISDN_TTY_MAJOR    43
-#define ISDN_TTYAUX_MAJOR 44
-#define ISDN_MAJOR        45
-
-/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for
- * physical Channel-Mapping, so they MUST NOT be changed without changing
- * the correspondent code in isdn.c
- */
-
-#ifdef USE_MINIMUM_MEM
-/* Save memory */
-#define ISDN_MAX_DRIVERS    2
-#define ISDN_MAX_CHANNELS   8
-#else
-#define ISDN_MAX_DRIVERS    32
-#define ISDN_MAX_CHANNELS   64
-#endif
-#define ISDN_MINOR_B        0
-#define ISDN_MINOR_BMAX     (ISDN_MAX_CHANNELS-1)
-#define ISDN_MINOR_CTRL     64
-#define ISDN_MINOR_CTRLMAX  (64 + (ISDN_MAX_CHANNELS-1))
-#define ISDN_MINOR_PPP      128
-#define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
-#define ISDN_MINOR_STATUS   255
-
-#undef CONFIG_ISDN_WITH_ABC_CALLB
-#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK
-#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
-#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
-#undef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
-#undef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
-#undef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE
-#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
-#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
-#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND
-#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
-#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
-#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
-#undef CONFIG_ISDN_WITH_ABC_IPTABLES_NETFILTER
-
-
 /* New ioctl-codes */
 #define IIOCNETAIF  _IO('I',1)
 #define IIOCNETDIF  _IO('I',2)
@@ -122,6 +78,7 @@
 #define ISDN_NET_ENCAP_CISCOHDLCK 6 /* With SLARP and keepalive    */
 #define ISDN_NET_ENCAP_X25IFACE   7 /* Documentation/networking/x25-iface.txt*/
 #define ISDN_NET_ENCAP_MAX_ENCAP  ISDN_NET_ENCAP_X25IFACE
+
 /* Facility which currently uses an ISDN-channel */
 #define ISDN_USAGE_NONE       0
 #define ISDN_USAGE_RAW        1
@@ -150,12 +107,6 @@
 } isdn_ioctl_struct;
 
 typedef struct {
-  unsigned long isdndev;
-  unsigned long atmodem[ISDN_MAX_CHANNELS];
-  unsigned long info[ISDN_MAX_CHANNELS];
-} debugvar_addr;
-
-typedef struct {
   char name[10];
   char phone[ISDN_MSNLEN];
   int  outgoing;
@@ -189,14 +140,15 @@
   int  dialmode;     /* Flag: off / on / auto                 */
 } isdn_net_ioctl_cfg;
 
-#define ISDN_NET_DIALMODE_MASK 0xC0  /* bits for status                   */
-#define  ISDN_NET_DM_OFF	0x00    /* this interface is stopped      */
-#define  ISDN_NET_DM_MANUAL	0x40    /* this interface is on (manual)  */
-#define  ISDN_NET_DM_AUTO	0x80    /* this interface is autodial     */
+#define ISDN_NET_DIALMODE_MASK  0xC0    /* bits for status                */
+#define ISDN_NET_DM_OFF	        0x00    /* this interface is stopped      */
+#define ISDN_NET_DM_MANUAL	0x40    /* this interface is on (manual)  */
+#define ISDN_NET_DM_AUTO	0x80    /* this interface is autodial     */
 #define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK)
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
@@ -220,6 +172,31 @@
 #include <linux/skbuff.h>
 #include <linux/tcp.h>
 
+#define ISDN_TTY_MAJOR    43
+#define ISDN_TTYAUX_MAJOR 44
+#define ISDN_MAJOR        45
+
+/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for
+ * physical Channel-Mapping, so they MUST NOT be changed without changing
+ * the correspondent code in isdn.c
+ */
+
+#ifdef CONFIG_COBALT_MICRO_SERVER
+/* Save memory */
+#define ISDN_MAX_DRIVERS    2
+#define ISDN_MAX_CHANNELS   8
+#else
+#define ISDN_MAX_DRIVERS    32
+#define ISDN_MAX_CHANNELS   64
+#endif
+#define ISDN_MINOR_B        0
+#define ISDN_MINOR_BMAX     (ISDN_MAX_CHANNELS-1)
+#define ISDN_MINOR_CTRL     64
+#define ISDN_MINOR_CTRLMAX  (64 + (ISDN_MAX_CHANNELS-1))
+#define ISDN_MINOR_PPP      128
+#define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
+#define ISDN_MINOR_STATUS   255
+
 #ifdef CONFIG_ISDN_PPP
 
 #ifdef CONFIG_ISDN_PPP_VJ
@@ -682,4 +659,5 @@
 #define MIN(a,b) ((a<b)?a:b)
 #define MAX(a,b) ((a>b)?a:b)
 #endif /* __KERNEL__ */
-#endif /* isdn_h */
+
+#endif /* __ISDN_H__ */
diff -u --recursive --new-file v2.4.4/linux/include/linux/isdn_ppp.h linux/include/linux/isdn_ppp.h
--- v2.4.4/linux/include/linux/isdn_ppp.h	Thu Apr 19 22:30:09 2001
+++ linux/include/linux/isdn_ppp.h	Sat May 19 17:54:14 2001
@@ -3,9 +3,6 @@
 #ifndef _LINUX_ISDN_PPP_H
 #define _LINUX_ISDN_PPP_H
 
-#ifdef __KERNEL__
-#include <linux/config.h>
-#endif
 
 #define CALLTYPE_INCOMING 0x1
 #define CALLTYPE_OUTGOING 0x2
@@ -46,13 +43,6 @@
 #define SC_LINK_DECOMP_DISCARD	0x40
 #define SC_LINK_COMP_DISCARD	0x80
 
-#define DECOMP_ERR_NOMEM	(-10)
-
-#define MP_END_FRAG    0x40
-#define MP_BEGIN_FRAG  0x80
-
-#define MP_MAX_QUEUE_LEN	16
-
 #define ISDN_PPP_COMP_MAX_OPTIONS 16
 
 #define IPPP_COMP_FLAG_XMIT 0x1
@@ -66,6 +56,17 @@
 };
 
 #ifdef __KERNEL__
+
+
+#include <linux/config.h>
+
+
+#define DECOMP_ERR_NOMEM	(-10)
+
+#define MP_END_FRAG    0x40
+#define MP_BEGIN_FRAG  0x80
+
+#define MP_MAX_QUEUE_LEN	16
 
 /*
  * We need a way for the decompressor to influence the generation of CCP
diff -u --recursive --new-file v2.4.4/linux/include/linux/isdnif.h linux/include/linux/isdnif.h
--- v2.4.4/linux/include/linux/isdnif.h	Thu Apr 19 22:30:09 2001
+++ linux/include/linux/isdnif.h	Sat May 19 17:54:14 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.37 2000/11/19 17:01:54 kai Exp $
+/* $Id: isdnif.h,v 1.37.6.2 2001/05/17 21:15:34 kai Exp $
 
  * Linux ISDN subsystem
  *
@@ -23,12 +23,9 @@
  *
  */
 
-#ifndef isdnif_h
-#define isdnif_h
+#ifndef __ISDNIF_H__
+#define __ISDNIF_H__
 
-#ifdef __KERNEL__
-#include <linux/config.h>
-#endif
 
 /*
  * Values for general protocol-selection
@@ -69,6 +66,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <linux/skbuff.h>
 
 /***************************************************************************/
@@ -562,4 +560,5 @@
 #include <asm/uaccess.h>
 
 #endif /* __KERNEL__ */
-#endif /* isdnif_h */
+
+#endif /* __ISDNIF_H__ */
diff -u --recursive --new-file v2.4.4/linux/include/linux/iso_fs.h linux/include/linux/iso_fs.h
--- v2.4.4/linux/include/linux/iso_fs.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/iso_fs.h	Tue May 22 11:17:57 2001
@@ -165,14 +165,46 @@
 #define ISOFS_SUPER_MAGIC 0x9660
 
 #ifdef __KERNEL__
-extern int isonum_711(char *);
-extern int isonum_712(char *);
-extern int isonum_721(char *);
-extern int isonum_722(char *);
-extern int isonum_723(char *);
-extern int isonum_731(char *);
-extern int isonum_732(char *);
-extern int isonum_733(char *);
+/* Number conversion inlines, named after the section in ISO 9660
+   they correspond to. */
+
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+
+static inline int isonum_711(char *p)
+{
+	return *(u8 *)p;
+}
+static inline int isonum_712(char *p)
+{
+	return *(s8 *)p;
+}
+static inline int isonum_721(char *p)
+{
+	return le16_to_cpu(get_unaligned((u16 *)p));
+}
+static inline int isonum_722(char *p)
+{
+	return be16_to_cpu(get_unaligned((u16 *)p));
+}
+static inline int isonum_723(char *p)
+{
+	/* Ignore bigendian datum due to broken mastering programs */
+	return le16_to_cpu(get_unaligned((u16 *)p));
+}
+static inline int isonum_731(char *p)
+{
+	return le32_to_cpu(get_unaligned((u32 *)p));
+}
+static inline int isonum_732(char *p)
+{
+	return be32_to_cpu(get_unaligned((u32 *)p));
+}
+static inline int isonum_733(char *p)
+{
+	/* Ignore bigendian datum due to broken mastering programs */
+	return le32_to_cpu(get_unaligned((u32 *)p));
+}
 extern int iso_date(char *, int);
 
 extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
diff -u --recursive --new-file v2.4.4/linux/include/linux/kernel.h linux/include/linux/kernel.h
--- v2.4.4/linux/include/linux/kernel.h	Thu Apr 12 12:25:53 2001
+++ linux/include/linux/kernel.h	Sun May 20 12:11:39 2001
@@ -54,6 +54,7 @@
 	ATTRIB_NORET;
 NORET_TYPE void up_and_exit(struct semaphore *, long)
 	ATTRIB_NORET;
+extern int abs(int);
 extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
diff -u --recursive --new-file v2.4.4/linux/include/linux/locks.h linux/include/linux/locks.h
--- v2.4.4/linux/include/linux/locks.h	Fri Apr 27 15:49:14 2001
+++ linux/include/linux/locks.h	Tue May 22 11:18:17 2001
@@ -39,30 +39,15 @@
  * a super-block (although even this isn't done right now.
  * nfs may need it).
  */
-extern void __wait_on_super(struct super_block *);
-
-extern inline void wait_on_super(struct super_block * sb)
-{
-	if (sb->s_lock)
-		__wait_on_super(sb);
-}
 
 extern inline void lock_super(struct super_block * sb)
 {
-	if (sb->s_lock)
-		__wait_on_super(sb);
-	sb->s_lock = 1;
+	down(&sb->s_lock);
 }
 
 extern inline void unlock_super(struct super_block * sb)
 {
-	sb->s_lock = 0;
-	/*
-	 * No need of any barrier, we're protected by
-	 * the big kernel lock here... unfortunately :)
-	 */
-	if (waitqueue_active(&sb->s_wait))
-		wake_up(&sb->s_wait);
+	up(&sb->s_lock);
 }
 
 #endif /* _LINUX_LOCKS_H */
diff -u --recursive --new-file v2.4.4/linux/include/linux/mii.h linux/include/linux/mii.h
--- v2.4.4/linux/include/linux/mii.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/mii.h	Wed May 16 10:25:38 2001
@@ -0,0 +1,181 @@
+/*
+ * linux/mii.h: definitions for MII-compatible transceivers
+ * Originally drivers/net/sunhme.h.
+ *
+ * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __LINUX_MII_H__
+#define __LINUX_MII_H__
+
+/* Inside the Happy Meal transceiver is the physical layer, they use an
+ * implementations for National Semiconductor, part number DP83840VCE.
+ * You can retrieve the data sheets and programming docs for this beast
+ * from http://www.national.com/
+ *
+ * The DP83840 is capable of both 10 and 100Mbps ethernet, in both
+ * half and full duplex mode.  It also supports auto negotiation.
+ *
+ * But.... THIS THING IS A PAIN IN THE ASS TO PROGRAM!
+ * Debugging eeprom burnt code is more fun than programming this chip!
+ */
+
+/* First, the MII register numbers (actually DP83840 register numbers). */
+#define MII_BMCR            0x00        /* Basic mode control register */
+#define MII_BMSR            0x01        /* Basic mode status register  */
+#define MII_PHYSID1         0x02        /* PHYS ID 1                   */
+#define MII_PHYSID2         0x03        /* PHYS ID 2                   */
+#define MII_ADVERTISE       0x04        /* Advertisement control reg   */
+#define MII_LPA             0x05        /* Link partner ability reg    */
+#define MII_EXPANSION       0x06        /* Expansion register          */
+#define MII_DCOUNTER        0x12        /* Disconnect counter          */
+#define MII_FCSCOUNTER      0x13        /* False carrier counter       */
+#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
+#define MII_RERRCOUNTER     0x15        /* Receive error counter       */
+#define MII_SREVISION       0x16        /* Silicon revision            */
+#define MII_CSCONFIG        0x17        /* CS configuration            */
+#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */
+#define MII_PHYADDR         0x19        /* PHY address                 */
+#define MII_RESERVED        0x1a        /* Unused...                   */
+#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */
+#define MII_NCONFIG         0x1c        /* Network interface config    */
+
+/* Basic mode control register. */
+#define BMCR_RESV               0x007f  /* Unused...                   */
+#define BMCR_CTST               0x0080  /* Collision test              */
+#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
+#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
+#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
+#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
+#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
+#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
+#define BMCR_RESET              0x8000  /* Reset the DP83840           */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */
+#define BMSR_JCD                0x0002  /* Jabber detected             */
+#define BMSR_LSTATUS            0x0004  /* Link status                 */
+#define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */
+#define BMSR_RFAULT             0x0010  /* Remote fault detected       */
+#define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */
+#define BMSR_RESV               0x07c0  /* Unused...                   */
+#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */
+#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */
+#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT          0x001f  /* Selector bits               */
+#define ADVERTISE_CSMA          0x0001  /* Only selector supported     */
+#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
+#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
+#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
+#define ADVERTISE_100BASE4      0x0200  /* Try for 100mbps 4k packets  */
+#define ADVERTISE_RESV          0x1c00  /* Unused...                   */
+#define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */
+#define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
+#define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
+
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+                       ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/* Link partner ability register. */
+#define LPA_SLCT                0x001f  /* Same as advertise selector  */
+#define LPA_10HALF              0x0020  /* Can do 10mbps half-duplex   */
+#define LPA_10FULL              0x0040  /* Can do 10mbps full-duplex   */
+#define LPA_100HALF             0x0080  /* Can do 100mbps half-duplex  */
+#define LPA_100FULL             0x0100  /* Can do 100mbps full-duplex  */
+#define LPA_100BASE4            0x0200  /* Can do 100mbps 4k packets   */
+#define LPA_RESV                0x1c00  /* Unused...                   */
+#define LPA_RFAULT              0x2000  /* Link partner faulted        */
+#define LPA_LPACK               0x4000  /* Link partner acked us       */
+#define LPA_NPAGE               0x8000  /* Next page bit               */
+
+#define LPA_DUPLEX		(LPA_10FULL | LPA_100FULL)
+#define LPA_100			(LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY          0x0001  /* Can do N-way auto-nego      */
+#define EXPANSION_LCWP          0x0002  /* Got new RX page code word   */
+#define EXPANSION_ENABLENPAGE   0x0004  /* This enables npage words    */
+#define EXPANSION_NPCAPABLE     0x0008  /* Link partner supports npage */
+#define EXPANSION_MFAULTS       0x0010  /* Multiple faults detected    */
+#define EXPANSION_RESV          0xffe0  /* Unused...                   */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1          0x00ff  /* Unused...                   */
+#define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
+#define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
+
+/* The Carrier Sense config register. */
+#define CSCONFIG_RESV1          0x0001  /* Unused...                   */
+#define CSCONFIG_LED4           0x0002  /* Pin for full-dplx LED4      */
+#define CSCONFIG_LED1           0x0004  /* Pin for conn-status LED1    */
+#define CSCONFIG_RESV2          0x0008  /* Unused...                   */
+#define CSCONFIG_TCVDISAB       0x0010  /* Turns off the transceiver   */
+#define CSCONFIG_DFBYPASS       0x0020  /* Bypass disconnect function  */
+#define CSCONFIG_GLFORCE        0x0040  /* Good link force for 100mbps */
+#define CSCONFIG_CLKTRISTATE    0x0080  /* Tristate 25m clock          */
+#define CSCONFIG_RESV3          0x0700  /* Unused...                   */
+#define CSCONFIG_ENCODE         0x0800  /* 1=MLT-3, 0=binary           */
+#define CSCONFIG_RENABLE        0x1000  /* Repeater mode enable        */
+#define CSCONFIG_TCDISABLE      0x2000  /* Disable timeout counter     */
+#define CSCONFIG_RESV4          0x4000  /* Unused...                   */
+#define CSCONFIG_NDISABLE       0x8000  /* Disable NRZI                */
+
+/**
+ * mii_nway_result
+ * @negotiated: value of MII ANAR and'd with ANLPAR
+ *
+ * Given a set of MII abilities, check each bit and returns the
+ * currently supported media, in the priority order defined by
+ * IEEE 802.3u.  We use LPA_xxx constants but note this is not the
+ * value of LPA solely, as described above.
+ *
+ * The one exception to IEEE 802.3u is that 100baseT4 is placed
+ * between 100T-full and 100T-half.  If your phy does not support
+ * 100T4 this is fine.  If your phy places 100T4 elsewhere in the
+ * priority order, you will need to roll your own function.
+ */
+static inline unsigned int mii_nway_result (unsigned int negotiated)
+{
+	unsigned int ret;
+
+	if (negotiated & LPA_100FULL)
+		ret = LPA_100FULL;
+	else if (negotiated & LPA_100BASE4)
+		ret = LPA_100BASE4;
+	else if (negotiated & LPA_100HALF)
+		ret = LPA_100HALF;
+	else if (negotiated & LPA_10FULL)
+		ret = LPA_10FULL;
+	else
+		ret = LPA_10HALF;
+
+	return ret;
+}
+
+/**
+ * mii_duplex
+ * @duplex_lock: Non-zero if duplex is locked at full
+ * @negotiated: value of MII ANAR and'd with ANLPAR
+ *
+ * A small helper function for a common case.  Returns one
+ * if the media is operating or locked at full duplex, and
+ * returns zero otherwise.
+ */
+static inline unsigned int mii_duplex (unsigned int duplex_lock,
+				       unsigned int negotiated)
+{
+	if (duplex_lock)
+		return 1;
+	if (mii_nway_result(negotiated) & LPA_DUPLEX)
+		return 1;
+	return 0;
+}
+
+
+#endif /* __LINUX_MII_H__ */
diff -u --recursive --new-file v2.4.4/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.4.4/linux/include/linux/mm.h	Fri Apr 27 15:48:35 2001
+++ linux/include/linux/mm.h	Thu May 24 15:20:18 2001
@@ -480,7 +480,6 @@
 #else
 #define __GFP_HIGHMEM	0x0 /* noop */
 #endif
-#define __GFP_VM	0x20
 
 
 #define GFP_BUFFER	(__GFP_HIGH | __GFP_WAIT)
diff -u --recursive --new-file v2.4.4/linux/include/linux/mmzone.h linux/include/linux/mmzone.h
--- v2.4.4/linux/include/linux/mmzone.h	Fri Apr 27 15:48:22 2001
+++ linux/include/linux/mmzone.h	Thu May 24 15:20:18 2001
@@ -16,7 +16,7 @@
 
 typedef struct free_area_struct {
 	struct list_head	free_list;
-	unsigned int		*map;
+	unsigned long		*map;
 } free_area_t;
 
 struct pglist_data;
@@ -34,7 +34,6 @@
 	 * Commonly accessed fields:
 	 */
 	spinlock_t		lock;
-	unsigned long		offset;
 	unsigned long		free_pages;
 	unsigned long		inactive_clean_pages;
 	unsigned long		inactive_dirty_pages;
@@ -47,17 +46,18 @@
 	free_area_t		free_area[MAX_ORDER];
 
 	/*
-	 * rarely used fields:
-	 */
-	char			*name;
-	unsigned long		size;
-	/*
 	 * Discontig memory support fields.
 	 */
 	struct pglist_data	*zone_pgdat;
+	struct page		*zone_mem_map;
 	unsigned long		zone_start_paddr;
 	unsigned long		zone_start_mapnr;
-	struct page		*zone_mem_map;
+
+	/*
+	 * rarely used fields:
+	 */
+	char			*name;
+	unsigned long		size;
 } zone_t;
 
 #define ZONE_DMA		0
@@ -81,7 +81,7 @@
 	int gfp_mask;
 } zonelist_t;
 
-#define NR_GFPINDEX		0x100
+#define NR_GFPINDEX		0x20
 
 /*
  * The pg_data_t structure is used in machines with CONFIG_DISCONTIGMEM
@@ -112,8 +112,7 @@
 extern pg_data_t *pgdat_list;
 
 #define memclass(pgzone, tzone)	(((pgzone)->zone_pgdat == (tzone)->zone_pgdat) \
-			&& (((pgzone) - (pgzone)->zone_pgdat->node_zones) <= \
-			((tzone) - (pgzone)->zone_pgdat->node_zones)))
+			&& ((pgzone) <= (tzone)))
 
 /*
  * The following two are not meant for general usage. They are here as
diff -u --recursive --new-file v2.4.4/linux/include/linux/mount.h linux/include/linux/mount.h
--- v2.4.4/linux/include/linux/mount.h	Sun Sep 17 09:51:57 2000
+++ linux/include/linux/mount.h	Thu May 24 15:02:06 2001
@@ -39,11 +39,13 @@
 	return mnt;
 }
 
+extern void __mntput(struct vfsmount *mnt);
+
 static inline void mntput(struct vfsmount *mnt)
 {
 	if (mnt) {
 		if (atomic_dec_and_test(&mnt->mnt_count))
-			BUG();
+			__mntput(mnt);
 	}
 }
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v2.4.4/linux/include/linux/msdos_fs.h	Mon Dec 11 13:25:10 2000
+++ linux/include/linux/msdos_fs.h	Thu May 24 15:36:34 2001
@@ -54,8 +54,7 @@
 #define SCAN_NOTANY  3  /* test name, then use SCAN_HID or SCAN_NOTHID */
 
 #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
-#define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG || \
-  *(const unsigned char *) (n) == FD_FILL_BYTE)
+#define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG)
 
 #define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
 	/* valid file mode bits */
@@ -77,6 +76,11 @@
 #define EOF_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
 	MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12)
 
+#define FAT_FSINFO_SIG1		0x41615252
+#define FAT_FSINFO_SIG2		0x61417272
+#define IS_FSINFO(x)		(CF_LE_L((x)->signature1) == FAT_FSINFO_SIG1	 \
+				 && CF_LE_L((x)->signature2) == FAT_FSINFO_SIG2)
+
 /*
  * Inode flags
  */
@@ -128,8 +132,9 @@
 };
 
 struct fat_boot_fsinfo {
-	__u32   reserved1;	/* Nothing as far as I can tell */
-	__u32   signature;	/* 0x61417272L */
+	__u32   signature1;	/* 0x61417272L */
+	__u32   reserved1[120];	/* Nothing as far as I can tell */
+	__u32   signature2;	/* 0x61417272L */
 	__u32   free_clusters;	/* Free cluster count.  -1 if unknown */
 	__u32   next_cluster;	/* Most recently allocated cluster.
 				 * Unused under Linux. */
@@ -209,7 +214,7 @@
 {
 	/* Fast stuff first */
 	if (*bh && *de &&
-	    	(*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_DPB-1) {
+	    (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
 		*pos += sizeof(struct msdos_dir_entry);
 		(*de)++;
 		(*ino)++;
diff -u --recursive --new-file v2.4.4/linux/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- v2.4.4/linux/include/linux/msdos_fs_sb.h	Tue Sep  5 14:53:04 2000
+++ linux/include/linux/msdos_fs_sb.h	Thu May 24 15:36:34 2001
@@ -44,7 +44,7 @@
 	unsigned long data_start;    /* first data sector */
 	unsigned long clusters;      /* number of clusters */
 	unsigned long root_cluster;  /* first cluster of the root directory */
-	unsigned long fsinfo_offset; /* FAT32 fsinfo offset from start of disk */
+	unsigned long fsinfo_sector; /* FAT32 fsinfo offset from start of disk */
 	wait_queue_head_t fat_wait;
 	struct semaphore fat_lock;
 	int prev_free;               /* previously returned free cluster number */
@@ -54,7 +54,9 @@
 	struct nls_table *nls_io;    /* Charset used for input and display */
 	struct cvf_format* cvf_format;
 	void *dir_ops;		     /* Opaque; default directory operations */
-	void *private_data;	
+	void *private_data;
+	int dir_per_block;	     /* dir entries per block */
+	int dir_per_block_bits;	     /* log2(dir_per_block) */
 };
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/linux/nbd.h linux/include/linux/nbd.h
--- v2.4.4/linux/include/linux/nbd.h	Wed Apr 11 19:02:30 2001
+++ linux/include/linux/nbd.h	Tue May  1 14:20:25 2001
@@ -2,6 +2,9 @@
  * 1999 Copyright (C) Pavel Machek, pavel@ucw.cz. This code is GPL.
  * 1999/11/04 Copyright (C) 1999 VMware, Inc. (Regis "HPReg" Duchesne)
  *            Made nbd_end_request() use the io_request_lock
+ * 2001 Copyright (C) Steven Whitehouse
+ *            New nbd_end_request() for compatibility with new linux block
+ *            layer code.
  */
 
 #ifndef LINUX_NBD_H
diff -u --recursive --new-file v2.4.4/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.4.4/linux/include/linux/nfs_fs.h	Fri Apr 27 15:49:37 2001
+++ linux/include/linux/nfs_fs.h	Tue May 22 11:18:33 2001
@@ -142,7 +142,7 @@
 				struct nfs_fattr *);
 extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
 				struct nfs_fattr *);
-extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
+extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_revalidate(struct dentry *);
 extern int nfs_permission(struct inode *, int);
 extern int nfs_open(struct inode *, struct file *);
@@ -271,6 +271,14 @@
 	if (time_before(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
 		return NFS_STALE(inode) ? -ESTALE : 0;
 	return __nfs_revalidate_inode(server, inode);
+}
+
+static inline int
+nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+		return 0;
+	return __nfs_refresh_inode(inode,fattr);
 }
 
 static inline loff_t
diff -u --recursive --new-file v2.4.4/linux/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h
--- v2.4.4/linux/include/linux/nfsd/nfsfh.h	Fri Apr 27 15:48:33 2001
+++ linux/include/linux/nfsd/nfsfh.h	Tue May 22 11:18:07 2001
@@ -31,7 +31,7 @@
  * ino/dev of the exported inode.
  */
 struct nfs_fhbase_old {
-	struct dentry *	fb_dentry;	/* dentry cookie - always 0xfeebbaca */
+	__u32		fb_dcookie;	/* dentry cookie - always 0xfeebbaca */
 	__u32		fb_ino;		/* our inode number */
 	__u32		fb_dirino;	/* dir inode number, 0 for directories */
 	__u32		fb_dev;		/* our device */
@@ -101,7 +101,7 @@
 	} fh_base;
 };
 
-#define ofh_dcookie		fh_base.fh_old.fb_dentry
+#define ofh_dcookie		fh_base.fh_old.fb_dcookie
 #define ofh_ino			fh_base.fh_old.fb_ino
 #define ofh_dirino		fh_base.fh_old.fb_dirino
 #define ofh_dev			fh_base.fh_old.fb_dev
diff -u --recursive --new-file v2.4.4/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.4.4/linux/include/linux/parport.h	Thu Feb  8 10:40:25 2001
+++ linux/include/linux/parport.h	Sat May 19 18:07:04 2001
@@ -90,6 +90,7 @@
 
 /* Flags for block transfer operations. */
 #define PARPORT_EPP_FAST		(1<<0) /* Unreliable counts. */
+#define PARPORT_W91284PIC		(1<<1) /* have a Warp9 w91284pic in the device */
 
 /* The rest is for the kernel only */
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.4.4/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h
--- v2.4.4/linux/include/linux/parport_pc.h	Mon Dec 11 12:50:09 2000
+++ linux/include/linux/parport_pc.h	Sat May 19 18:07:04 2001
@@ -59,6 +59,51 @@
 	return val;
 }
 
+#ifdef DEBUG_PARPORT
+extern __inline__ void dump_parport_state (char *str, struct parport *p)
+{
+	/* here's hoping that reading these ports won't side-effect anything underneath */
+	unsigned char ecr = inb (ECONTROL (p));
+	unsigned char dcr = inb (CONTROL (p));
+	unsigned char dsr = inb (STATUS (p));
+	static char *ecr_modes[] = {"SPP", "PS2", "PPFIFO", "ECP", "xXx", "yYy", "TST", "CFG"};
+	const struct parport_pc_private *priv = (parport_pc_private *)p->physport->private_data;
+	int i;
+
+	printk (KERN_DEBUG "*** parport state (%s): ecr=[%s", str, ecr_modes[(ecr & 0xe0) >> 5]);
+	if (ecr & 0x10) printk (",nErrIntrEn");
+	if (ecr & 0x08) printk (",dmaEn");
+	if (ecr & 0x04) printk (",serviceIntr");
+	if (ecr & 0x02) printk (",f_full");
+	if (ecr & 0x01) printk (",f_empty");
+	for (i=0; i<2; i++) {
+		printk ("]  dcr(%s)=[", i ? "soft" : "hard");
+		dcr = i ? priv->ctr : inb (CONTROL (p));
+	
+		if (dcr & 0x20) {
+			printk ("rev");
+		} else {
+			printk ("fwd");
+		}
+		if (dcr & 0x10) printk (",ackIntEn");
+		if (!(dcr & 0x08)) printk (",N-SELECT-IN");
+		if (dcr & 0x04) printk (",N-INIT");
+		if (!(dcr & 0x02)) printk (",N-AUTOFD");
+		if (!(dcr & 0x01)) printk (",N-STROBE");
+	}
+	printk ("]  dsr=[");
+	if (!(dsr & 0x80)) printk ("BUSY");
+	if (dsr & 0x40) printk (",N-ACK");
+	if (dsr & 0x20) printk (",PERROR");
+	if (dsr & 0x10) printk (",SELECT");
+	if (dsr & 0x08) printk (",N-FAULT");
+	printk ("]\n");
+	return;
+}
+#else	/* !DEBUG_PARPORT */
+#define dump_parport_state(args...)
+#endif	/* !DEBUG_PARPORT */
+
 /* __parport_pc_frob_control differs from parport_pc_frob_control in that
  * it doesn't do any extra masking. */
 static __inline__ unsigned char __parport_pc_frob_control (struct parport *p,
diff -u --recursive --new-file v2.4.4/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.4.4/linux/include/linux/pci.h	Fri Apr 27 15:49:27 2001
+++ linux/include/linux/pci.h	Tue May 22 11:18:28 2001
@@ -279,6 +279,13 @@
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 
+/* Ioctls for /proc/bus/pci/X/Y nodes. */
+#define PCIIOC_BASE		('P' << 24 | 'C' << 16 | 'I' << 8)
+#define PCIIOC_CONTROLLER	(PCIIOC_BASE | 0x00)	/* Get controller for PCI device. */
+#define PCIIOC_MMAP_IS_IO	(PCIIOC_BASE | 0x01)	/* Set mmap state to I/O space. */
+#define PCIIOC_MMAP_IS_MEM	(PCIIOC_BASE | 0x02)	/* Set mmap state to MEM space. */
+#define PCIIOC_WRITE_COMBINE	(PCIIOC_BASE | 0x03)	/* Enable/disable write-combining. */
+
 #ifdef __KERNEL__
 
 #include <linux/types.h>
@@ -287,6 +294,12 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 
+/* File state for mmap()s on /proc/bus/pci/X/Y */
+enum pci_mmap_state {
+	pci_mmap_io,
+	pci_mmap_mem
+};
+
 /* This defines the direction arg to the DMA mapping routines. */
 #define PCI_DMA_BIDIRECTIONAL	0
 #define PCI_DMA_TODEVICE	1
@@ -302,8 +315,6 @@
 
 #define pci_present pcibios_present
 
-#define pci_for_each_dev(dev) \
-	for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))
 
 #define pci_for_each_dev_reverse(dev) \
 	for(dev = pci_dev_g(pci_devices.prev); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.prev))
@@ -460,6 +471,9 @@
 /* these external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
+#define pci_for_each_dev(dev) \
+	for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))
+
 void pcibios_init(void);
 void pcibios_fixup_bus(struct pci_bus *);
 int pcibios_enable_device(struct pci_dev *);
@@ -611,6 +625,10 @@
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
 static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
+static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
+
+#define pci_for_each_dev(dev) \
+	for(dev = NULL; 0; )
 
 #else
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.4.4/linux/include/linux/pci_ids.h	Wed Apr 18 14:40:06 2001
+++ linux/include/linux/pci_ids.h	Wed May 16 10:25:39 2001
@@ -978,6 +978,10 @@
 #define PCI_VENDOR_ID_MUTECH		0x1159
 #define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
 
+#define PCI_VENDOR_ID_XIRCOM		0x115d
+#define PCI_DEVICE_ID_XIRCOM_X3201_ETH	0x0003
+#define PCI_DEVICE_ID_XIRCOM_X3201_MDM	0x0103
+
 #define PCI_VENDOR_ID_RENDITION		0x1163
 #define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
diff -u --recursive --new-file v2.4.4/linux/include/linux/ppdev.h linux/include/linux/ppdev.h
--- v2.4.4/linux/include/linux/ppdev.h	Mon Oct 11 10:04:02 1999
+++ linux/include/linux/ppdev.h	Sat May 19 18:07:04 2001
@@ -11,6 +11,7 @@
  * 2 of the License, or (at your option) any later version.
  *
  * Added PPGETTIME/PPSETTIME, Fred Barnes, 1999
+ * Added PPGETMODES/PPGETMODE/PPGETPHASE, Fred Barnes <frmb2@ukc.ac.uk>, 03/01/2001
  */
 
 #define PP_MAJOR	99
@@ -77,5 +78,24 @@
 /* Set and get port timeout (struct timeval's) */
 #define PPGETTIME	_IOR(PP_IOCTL, 0x95, struct timeval)
 #define PPSETTIME	_IOW(PP_IOCTL, 0x96, struct timeval)
+
+/* Get available modes (what the hardware can do) */
+#define PPGETMODES	_IOR(PP_IOCTL, 0x97, unsigned int)
+
+/* Get the current mode and phaze */
+#define PPGETMODE	_IOR(PP_IOCTL, 0x98, int)
+#define PPGETPHASE	_IOR(PP_IOCTL, 0x99, int)
+
+/* get/set flags */
+#define PPGETFLAGS	_IOR(PP_IOCTL, 0x9a, int)
+#define PPSETFLAGS	_IOW(PP_IOCTL, 0x9b, int)
+
+/* flags visible to the world */
+#define PP_FASTWRITE	(1<<2)
+#define PP_FASTREAD	(1<<3)
+#define PP_W91284PIC	(1<<4)
+
+/* only masks user-visible flags */
+#define PP_FLAGMASK	(PP_FASTWRITE | PP_FASTREAD | PP_W91284PIC)
 
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.4.4/linux/include/linux/proc_fs.h	Fri Apr 27 15:48:38 2001
+++ linux/include/linux/proc_fs.h	Tue May 22 11:17:42 2001
@@ -127,6 +127,11 @@
  */
 extern void proc_device_tree_init(void);
 
+/*
+ * proc_rtas.c
+ */
+extern void proc_rtas_init(void);
+
 extern struct proc_dir_entry *proc_symlink(const char *,
 		struct proc_dir_entry *, const char *);
 extern struct proc_dir_entry *proc_mknod(const char *,mode_t,
diff -u --recursive --new-file v2.4.4/linux/include/linux/raid/md.h linux/include/linux/raid/md.h
--- v2.4.4/linux/include/linux/raid/md.h	Fri Apr 27 15:49:20 2001
+++ linux/include/linux/raid/md.h	Tue May 22 11:18:52 2001
@@ -80,7 +80,7 @@
 extern struct gendisk * find_gendisk (kdev_t dev);
 extern int md_notify_reboot(struct notifier_block *this,
 					unsigned long code, void *x);
-extern int md_error (kdev_t mddev, kdev_t rdev);
+extern int md_error (mddev_t *mddev, kdev_t rdev);
 extern int md_run_setup(void);
 
 extern void md_print_devices (void);
diff -u --recursive --new-file v2.4.4/linux/include/linux/raid/md_k.h linux/include/linux/raid/md_k.h
--- v2.4.4/linux/include/linux/raid/md_k.h	Fri Dec 29 14:07:24 2000
+++ linux/include/linux/raid/md_k.h	Sun May 20 12:11:39 2001
@@ -25,7 +25,7 @@
 #define HSM               6UL
 #define MAX_PERSONALITY   7UL
 
-extern inline int pers_to_level (int pers)
+static inline int pers_to_level (int pers)
 {
 	switch (pers) {
 		case HSM:		return -3;
@@ -36,6 +36,7 @@
 		case RAID5:		return 5;
 	}
 	panic("pers_to_level()");
+	return MD_RESERVED;
 }
 
 extern inline int level_to_pers (int level)
@@ -72,7 +73,7 @@
 
 extern dev_mapping_t mddev_map [MAX_MD_DEVS];
 
-extern inline mddev_t * kdev_to_mddev (kdev_t dev)
+static inline mddev_t * kdev_to_mddev (kdev_t dev)
 {
 	if (MAJOR(dev) != MD_MAJOR)
 		BUG();
@@ -90,62 +91,62 @@
  */
 #define MD_READAHEAD	MAX_READAHEAD
 
-extern inline int disk_faulty(mdp_disk_t * d)
+static inline int disk_faulty(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_FAULTY);
 }
 
-extern inline int disk_active(mdp_disk_t * d)
+static inline int disk_active(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_ACTIVE);
 }
 
-extern inline int disk_sync(mdp_disk_t * d)
+static inline int disk_sync(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_SYNC);
 }
 
-extern inline int disk_spare(mdp_disk_t * d)
+static inline int disk_spare(mdp_disk_t * d)
 {
 	return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
 }
 
-extern inline int disk_removed(mdp_disk_t * d)
+static inline int disk_removed(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_REMOVED);
 }
 
-extern inline void mark_disk_faulty(mdp_disk_t * d)
+static inline void mark_disk_faulty(mdp_disk_t * d)
 {
 	d->state |= (1 << MD_DISK_FAULTY);
 }
 
-extern inline void mark_disk_active(mdp_disk_t * d)
+static inline void mark_disk_active(mdp_disk_t * d)
 {
 	d->state |= (1 << MD_DISK_ACTIVE);
 }
 
-extern inline void mark_disk_sync(mdp_disk_t * d)
+static inline void mark_disk_sync(mdp_disk_t * d)
 {
 	d->state |= (1 << MD_DISK_SYNC);
 }
 
-extern inline void mark_disk_spare(mdp_disk_t * d)
+static inline void mark_disk_spare(mdp_disk_t * d)
 {
 	d->state = 0;
 }
 
-extern inline void mark_disk_removed(mdp_disk_t * d)
+static inline void mark_disk_removed(mdp_disk_t * d)
 {
 	d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
 }
 
-extern inline void mark_disk_inactive(mdp_disk_t * d)
+static inline void mark_disk_inactive(mdp_disk_t * d)
 {
 	d->state &= ~(1 << MD_DISK_ACTIVE);
 }
 
-extern inline void mark_disk_nonsync(mdp_disk_t * d)
+static inline void mark_disk_nonsync(mdp_disk_t * d)
 {
 	d->state &= ~(1 << MD_DISK_SYNC);
 }
@@ -245,12 +246,12 @@
  * number. This will have to change to dynamic allocation
  * once we start supporting partitioning of md devices.
  */
-extern inline int mdidx (mddev_t * mddev)
+static inline int mdidx (mddev_t * mddev)
 {
 	return mddev->__minor;
 }
 
-extern inline kdev_t mddev_to_kdev(mddev_t * mddev)
+static inline kdev_t mddev_to_kdev(mddev_t * mddev)
 {
 	return MKDEV(MD_MAJOR, mdidx(mddev));
 }
@@ -304,12 +305,12 @@
 			tmp = tmp->next, tmp->prev != &all_mddevs	\
 		; )
 
-extern inline int lock_mddev (mddev_t * mddev)
+static inline int lock_mddev (mddev_t * mddev)
 {
 	return down_interruptible(&mddev->reconfig_sem);
 }
 
-extern inline void unlock_mddev (mddev_t * mddev)
+static inline void unlock_mddev (mddev_t * mddev)
 {
 	up(&mddev->reconfig_sem);
 }
diff -u --recursive --new-file v2.4.4/linux/include/linux/rwsem-spinlock.h linux/include/linux/rwsem-spinlock.h
--- v2.4.4/linux/include/linux/rwsem-spinlock.h	Fri Apr 27 15:48:23 2001
+++ linux/include/linux/rwsem-spinlock.h	Tue May 22 11:17:37 2001
@@ -9,7 +9,7 @@
 #define _LINUX_RWSEM_SPINLOCK_H
 
 #ifndef _LINUX_RWSEM_H
-#error please dont include asm/rwsem-spinlock.h directly, use linux/rwsem.h instead
+#error please dont include linux/rwsem-spinlock.h directly, use linux/rwsem.h instead
 #endif
 
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.4.4/linux/include/linux/rwsem.h linux/include/linux/rwsem.h
--- v2.4.4/linux/include/linux/rwsem.h	Fri Apr 27 15:48:25 2001
+++ linux/include/linux/rwsem.h	Tue May 22 11:17:37 2001
@@ -13,6 +13,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.4/linux/include/linux/serial_reg.h linux/include/linux/serial_reg.h
--- v2.4.4/linux/include/linux/serial_reg.h	Tue Mar  6 19:28:35 2001
+++ linux/include/linux/serial_reg.h	Tue May  1 16:05:00 2001
@@ -260,8 +260,8 @@
 #define UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */
 #define UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */
 #define UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */
-#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occured (1) */
-#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occured */
+#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occurred (1) */
+#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occurred */
 
 #define UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */
 
diff -u --recursive --new-file v2.4.4/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.4.4/linux/include/linux/skbuff.h	Fri Apr 27 15:48:50 2001
+++ linux/include/linux/skbuff.h	Tue May 22 11:17:51 2001
@@ -1069,7 +1069,7 @@
 static inline int
 skb_cow(struct sk_buff *skb, unsigned int headroom)
 {
-	int delta = headroom - skb_headroom(skb);
+	int delta = (headroom > 16 ? headroom : 16) - skb_headroom(skb);
 
 	if (delta < 0)
 		delta = 0;
diff -u --recursive --new-file v2.4.4/linux/include/linux/smb.h linux/include/linux/smb.h
--- v2.4.4/linux/include/linux/smb.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/smb.h	Tue May 22 11:17:35 2001
@@ -94,21 +94,14 @@
 };
 
 enum smb_conn_state {
-        CONN_VALID,             /* everything's fine */
-        CONN_INVALID,           /* Something went wrong, but did not
-                                   try to reconnect yet. */
-        CONN_RETRIED            /* Tried a reconnection, but was refused */
+	CONN_VALID,		/* everything's fine */
+	CONN_INVALID,		/* Something went wrong, but did not
+				   try to reconnect yet. */
+	CONN_RETRIED,		/* Tried a reconnection, but was refused */
+	CONN_RETRYING		/* Currently trying to reconnect */
 };
 
-/*
- * The readdir cache size controls how many directory entries are cached.
- */
-#define SMB_READDIR_CACHE_SIZE        64
-
 #define SMB_SUPER_MAGIC               0x517B
-
-#define SMB_SERVER(inode)    (&(inode->i_sb->u.smbfs_sb))
-#define SMB_INOP(inode)      (&(inode->u.smbfs_i))
 
 #define SMB_HEADER_LEN   37     /* includes everything up to, but not
                                  * including smb_bcc */
diff -u --recursive --new-file v2.4.4/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.4.4/linux/include/linux/smb_fs.h	Fri Feb 16 16:03:24 2001
+++ linux/include/linux/smb_fs.h	Tue May 15 13:40:55 2001
@@ -48,8 +48,11 @@
 
 #ifdef DEBUG_SMB_MALLOC
 
+#include <linux/slab.h>
+
 extern int smb_malloced;
 extern int smb_current_vmalloced;
+extern int smb_current_kmalloced;
 
 static inline void *
 smb_vmalloc(unsigned int size)
@@ -66,20 +69,30 @@
         vfree(obj);
 }
 
+static inline void *
+smb_kmalloc(size_t size, int flags)
+{
+	smb_malloced += 1;
+	smb_current_kmalloced += 1;
+	return kmalloc(size, flags);
+}
+
+static inline void
+smb_kfree(void *obj)
+{
+	smb_current_kmalloced -= 1;
+	kfree(obj);
+}
+
 #else /* DEBUG_SMB_MALLOC */
 
-#define smb_kmalloc(s,p) kmalloc(s,p)
-#define smb_kfree_s(o,s) kfree(o)
-#define smb_vmalloc(s)   vmalloc(s)
-#define smb_vfree(o)     vfree(o)
+#define smb_kmalloc(s,p)	kmalloc(s,p)
+#define smb_kfree(o)		kfree(o)
+#define smb_vmalloc(s)		vmalloc(s)
+#define smb_vfree(o)		vfree(o)
 
 #endif /* DEBUG_SMB_MALLOC */
 
-/*
- * Flags for the in-memory inode
- */
-#define SMB_F_LOCALWRITE	0x02	/* file modified locally */
-
 
 /* NT1 protocol capability bits */
 #define SMB_CAP_RAW_MODE         0x0001
@@ -139,7 +152,7 @@
 static inline int
 smb_is_open(struct inode *i)
 {
-	return (i->u.smbfs_i.open == SMB_SERVER(i)->generation);
+	return (i->u.smbfs_i.open == server_from_inode(i)->generation);
 }
 
 
@@ -194,6 +207,7 @@
 int smb_proc_dskattr(struct super_block *, struct statfs *);
 int smb_proc_disconnect(struct smb_sb_info *);
 int smb_proc_trunc(struct smb_sb_info *, __u16, __u32);
+int smb_proc_flush(struct smb_sb_info *, __u16);
 void smb_init_root_dirent(struct smb_sb_info *, struct smb_fattr *);
 
 /* linux/fs/smbfs/sock.c */
diff -u --recursive --new-file v2.4.4/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h
--- v2.4.4/linux/include/linux/smb_fs_i.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/smb_fs_i.h	Tue May 22 11:17:35 2001
@@ -26,7 +26,6 @@
 	__u16 attr;		/* Attribute fields, DOS value */
 
 	__u16 access;		/* Access mode */
-	__u16 flags;		/* status flags */
 	unsigned long oldmtime;	/* last time refreshed */
 	unsigned long closed;	/* timestamp when closed */
 	unsigned openers;	/* number of fileid users */
diff -u --recursive --new-file v2.4.4/linux/include/linux/smb_fs_sb.h linux/include/linux/smb_fs_sb.h
--- v2.4.4/linux/include/linux/smb_fs_sb.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/smb_fs_sb.h	Tue May 22 11:17:36 2001
@@ -58,6 +58,19 @@
 		       struct nls_table *, struct nls_table *);
 };
 
+
+static inline void
+smb_lock_server(struct smb_sb_info *server)
+{
+	down(&(server->sem));
+}
+
+static inline void
+smb_unlock_server(struct smb_sb_info *server)
+{
+	up(&(server->sem));
+}
+
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.4.4/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.4.4/linux/include/linux/swap.h	Fri Apr 27 15:48:23 2001
+++ linux/include/linux/swap.h	Thu May 24 15:20:18 2001
@@ -64,9 +64,9 @@
 };
 
 extern int nr_swap_pages;
-FASTCALL(unsigned int nr_free_pages(void));
-FASTCALL(unsigned int nr_inactive_clean_pages(void));
-FASTCALL(unsigned int nr_free_buffer_pages(void));
+extern unsigned int nr_free_pages(void);
+extern unsigned int nr_inactive_clean_pages(void);
+extern unsigned int nr_free_buffer_pages(void);
 extern int nr_active_pages;
 extern int nr_inactive_dirty_pages;
 extern atomic_t nr_async_pages;
diff -u --recursive --new-file v2.4.4/linux/include/linux/synclink.h linux/include/linux/synclink.h
--- v2.4.4/linux/include/linux/synclink.h	Tue Mar  6 19:44:37 2001
+++ linux/include/linux/synclink.h	Tue May  1 16:05:00 2001
@@ -1,17 +1,17 @@
 /*
  * SyncLink Multiprotocol Serial Adapter Driver
  *
- * $Id: synclink.h,v 3.2 2000/11/06 22:34:38 paul Exp $
+ * $Id: synclink.h,v 3.5 2001/03/26 17:04:36 ez Exp $
  *
  * Copyright (C) 1998-2000 by Microgate Corporation
  * 
  * Redistribution of this file is permitted under 
- * the terms of the GNU General Public License (GPL)
+ * the terms of the GNU Public License (GPL)
  */
 
 #ifndef _SYNCLINK_H_
 #define _SYNCLINK_H_
-#define SYNCLINK_H_VERSION 3.2
+#define SYNCLINK_H_VERSION 3.5
 
 #define BOOLEAN int
 #define TRUE 1
@@ -84,6 +84,11 @@
 #define HDLC_CRC_NONE			0
 #define HDLC_CRC_16_CCITT		1
 #define HDLC_CRC_32_CCITT		2
+#define HDLC_CRC_MASK			0x00ff
+#define HDLC_CRC_RETURN_EX		0x8000
+
+#define RX_OK				0
+#define RX_CRC_ERROR			1
 
 #define HDLC_TXIDLE_FLAGS		0
 #define HDLC_TXIDLE_ALT_ZEROS_ONES	1
@@ -117,6 +122,7 @@
 
 #define MGSL_MODE_ASYNC		1
 #define MGSL_MODE_HDLC		2
+#define MGSL_MODE_RAW		6
 
 #define MGSL_BUS_TYPE_ISA	1
 #define MGSL_BUS_TYPE_EISA	2
@@ -150,6 +156,8 @@
 
 #define MICROGATE_VENDOR_ID 0x13c0
 #define SYNCLINK_DEVICE_ID 0x0010
+#define MGSCC_DEVICE_ID 0x0020
+#define SYNCLINK_SCA_DEVICE_ID 0x0030
 #define MGSL_MAX_SERIAL_NUMBER 30
 
 /*
diff -u --recursive --new-file v2.4.4/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.4.4/linux/include/linux/sysctl.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/sysctl.h	Tue May 22 11:17:37 2001
@@ -324,7 +324,8 @@
 	NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
 	NET_IPV4_CONF_BOOTP_RELAY=10,
 	NET_IPV4_CONF_LOG_MARTIANS=11,
-	NET_IPV4_CONF_TAG=12
+	NET_IPV4_CONF_TAG=12,
+	NET_IPV4_CONF_ARPFILTER=13
 };
 
 /* /proc/sys/net/ipv6 */
diff -u --recursive --new-file v2.4.4/linux/include/linux/timer.h linux/include/linux/timer.h
--- v2.4.4/linux/include/linux/timer.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/timer.h	Tue May 22 11:17:35 2001
@@ -5,17 +5,13 @@
 #include <linux/list.h>
 
 /*
- * This is completely separate from the above, and is the
- * "new and improved" way of handling timers more dynamically.
- * Hopefully efficient and general enough for most things.
+ * In Linux 2.4, static timers have been removed from the kernel.
+ * Timers may be dynamically created and destroyed, and should be initialized
+ * by a call to init_timer() upon creation.
  *
- * The "hardcoded" timers above are still useful for well-
- * defined problems, but the timer-list is probably better
- * when you need multiple outstanding timers or similar.
- *
- * The "data" field is in case you want to use the same
- * timeout function for several timeouts. You can use this
- * to distinguish between the different invocations.
+ * The "data" field enables use of a common timeout function for several
+ * timeouts. You can use this field to distinguish between the different
+ * invocations.
  */
 struct timer_list {
 	struct list_head list;
diff -u --recursive --new-file v2.4.4/linux/include/linux/usbdev_fs_sb.h linux/include/linux/usbdev_fs_sb.h
--- v2.4.4/linux/include/linux/usbdev_fs_sb.h	Mon Jan 10 11:32:48 2000
+++ linux/include/linux/usbdev_fs_sb.h	Tue May 22 10:25:36 2001
@@ -7,4 +7,7 @@
 	uid_t busuid;
 	gid_t busgid;
 	umode_t busmode;
+	uid_t listuid;
+	gid_t listgid;
+	umode_t listmode;
 };
diff -u --recursive --new-file v2.4.4/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.4.4/linux/include/linux/videodev.h	Thu Apr 12 12:20:31 2001
+++ linux/include/linux/videodev.h	Tue May 22 10:25:36 2001
@@ -33,9 +33,8 @@
 	devfs_handle_t devfs_handle;
 };
 
-extern int videodev_init(void);
 #define VIDEO_MAJOR	81
-extern int video_register_device(struct video_device *, int type);
+extern int video_register_device(struct video_device *, int type, int nr);
 
 #define VFL_TYPE_GRABBER	0
 #define VFL_TYPE_VBI		1
@@ -374,7 +373,8 @@
 #define VID_HARDWARE_OV511	27	
 #define VID_HARDWARE_ZR356700	28	/* Zoran 36700 series */
 #define VID_HARDWARE_W9966	29
-
+#define VID_HARDWARE_SE401	30	/* SE401 USB webcams */
+#define VID_HARDWARE_PWC	31	/* Philips webcams */
 
 /*
  *	Initialiser list
diff -u --recursive --new-file v2.4.4/linux/include/net/addrconf.h linux/include/net/addrconf.h
--- v2.4.4/linux/include/net/addrconf.h	Thu Apr 26 22:17:26 2001
+++ linux/include/net/addrconf.h	Wed May 16 10:31:27 2001
@@ -158,16 +158,8 @@
  *	compute link-local solicited-node multicast address
  */
 
-static inline void addrconf_addr_solict_mult_old(struct in6_addr *addr,
-						     struct in6_addr *solicited)
-{
-	ipv6_addr_set(solicited,
-		      __constant_htonl(0xFF020000), 0,
-		      __constant_htonl(0x1), addr->s6_addr32[3]);
-}
-
-static inline void addrconf_addr_solict_mult_new(struct in6_addr *addr,
-						     struct in6_addr *solicited)
+static inline void addrconf_addr_solict_mult(struct in6_addr *addr,
+					     struct in6_addr *solicited)
 {
 	ipv6_addr_set(solicited,
 		      __constant_htonl(0xFF020000), 0,
diff -u --recursive --new-file v2.4.4/linux/include/net/ipconfig.h linux/include/net/ipconfig.h
--- v2.4.4/linux/include/net/ipconfig.h	Mon Jan  4 15:31:35 1999
+++ linux/include/net/ipconfig.h	Tue May  1 20:59:24 2001
@@ -1,21 +1,38 @@
 /*
- *  $Id: ipconfig.h,v 1.3 1999/01/04 20:13:29 davem Exp $
+ *  $Id: ipconfig.h,v 1.4 2001/04/30 04:51:46 davem Exp $
  *
  *  Copyright (C) 1997 Martin Mares
  *
  *  Automatic IP Layer Configuration
  */
 
-extern __u32 root_server_addr;
-extern u8 root_server_path[];
-extern u32 ic_myaddr;
-extern u32 ic_servaddr;
-extern u32 ic_gateway;
-extern u32 ic_netmask;
-extern int ic_enable;
-extern int ic_host_name_set;
-extern int ic_set_manually;
-extern int ic_proto_enabled;
+/* The following are initdata: */
 
-#define IC_BOOTP 1
-#define IC_RARP 2
+extern int ic_enable;		/* Enable or disable the whole shebang */
+
+extern int ic_proto_enabled;	/* Protocols enabled (see IC_xxx) */
+extern int ic_host_name_set;	/* Host name set by ipconfig? */
+extern int ic_set_manually;	/* IPconfig parameters set manually */
+
+extern u32 ic_myaddr;		/* My IP address */
+extern u32 ic_netmask;		/* Netmask for local subnet */
+extern u32 ic_gateway;		/* Gateway IP address */
+
+extern u32 ic_servaddr;		/* Boot server IP address */
+
+extern u32 root_server_addr;	/* Address of NFS server */
+extern u8 root_server_path[];	/* Path to mount as root */
+
+
+
+/* The following are persistent (not initdata): */
+
+extern int ic_proto_used;	/* Protocol used, if any */
+extern u32 ic_nameserver;	/* DNS server IP address */
+extern u8 ic_domain[];		/* DNS (not NIS) domain name */
+
+/* bits in ic_proto_{enabled,used} */
+#define IC_PROTO	0xFF	/* Protocols mask: */
+#define IC_BOOTP	0x01	/*   BOOTP (or DHCP, see below) */
+#define IC_RARP		0x02	/*   RARP */
+#define IC_USE_DHCP    0x100	/* If on, use DHCP instead of BOOTP */
diff -u --recursive --new-file v2.4.4/linux/include/net/irda/irda-usb.h linux/include/net/irda/irda-usb.h
--- v2.4.4/linux/include/net/irda/irda-usb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irda-usb.h	Tue May  1 16:05:00 2001
@@ -0,0 +1,120 @@
+/*****************************************************************************
+ *
+ * Filename:      irda-usb.h
+ * Version:       0.8
+ * Description:   IrDA-USB Driver
+ * Status:        Experimental 
+ * Author:        Dag Brattli <dag@brattli.net>
+ *
+ *      Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+ *	Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+ *          
+ *	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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *****************************************************************************/
+
+#include <linux/time.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irda_device.h>
+
+#define RX_COPY_THRESHOLD 200
+#define IRDA_USB_MAX_MTU 2051
+#define IRDA_USB_SPEED_MTU 64		/* Weird, but work like this */
+
+/*
+ * Maximum number of URB on the Rx and Tx path, a number larger than 1
+ * is required for handling back-to-back (brickwalled) frames 
+ */
+#define IU_MAX_ACTIVE_RX_URBS 1
+#define IU_MAX_RX_URBS	(IU_MAX_ACTIVE_RX_URBS + 1) 
+#define IU_MAX_TX_URBS  1
+
+/* Inbound header */
+#define MEDIA_BUSY    0x80
+
+#define SPEED_2400    0x01
+#define SPEED_9600    0x02
+#define SPEED_19200   0x03
+#define SPEED_38400   0x04
+#define SPEED_57600   0x05
+#define SPEED_115200  0x06
+#define SPEED_576000  0x07
+#define SPEED_1152000 0x08
+#define SPEED_4000000 0x09
+
+/* device_info flags in struct usb_device_id */
+#define IUC_DEFAULT	0x00	/* Basic device compliant with 1.0 spec */
+#define IUC_SPEED_BUG	0x01	/* Device doesn't set speed after the frame */
+#define IUC_SIR_ONLY	0x02	/* Device doesn't behave at FIR speeds */
+#define IUC_SMALL_PKT	0x04	/* Device doesn't behave with big Rx packets */
+#define IUC_NO_WINDOW	0x08	/* Device doesn't behave with big Rx window */
+#define IUC_MAX_WINDOW	0x10	/* Device underestimate the Rx window */
+#define IUC_MAX_XBOFS	0x20	/* Device need more xbofs than advertised */
+
+#define USB_IRDA_HEADER   0x01
+#define USB_CLASS_IRDA    0x02 /* USB_CLASS_APP_SPEC subclass */ 
+#define USB_DT_IRDA       0x21
+
+struct irda_class_desc {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 bcdSpecRevision;
+	__u8  bmDataSize;
+	__u8  bmWindowSize;
+	__u8  bmMinTurnaroundTime;
+	__u16 wBaudRate;
+	__u8  bmAdditionalBOFs;
+	__u8  bIrdaRateSniff;
+	__u8  bMaxUnicastList;
+} __attribute__ ((packed));
+
+struct irda_usb_cb {
+	struct irda_class_desc *irda_desc;
+	struct usb_device *usbdev;	/* init: probe_irda */
+	unsigned int ifnum;		/* Interface number of the USB dev. */
+	int netopen;			/* Device is active for network */
+	int present;			/* Device is present on the bus */
+	__u32 capability;		/* Capability of the hardware */
+	__u8  bulk_in_ep, bulk_out_ep;	/* Endpoint assignments */
+	__u16 bulk_out_mtu;
+	
+	wait_queue_head_t wait_q;	/* for timeouts */
+
+	struct urb rx_urb[IU_MAX_RX_URBS];  /* URBs used to receive data frames */
+	struct urb *rx_idle_urb;         /* Pointer to idle URB in Rx path */
+	struct urb tx_urb;		/* URB used to send data frames */
+	struct urb speed_urb;		/* URB used to send speed commands */
+	
+	struct net_device *netdev;	/* Yes! we are some kind of netdev. */
+	struct net_device_stats stats;
+	struct irlap_cb   *irlap;	/* The link layer we are binded to */
+	struct qos_info qos;		 
+	hashbin_t *tx_list;		/* Queued transmit skb's */
+
+        struct timeval stamp;
+	struct timeval now;
+
+	spinlock_t lock;		/* For serializing operations */
+
+	__u16 xbofs;			/* Current xbofs setting */
+	__s16 new_xbofs;		/* xbofs we need to set */
+	__u32 speed;			/* Current speed */
+	__s32 new_speed;		/* speed we need to set */
+	__u32 flags;			/* Interface flags */
+};
+
+
diff -u --recursive --new-file v2.4.4/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.4.4/linux/include/net/irda/irda.h	Fri Apr 27 15:48:59 2001
+++ linux/include/net/irda/irda.h	Tue May 22 11:17:55 2001
@@ -71,7 +71,9 @@
         func }
 #else
 #define IRDA_DEBUG(n, args...)
-#define ASSERT(expr, func)
+#define ASSERT(expr, func) \
+if(!(expr)) do { \
+        func } while (0)
 #endif /* CONFIG_IRDA_DEBUG */
 
 #define WARNING(args...) printk(KERN_WARNING args)
diff -u --recursive --new-file v2.4.4/linux/include/net/protocol.h linux/include/net/protocol.h
--- v2.4.4/linux/include/net/protocol.h	Fri Apr 27 15:48:20 2001
+++ linux/include/net/protocol.h	Tue May 22 11:17:36 2001
@@ -67,7 +67,6 @@
 extern struct inet_protocol *inet_protos[MAX_INET_PROTOS];
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-extern struct inet6_protocol *inet6_protocol_base;
 extern struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
 #endif
 
diff -u --recursive --new-file v2.4.4/linux/include/net/snmp.h linux/include/net/snmp.h
--- v2.4.4/linux/include/net/snmp.h	Fri Apr 27 15:48:20 2001
+++ linux/include/net/snmp.h	Tue May 22 11:17:36 2001
@@ -14,7 +14,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- *		$Id: snmp.h,v 1.17 2000/09/21 01:31:50 davem Exp $
+ *		$Id: snmp.h,v 1.18 2001/05/16 16:45:35 davem Exp $
  *
  */
  
@@ -199,6 +199,7 @@
 	unsigned long	OfoPruned;
 	unsigned long	OutOfWindowIcmps; 
 	unsigned long	LockDroppedIcmps; 
+        unsigned long   ArpFilter;
 	unsigned long	TimeWaited; 
 	unsigned long	TimeWaitRecycled; 
 	unsigned long	TimeWaitKilled; 
diff -u --recursive --new-file v2.4.4/linux/include/net/syncppp.h linux/include/net/syncppp.h
--- v2.4.4/linux/include/net/syncppp.h	Tue Mar  6 19:44:37 2001
+++ linux/include/net/syncppp.h	Thu May 24 15:14:08 2001
@@ -94,5 +94,7 @@
 #define SPPPIOCCISCO	(SIOCDEVPRIVATE)
 #define SPPPIOCPPP	(SIOCDEVPRIVATE+1)
 #define SPPPIOCDEBUG	(SIOCDEVPRIVATE+2)
+#define SPPPIOCSFLAGS	(SIOCDEVPRIVATE+3)
+#define SPPPIOCGFLAGS	(SIOCDEVPRIVATE+4)
 
 #endif /* _SYNCPPP_H_ */
diff -u --recursive --new-file v2.4.4/linux/init/main.c linux/init/main.c
--- v2.4.4/linux/init/main.c	Fri Apr 27 14:23:40 2001
+++ linux/init/main.c	Tue May 22 09:35:42 2001
@@ -93,7 +93,6 @@
 extern void ppc_init(void);
 extern void sysctl_init(void);
 extern void signals_init(void);
-extern void bdev_init(void);
 extern int init_pcmcia_ds(void);
 extern void net_notifier_init(void);
 
@@ -108,9 +107,6 @@
 #if defined(CONFIG_SYSVIPC)
 extern void ipc_init(void);
 #endif
-#if defined(CONFIG_QUOTA)
-extern void dquot_init_hash(void);
-#endif
 
 /*
  * Boot command-line arguments
@@ -561,9 +557,6 @@
 #endif
 	mem_init();
 	kmem_cache_sizes_init();
-#ifdef CONFIG_PROC_FS
-	proc_root_init();
-#endif
 	mempages = num_physpages;
 
 	fork_init(mempages);
@@ -575,14 +568,12 @@
 	ccwcache_init();
 #endif
 	signals_init();
-	bdev_init();
-	inode_init(mempages);
+#ifdef CONFIG_PROC_FS
+	proc_root_init();
+#endif
 #if defined(CONFIG_SYSVIPC)
 	ipc_init();
 #endif
-#if defined(CONFIG_QUOTA)
-	dquot_init_hash();
-#endif
 	check_bugs();
 	printk("POSIX conformance testing by UNIFIX\n");
 
@@ -638,9 +629,6 @@
  */
 static void __init do_basic_setup(void)
 {
-#ifdef CONFIG_BLK_DEV_INITRD
-	int real_root_mountflags;
-#endif
 
 	/*
 	 * Tell the world that we're going to be the grim
@@ -707,22 +695,43 @@
 	/* Networking initialization needs a process context */ 
 	sock_init();
 
-#ifdef CONFIG_BLK_DEV_INITRD
-	real_root_dev = ROOT_DEV;
-	real_root_mountflags = root_mountflags;
-	if (initrd_start && mount_initrd) root_mountflags &= ~MS_RDONLY;
-	else mount_initrd =0;
-#endif
-
 	start_context_thread();
 	do_initcalls();
 
 #ifdef CONFIG_IRDA
+	irda_proto_init();
 	irda_device_init(); /* Must be done after protocol initialization */
 #endif
 #ifdef CONFIG_PCMCIA
 	init_pcmcia_ds();		/* Do this last */
 #endif
+}
+
+extern void rd_load(void);
+extern void initrd_load(void);
+
+/*
+ * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
+ */
+static void prepare_namespace(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	int real_root_mountflags = root_mountflags;
+	if (!initrd_start)
+		mount_initrd = 0;
+	if (mount_initrd)
+		root_mountflags &= ~MS_RDONLY;
+	real_root_dev = ROOT_DEV;
+#endif
+
+#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (mount_initrd)
+		initrd_load();
+	else
+#endif
+	rd_load();
+#endif
 
 	/* Mount the root filesystem.. */
 	mount_root();
@@ -754,6 +763,8 @@
 {
 	lock_kernel();
 	do_basic_setup();
+
+	prepare_namespace();
 
 	/*
 	 * Ok, we have completed the initial bootup, and
diff -u --recursive --new-file v2.4.4/linux/ipc/shm.c linux/ipc/shm.c
--- v2.4.4/linux/ipc/shm.c	Mon Mar 19 12:35:08 2001
+++ linux/ipc/shm.c	Sat May 19 17:47:55 2001
@@ -497,14 +497,21 @@
 		if (shp == NULL) 
 			goto out_up;
 		err = shm_checkid(shp, shmid);
-		if (err == 0) {
-			if (shp->shm_nattch){
-				shp->shm_flags |= SHM_DEST;
-				/* Do not find it any more */
-				shp->shm_perm.key = IPC_PRIVATE;
-			} else
-				shm_destroy (shp);
+		if(err)
+			goto out_unlock_up;
+		if (current->euid != shp->shm_perm.uid &&
+		    current->euid != shp->shm_perm.cuid && 
+		    !capable(CAP_SYS_ADMIN)) {
+			err=-EPERM;
+			goto out_unlock_up;
 		}
+		if (shp->shm_nattch){
+			shp->shm_flags |= SHM_DEST;
+			/* Do not find it any more */
+			shp->shm_perm.key = IPC_PRIVATE;
+		} else
+			shm_destroy (shp);
+
 		/* Unlock */
 		shm_unlock(shmid);
 		up(&shm_ids.sem);
diff -u --recursive --new-file v2.4.4/linux/kernel/context.c linux/kernel/context.c
--- v2.4.4/linux/kernel/context.c	Fri Jan 12 09:52:41 2001
+++ linux/kernel/context.c	Sat May 19 17:47:55 2001
@@ -101,8 +101,10 @@
 		if (signal_pending(curtask)) {
 			while (waitpid(-1, (unsigned int *)0, __WALL|WNOHANG) > 0)
 				;
+			spin_lock_irq(&curtask->sigmask_lock);
 			flush_signals(curtask);
 			recalc_sigpending(curtask);
+			spin_unlock_irq(&curtask->sigmask_lock);
 		}
 	}
 }
diff -u --recursive --new-file v2.4.4/linux/kernel/exit.c linux/kernel/exit.c
--- v2.4.4/linux/kernel/exit.c	Fri Feb  9 11:29:44 2001
+++ linux/kernel/exit.c	Fri May  4 14:44:06 2001
@@ -62,6 +62,7 @@
 		current->counter += p->counter;
 		if (current->counter >= MAX_COUNTER)
 			current->counter = MAX_COUNTER;
+		p->pid = 0;
 		free_task_struct(p);
 	} else {
 		printk("task releasing itself\n");
diff -u --recursive --new-file v2.4.4/linux/kernel/fork.c linux/kernel/fork.c
--- v2.4.4/linux/kernel/fork.c	Thu Apr 26 06:11:17 2001
+++ linux/kernel/fork.c	Mon Apr 30 22:23:29 2001
@@ -666,17 +666,15 @@
 	p->pdeath_signal = 0;
 
 	/*
-	 * Give the parent's dynamic priority entirely to the child.  The
-	 * total amount of dynamic priorities in the system doesn't change
-	 * (more scheduling fairness), but the child will run first, which
-	 * is especially useful in avoiding a lot of copy-on-write faults
-	 * if the child for a fork() just wants to do a few simple things
-	 * and then exec(). This is only important in the first timeslice.
-	 * In the long run, the scheduling behavior is unchanged.
+	 * "share" dynamic priority between parent and child, thus the
+	 * total amount of dynamic priorities in the system doesnt change,
+	 * more scheduling fairness. This is only important in the first
+	 * timeslice, on the long run the scheduling behaviour is unchanged.
 	 */
-	p->counter = current->counter;
-	current->counter = 0;
-	current->need_resched = 1;
+	p->counter = (current->counter + 1) >> 1;
+	current->counter >>= 1;
+	if (!current->counter)
+		current->need_resched = 1;
 
 	/*
 	 * Ok, add it to the run-queues and make it
diff -u --recursive --new-file v2.4.4/linux/kernel/kmod.c linux/kernel/kmod.c
--- v2.4.4/linux/kernel/kmod.c	Sat Dec 30 18:16:13 2000
+++ linux/kernel/kmod.c	Tue May  1 16:05:00 2001
@@ -157,19 +157,18 @@
 }
 
 /**
- *	request_module - try to load a kernel module
- *	@module_name: Name of module
+ * request_module - try to load a kernel module
+ * @module_name: Name of module
  *
- * 	Load a module using the user mode module loader. The function returns
- *	zero on success or a negative errno code on failure. Note that a
- * 	successful module load does not mean the module did not then unload
- *	and exit on an error of its own. Callers must check that the service
- *	they requested is now available not blindly invoke it.
+ * Load a module using the user mode module loader. The function returns
+ * zero on success or a negative errno code on failure. Note that a
+ * successful module load does not mean the module did not then unload
+ * and exit on an error of its own. Callers must check that the service
+ * they requested is now available not blindly invoke it.
  *
- *	If module auto-loading support is disabled then this function
- *	becomes a no-operation.
+ * If module auto-loading support is disabled then this function
+ * becomes a no-operation.
  */
- 
 int request_module(const char * module_name)
 {
 	pid_t pid;
diff -u --recursive --new-file v2.4.4/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.4.4/linux/kernel/ksyms.c	Fri Apr 27 14:23:25 2001
+++ linux/kernel/ksyms.c	Thu May 24 15:20:18 2001
@@ -98,6 +98,8 @@
 EXPORT_SYMBOL(free_pages);
 #ifndef CONFIG_DISCONTIGMEM
 EXPORT_SYMBOL(contig_page_data);
+#else
+EXPORT_SYMBOL(alloc_pages);
 #endif
 EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(kmem_find_general_cachep);
@@ -146,7 +148,7 @@
 EXPORT_SYMBOL(path_walk);
 EXPORT_SYMBOL(path_release);
 EXPORT_SYMBOL(__user_walk);
-EXPORT_SYMBOL(lookup_one);
+EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(lookup_hash);
 EXPORT_SYMBOL(sys_close);
 EXPORT_SYMBOL(dcache_lock);
@@ -174,6 +176,7 @@
 EXPORT_SYMBOL(check_disk_change);
 EXPORT_SYMBOL(__invalidate_buffers);
 EXPORT_SYMBOL(invalidate_inodes);
+EXPORT_SYMBOL(invalidate_device);
 EXPORT_SYMBOL(invalidate_inode_pages);
 EXPORT_SYMBOL(truncate_inode_pages);
 EXPORT_SYMBOL(fsync_dev);
@@ -185,6 +188,8 @@
 EXPORT_SYMBOL(notify_change);
 EXPORT_SYMBOL(set_blocksize);
 EXPORT_SYMBOL(getblk);
+EXPORT_SYMBOL(cdget);
+EXPORT_SYMBOL(cdput);
 EXPORT_SYMBOL(bdget);
 EXPORT_SYMBOL(bdput);
 EXPORT_SYMBOL(bread);
@@ -202,6 +207,7 @@
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(generic_block_bmap);
+EXPORT_SYMBOL(waitfor_one_page);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
@@ -262,6 +268,8 @@
 EXPORT_SYMBOL(dentry_open);
 EXPORT_SYMBOL(filemap_nopage);
 EXPORT_SYMBOL(filemap_sync);
+EXPORT_SYMBOL(filemap_fdatasync);
+EXPORT_SYMBOL(filemap_fdatawait);
 EXPORT_SYMBOL(lock_page);
 
 /* device registration */
@@ -314,7 +322,7 @@
 EXPORT_SYMBOL(register_filesystem);
 EXPORT_SYMBOL(unregister_filesystem);
 EXPORT_SYMBOL(kern_mount);
-EXPORT_SYMBOL(kern_umount);
+EXPORT_SYMBOL(__mntput);
 EXPORT_SYMBOL(may_umount);
 
 /* executable format registration */
@@ -477,7 +485,6 @@
 
 /* Added to make file system as module */
 EXPORT_SYMBOL(sys_tz);
-EXPORT_SYMBOL(__wait_on_super);
 EXPORT_SYMBOL(file_fsync);
 EXPORT_SYMBOL(fsync_inode_buffers);
 EXPORT_SYMBOL(clear_inode);
diff -u --recursive --new-file v2.4.4/linux/kernel/module.c linux/kernel/module.c
--- v2.4.4/linux/kernel/module.c	Fri Feb 16 16:02:37 2001
+++ linux/kernel/module.c	Tue May  1 16:05:00 2001
@@ -554,8 +554,8 @@
 	put_mod_name(name);
 
 	/* Initialize the module.  */
-	mod->flags |= MOD_INITIALIZING;
 	atomic_set(&mod->uc.usecount,1);
+	mod->flags |= MOD_INITIALIZING;
 	if (mod->init && (error = mod->init()) != 0) {
 		atomic_set(&mod->uc.usecount,0);
 		mod->flags &= ~MOD_INITIALIZING;
@@ -613,11 +613,6 @@
 	if (name_user) {
 		if ((error = get_mod_name(name_user, &name)) < 0)
 			goto out;
-		if (error == 0) {
-			error = -EINVAL;
-			put_mod_name(name);
-			goto out;
-		}
 		error = -ENOENT;
 		if ((mod = find_module(name)) == NULL) {
 			put_mod_name(name);
@@ -847,7 +842,6 @@
 		bufsize -= len;
 		space += len;
 	}
-
 	if (put_user(i, ret))
 		return -EFAULT;
 	else
@@ -876,8 +870,11 @@
 		info.addr = (unsigned long)mod;
 		info.size = mod->size;
 		info.flags = mod->flags;
+		
+		/* usecount is one too high here - report appropriately to
+		   compensate for locking */
 		info.usecount = (mod_member_present(mod, can_unload)
-				 && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount));
+				 && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount)-1);
 
 		if (copy_to_user(buf, &info, sizeof(struct module_info)))
 			return -EFAULT;
@@ -909,15 +906,17 @@
 			goto out;
 		}
 		err = -ENOENT;
-		if (namelen == 0)
-			mod = &kernel_module;
-		else if ((mod = find_module(name)) == NULL) {
+		if ((mod = find_module(name)) == NULL) {
 			put_mod_name(name);
 			goto out;
 		}
 		put_mod_name(name);
 	}
 
+	/* __MOD_ touches the flags. We must avoid that */
+	
+	atomic_inc(&mod->uc.usecount);
+		
 	switch (which)
 	{
 	case 0:
@@ -942,6 +941,8 @@
 		err = -EINVAL;
 		break;
 	}
+	atomic_dec(&mod->uc.usecount);
+	
 out:
 	unlock_kernel();
 	return err;
diff -u --recursive --new-file v2.4.4/linux/kernel/resource.c linux/kernel/resource.c
--- v2.4.4/linux/kernel/resource.c	Fri Feb  9 11:29:44 2001
+++ linux/kernel/resource.c	Mon May 21 18:10:36 2001
@@ -297,20 +297,23 @@
 #define MAXRESERVE 4
 static int __init reserve_setup(char *str)
 {
-	int opt = 2, io_start, io_num;
 	static int reserved = 0;
 	static struct resource reserve[MAXRESERVE];
 
-    while (opt==2) {
+	for (;;) {
+		int io_start, io_num;
 		int x = reserved;
 
-        if (get_option (&str, &io_start) != 2) break;
-        if (get_option (&str, &io_num)   == 0) break;
+		if (get_option (&str, &io_start) != 2)
+			break;
+		if (get_option (&str, &io_num)   == 0)
+			break;
 		if (x < MAXRESERVE) {
 			struct resource *res = reserve + x;
 			res->name = "reserved";
 			res->start = io_start;
 			res->end = io_start + io_num - 1;
+			res->flags = IORESOURCE_BUSY;
 			res->child = NULL;
 			if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
 				reserved = x+1;
diff -u --recursive --new-file v2.4.4/linux/mm/bootmem.c linux/mm/bootmem.c
--- v2.4.4/linux/mm/bootmem.c	Fri Apr 13 20:26:07 2001
+++ linux/mm/bootmem.c	Thu May 24 15:20:18 2001
@@ -83,6 +83,14 @@
 
 	if (!size) BUG();
 
+	if (sidx < 0)
+		BUG();
+	if (eidx < 0)
+		BUG();
+	if (sidx >= eidx)
+		BUG();
+	if ((addr >> PAGE_SHIFT) >= bdata->node_low_pfn)
+		BUG();
 	if (end > bdata->node_low_pfn)
 		BUG();
 	for (i = sidx; i < eidx; i++)
@@ -142,6 +150,9 @@
 							PAGE_SHIFT);
 
 	if (!size) BUG();
+
+	if (align & (align-1))
+		BUG();
 
 	/*
 	 * We try to allocate bootmem pages above 'goal'
diff -u --recursive --new-file v2.4.4/linux/mm/filemap.c linux/mm/filemap.c
--- v2.4.4/linux/mm/filemap.c	Wed Apr 25 16:13:50 2001
+++ linux/mm/filemap.c	Tue May 22 10:52:35 2001
@@ -9,6 +9,7 @@
  * most "normal" filesystems (but you don't /have/ to use this:
  * the NFS filesystem used to do this differently, for example)
  */
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
@@ -284,6 +285,34 @@
 	spin_unlock(&pagecache_lock);
 }
 
+/*
+ * This function is pretty much like __find_page_nolock(), but it only
+ * requires 2 arguments and doesn't mark the page as touched, making it
+ * ideal for ->writepage() clustering and other places where you don't
+ * want to mark the page referenced.
+ *
+ * The caller needs to hold the pagecache_lock.
+ */
+static struct page * FASTCALL(__find_page_simple(struct address_space *, unsigned long));
+static struct page * __find_page_simple(struct address_space *mapping, unsigned long index)
+{
+	struct page **next = page_hash(mapping, index);;
+
+	for (;;) {
+		struct page *page = *next;
+		if (!page)
+			break;
+		next = &page->next_hash;
+		if (page->mapping != mapping)
+			continue;
+		if (page->index != index)
+			continue;
+		return page;
+	}
+
+	return NULL;
+}
+
 static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page)
 {
 	goto inside;
@@ -298,14 +327,9 @@
 		if (page->index == offset)
 			break;
 	}
-	/*
-	 * Touching the page may move it to the active list.
-	 * If we end up with too few inactive pages, we wake
-	 * up kswapd.
-	 */
-	age_page_up(page);
-	if (inactive_shortage() > inactive_target / 2 && free_shortage())
-			wakeup_kswapd();
+	/* Mark the page referenced, kswapd will find it later. */
+	SetPageReferenced(page);
+
 not_found:
 	return page;
 }
@@ -331,7 +355,7 @@
 	return 0;
 }
 
-static int waitfor_one_page(struct page *page)
+int waitfor_one_page(struct page *page)
 {
 	int error = 0;
 	struct buffer_head *bh, *head = page->buffers;
@@ -762,7 +786,6 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
-	struct page **hash;
 	struct page *page;
 	unsigned long start;
 
@@ -783,8 +806,7 @@
 	 */
 	spin_lock(&pagecache_lock);
 	while (--index >= start) {
-		hash = page_hash(mapping, index);
-		page = __find_page_nolock(mapping, index, *hash);
+		page = __find_page_simple(mapping, index);
 		if (!page)
 			break;
 		deactivate_page(page);
@@ -2549,11 +2571,14 @@
 	 *	Linus frestrict idea will clean these up nicely..
 	 */
 	 
-	if (pos > inode->i_sb->s_maxbytes)
+	if (pos >= inode->i_sb->s_maxbytes)
 	{
-		send_sig(SIGXFSZ, current, 0);
-		err = -EFBIG;
-		goto out;	
+		if (count || pos > inode->i_sb->s_maxbytes) {
+			send_sig(SIGXFSZ, current, 0);
+			err = -EFBIG;
+			goto out;
+		}
+		/* zero-length writes at ->s_maxbytes are OK */
 	}
 
 	if (pos + count > inode->i_sb->s_maxbytes)
diff -u --recursive --new-file v2.4.4/linux/mm/mmap.c linux/mm/mmap.c
--- v2.4.4/linux/mm/mmap.c	Fri Apr 13 20:15:55 2001
+++ linux/mm/mmap.c	Thu May 24 15:20:18 2001
@@ -54,7 +54,7 @@
 	 * of num_physpages for safety margin.
 	 */
 
-	long free;
+	unsigned long free;
 	
         /* Sometimes we want to use more memory than we have. */
 	if (sysctl_overcommit_memory)
diff -u --recursive --new-file v2.4.4/linux/mm/oom_kill.c linux/mm/oom_kill.c
--- v2.4.4/linux/mm/oom_kill.c	Tue Nov 14 10:56:46 2000
+++ linux/mm/oom_kill.c	Tue May 15 00:25:41 2001
@@ -191,8 +191,6 @@
  */
 int out_of_memory(void)
 {
-	struct sysinfo swp_info;
-
 	/* Enough free memory?  Not OOM. */
 	if (nr_free_pages() > freepages.min)
 		return 0;
@@ -201,8 +199,7 @@
 		return 0;
 
 	/* Enough swap space left?  Not OOM. */
-	si_swapinfo(&swp_info);
-	if (swp_info.freeswap > 0)
+	if (nr_swap_pages > 0)
 		return 0;
 
 	/* Else... */
diff -u --recursive --new-file v2.4.4/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.4.4/linux/mm/page_alloc.c	Fri Apr 27 14:18:08 2001
+++ linux/mm/page_alloc.c	Thu May 24 15:20:18 2001
@@ -53,7 +53,7 @@
 /*
  * Temporary debugging check.
  */
-#define BAD_RANGE(zone,x) (((zone) != (x)->zone) || (((x)-mem_map) < (zone)->offset) || (((x)-mem_map) >= (zone)->offset+(zone)->size))
+#define BAD_RANGE(zone,x) (((zone) != (x)->zone) || (((x)-mem_map) < (zone)->zone_start_mapnr) || (((x)-mem_map) >= (zone)->zone_start_mapnr+(zone)->size))
 
 /*
  * Buddy system. Hairy. You really aren't expected to understand this
@@ -94,7 +94,7 @@
 	zone = page->zone;
 
 	mask = (~0UL) << order;
-	base = mem_map + zone->offset;
+	base = zone->zone_mem_map;
 	page_idx = page - base;
 	if (page_idx & ~mask)
 		BUG();
@@ -111,7 +111,7 @@
 
 		if (area >= zone->free_area + MAX_ORDER)
 			BUG();
-		if (!test_and_change_bit(index, area->map))
+		if (!__test_and_change_bit(index, area->map))
 			/*
 			 * the buddy page is still allocated.
 			 */
@@ -146,7 +146,7 @@
 }
 
 #define MARK_USED(index, order, area) \
-	change_bit((index) >> (1+(order)), (area)->map)
+	__change_bit((index) >> (1+(order)), (area)->map)
 
 static inline struct page * expand (zone_t *zone, struct page *page,
 	 unsigned long index, int low, int high, free_area_t * area)
@@ -190,8 +190,9 @@
 			if (BAD_RANGE(zone,page))
 				BUG();
 			memlist_del(curr);
-			index = (page - mem_map) - zone->offset;
-			MARK_USED(index, curr_order, area);
+			index = page - zone->zone_mem_map;
+			if (curr_order != MAX_ORDER-1)
+				MARK_USED(index, curr_order, area);
 			zone->free_pages -= 1 << order;
 
 			page = expand(zone, page, index, order, curr_order, area);
@@ -743,7 +744,10 @@
 	unsigned long i, j;
 	unsigned long map_size;
 	unsigned long totalpages, offset, realtotalpages;
-	unsigned int cumulative = 0;
+	const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1);
+
+	if (zone_start_paddr & ~PAGE_MASK)
+		BUG();
 
 	totalpages = 0;
 	for (i = 0; i < MAX_NR_ZONES; i++) {
@@ -812,8 +816,6 @@
 		if (!size)
 			continue;
 
-		zone->offset = offset;
-		cumulative += size;
 		mask = (realsize / zone_balance_ratio[j]);
 		if (mask < zone_balance_min[j])
 			mask = zone_balance_min[j];
@@ -840,28 +842,34 @@
 		zone->zone_start_mapnr = offset;
 		zone->zone_start_paddr = zone_start_paddr;
 
+		if ((zone_start_paddr >> PAGE_SHIFT) & (zone_required_alignment-1))
+			printk("BUG: wrong zone alignment, it will crash\n");
+
 		for (i = 0; i < size; i++) {
 			struct page *page = mem_map + offset + i;
 			page->zone = zone;
-			if (j != ZONE_HIGHMEM) {
+			if (j != ZONE_HIGHMEM)
 				page->virtual = __va(zone_start_paddr);
-				zone_start_paddr += PAGE_SIZE;
-			}
+			zone_start_paddr += PAGE_SIZE;
 		}
 
 		offset += size;
 		mask = -1;
-		for (i = 0; i < MAX_ORDER; i++) {
+		for (i = 0; ; i++) {
 			unsigned long bitmap_size;
 
 			memlist_init(&zone->free_area[i].free_list);
+			if (i == MAX_ORDER-1) {
+				zone->free_area[i].map = NULL;
+				break;
+			}
 			mask += mask;
 			size = (size + ~mask) & mask;
-			bitmap_size = size >> i;
+			bitmap_size = size >> (i+1);
 			bitmap_size = (bitmap_size + 7) >> 3;
 			bitmap_size = LONG_ALIGN(bitmap_size);
 			zone->free_area[i].map = 
-			  (unsigned int *) alloc_bootmem_node(pgdat, bitmap_size);
+			  (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size);
 		}
 	}
 	build_zonelists(pgdat);
diff -u --recursive --new-file v2.4.4/linux/mm/shmem.c linux/mm/shmem.c
--- v2.4.4/linux/mm/shmem.c	Wed Apr 25 14:46:21 2001
+++ linux/mm/shmem.c	Tue May 22 09:31:25 2001
@@ -516,7 +516,7 @@
 		inode->i_gid = current->fsgid;
 		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks = 0;
-		inode->i_rdev = to_kdev_t(dev);
+		inode->i_rdev = NODEV;
 		inode->i_mapping->a_ops = &shmem_aops;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		spin_lock_init (&inode->u.shmem_i.lock);
diff -u --recursive --new-file v2.4.4/linux/mm/slab.c linux/mm/slab.c
--- v2.4.4/linux/mm/slab.c	Sun Mar 25 10:37:48 2001
+++ linux/mm/slab.c	Tue May 22 10:23:16 2001
@@ -1492,20 +1492,20 @@
  * @flags: the type of memory to allocate.
  *
  * kmalloc is the normal method of allocating memory
- * in the kernel.  The @flags argument may be one of:
+ * in the kernel.
  *
- * %GFP_BUFFER - XXX
+ * The @flags argument may be one of:
  *
- * %GFP_ATOMIC - allocation will not sleep.  Use inside interrupt handlers.
+ * %GFP_USER - Allocate memory on behalf of user.  May sleep.
  *
- * %GFP_USER - allocate memory on behalf of user.  May sleep.
+ * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
  *
- * %GFP_KERNEL - allocate normal kernel ram.  May sleep.
+ * %GFP_ATOMIC - Allocation will not sleep.  Use inside interrupt handlers.
  *
- * %GFP_NFS - has a slightly lower probability of sleeping than %GFP_KERNEL.
- * Don't use unless you're in the NFS code.
- *
- * %GFP_KSWAPD - Don't use unless you're modifying kswapd.
+ * Additionally, the %GFP_DMA flag may be set to indicate the memory
+ * must be suitable for DMA.  This can mean different things on different
+ * platforms.  For example, on i386, it means that the memory must come
+ * from the first 16MB.
  */
 void * kmalloc (size_t size, int flags)
 {
@@ -1958,7 +1958,7 @@
 				unsigned long count, void *data)
 {
 #ifdef CONFIG_SMP
-	char kbuf[MAX_SLABINFO_WRITE], *tmp;
+	char kbuf[MAX_SLABINFO_WRITE+1], *tmp;
 	int limit, batchcount, res;
 	struct list_head *p;
 	
@@ -1966,6 +1966,7 @@
 		return -EINVAL;
 	if (copy_from_user(&kbuf, buffer, count))
 		return -EFAULT;
+	kbuf[MAX_SLABINFO_WRITE] = '\0'; 
 
 	tmp = strchr(kbuf, ' ');
 	if (!tmp)
diff -u --recursive --new-file v2.4.4/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.4.4/linux/mm/swap_state.c	Wed Apr 25 14:46:21 2001
+++ linux/mm/swap_state.c	Thu May 24 15:20:18 2001
@@ -189,7 +189,6 @@
 struct page * read_swap_cache_async(swp_entry_t entry)
 {
 	struct page *found_page = 0, *new_page;
-	unsigned long new_page_addr;
 	
 	/*
 	 * Make sure the swap entry is still in use.
@@ -203,10 +202,9 @@
 	if (found_page)
 		goto out_free_swap;
 
-	new_page_addr = __get_free_page(GFP_USER);
-	if (!new_page_addr)
+	new_page = alloc_page(GFP_USER);
+	if (!new_page)
 		goto out_free_swap;	/* Out of memory */
-	new_page = virt_to_page(new_page_addr);
 
 	/*
 	 * Check the swap cache again, in case we stalled above.
@@ -217,7 +215,8 @@
 	/* 
 	 * Add it to the swap cache and read its contents.
 	 */
-	lock_page(new_page);
+	if (TryLockPage(new_page))
+		BUG();
 	add_to_swap_cache(new_page, entry);
 	rw_swap_page(READ, new_page);
 	return new_page;
diff -u --recursive --new-file v2.4.4/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.4.4/linux/mm/swapfile.c	Wed Apr 25 14:46:21 2001
+++ linux/mm/swapfile.c	Sat May 19 17:16:18 2001
@@ -134,7 +134,7 @@
 bad_count:
 	printk(KERN_ERR "get_swap_page: bad count %hd from %p\n",
 	       count, __builtin_return_address(0));
-	goto out;
+	return entry;
 }
 
 
diff -u --recursive --new-file v2.4.4/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.4.4/linux/mm/vmalloc.c	Fri Mar 23 16:14:00 2001
+++ linux/mm/vmalloc.c	Tue May 22 19:54:04 2001
@@ -180,19 +180,13 @@
 	addr = VMALLOC_START;
 	write_lock(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
-		if ((size + addr) < addr) {
-			write_unlock(&vmlist_lock);
-			kfree(area);
-			return NULL;
-		}
-		if (size + addr < (unsigned long) tmp->addr)
+		if ((size + addr) < addr)
+			goto out;
+		if (size + addr <= (unsigned long) tmp->addr)
 			break;
 		addr = tmp->size + (unsigned long) tmp->addr;
-		if (addr > VMALLOC_END-size) {
-			write_unlock(&vmlist_lock);
-			kfree(area);
-			return NULL;
-		}
+		if (addr > VMALLOC_END-size)
+			goto out;
 	}
 	area->flags = flags;
 	area->addr = (void *)addr;
@@ -201,6 +195,11 @@
 	*p = area;
 	write_unlock(&vmlist_lock);
 	return area;
+
+out:
+	write_unlock(&vmlist_lock);
+	kfree(area);
+	return NULL;
 }
 
 void vfree(void * addr)
diff -u --recursive --new-file v2.4.4/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.4.4/linux/mm/vmscan.c	Thu Apr 12 12:10:25 2001
+++ linux/mm/vmscan.c	Thu May 24 15:20:18 2001
@@ -24,6 +24,8 @@
 
 #include <asm/pgalloc.h>
 
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
 /*
  * The swap-out function returns 1 if it successfully
  * scanned all the pages it was asked to (`count').
@@ -228,6 +230,8 @@
 	unsigned long address;
 	struct vm_area_struct* vma;
 
+	if (!count)
+		return 1;
 	/*
 	 * Go through process' page directory.
 	 */
@@ -271,7 +275,12 @@
 static inline int swap_amount(struct mm_struct *mm)
 {
 	int nr = mm->rss >> SWAP_SHIFT;
-	return nr < SWAP_MIN ? SWAP_MIN : nr;
+	if (nr < SWAP_MIN) {
+		nr = SWAP_MIN;
+		if (nr > mm->rss)
+			nr = mm->rss;
+	}
+	return nr;
 }
 
 static int swap_out(unsigned int priority, int gfp_mask)
@@ -285,7 +294,7 @@
 		retval = swap_out_mm(mm, swap_amount(mm));
 
 	/* Then, look at the other mm's */
-	counter = mmlist_nr >> priority;
+	counter = (mmlist_nr << SWAP_SHIFT) >> priority;
 	do {
 		struct list_head *p;
 
@@ -350,7 +359,7 @@
 		}
 
 		/* Page is or was in use?  Move it to the active list. */
-		if (PageTestandClearReferenced(page) || page->age > 0 ||
+		if (PageReferenced(page) || page->age > 0 ||
 				(!page->buffers && page_count(page) > 1)) {
 			del_page_from_inactive_clean_list(page);
 			add_page_to_active_list(page);
@@ -453,7 +462,7 @@
 		}
 
 		/* Page is or was in use?  Move it to the active list. */
-		if (PageTestandClearReferenced(page) || page->age > 0 ||
+		if (PageReferenced(page) || page->age > 0 ||
 				(!page->buffers && page_count(page) > 1) ||
 				page_ramdisk(page)) {
 			del_page_from_inactive_dirty_list(page);
@@ -631,21 +640,42 @@
 /**
  * refill_inactive_scan - scan the active list and find pages to deactivate
  * @priority: the priority at which to scan
- * @oneshot: exit after deactivating one page
+ * @target: number of pages to deactivate, zero for background aging
  *
  * This function will scan a portion of the active list to find
  * unused pages, those pages will then be moved to the inactive list.
  */
-int refill_inactive_scan(unsigned int priority, int oneshot)
+int refill_inactive_scan(unsigned int priority, int target)
 {
 	struct list_head * page_lru;
 	struct page * page;
-	int maxscan, page_active = 0;
-	int ret = 0;
+	int maxscan = nr_active_pages >> priority;
+	int page_active = 0;
+	int nr_deactivated = 0;
+
+	/*
+	 * When we are background aging, we try to increase the page aging
+	 * information in the system. When we have too many inactive pages
+	 * we don't do background aging since having all pages on the
+	 * inactive list decreases aging information.
+	 *
+	 * Since not all active pages have to be on the active list, we round
+	 * nr_active_pages up to num_physpages/2, if needed.
+	 */
+	if (!target) {
+		int inactive = nr_free_pages() + nr_inactive_clean_pages() +
+						nr_inactive_dirty_pages;
+		int active = MAX(nr_active_pages, num_physpages / 2);
+		if (active > 10 * inactive)
+			maxscan = nr_active_pages >> 4;
+		else if (active > 3 * inactive)
+			maxscan = nr_active_pages >> 8;
+		else
+			return 0;
+	}
 
 	/* Take the lock while messing with the list... */
 	spin_lock(&pagemap_lru_lock);
-	maxscan = nr_active_pages >> priority;
 	while (maxscan-- > 0 && (page_lru = active_list.prev) != &active_list) {
 		page = list_entry(page_lru, struct page, lru);
 
@@ -683,21 +713,21 @@
 		}
 		/*
 		 * If the page is still on the active list, move it
-		 * to the other end of the list. Otherwise it was
-		 * deactivated by age_page_down and we exit successfully.
+		 * to the other end of the list. Otherwise we exit if
+		 * we have done enough work.
 		 */
 		if (page_active || PageActive(page)) {
 			list_del(page_lru);
 			list_add(page_lru, &active_list);
 		} else {
-			ret = 1;
-			if (oneshot)
+			nr_deactivated++;
+			if (target && nr_deactivated >= target)
 				break;
 		}
 	}
 	spin_unlock(&pagemap_lru_lock);
 
-	return ret;
+	return nr_deactivated;
 }
 
 /*
@@ -709,7 +739,7 @@
 	pg_data_t *pgdat = pgdat_list;
 	int sum = 0;
 	int freeable = nr_free_pages() + nr_inactive_clean_pages();
-	int freetarget = freepages.high + inactive_target / 3;
+	int freetarget = freepages.high;
 
 	/* Are we low on free pages globally? */
 	if (freeable < freetarget)
@@ -721,9 +751,8 @@
 		for(i = 0; i < MAX_NR_ZONES; i++) {
 			zone_t *zone = pgdat->node_zones+ i;
 			if (zone->size && (zone->inactive_clean_pages +
-					zone->free_pages < zone->pages_min+1)) {
-				/* + 1 to have overlap with alloc_pages() !! */
-				sum += zone->pages_min + 1;
+					zone->free_pages < zone->pages_min)) {
+				sum += zone->pages_min;
 				sum -= zone->free_pages;
 				sum -= zone->inactive_clean_pages;
 			}
@@ -777,38 +806,46 @@
 }
 
 /*
- * We need to make the locks finer granularity, but right
- * now we need this so that we can do page allocations
- * without holding the kernel lock etc.
+ * Refill_inactive is the function used to scan and age the pages on
+ * the active list and in the working set of processes, moving the
+ * little-used pages to the inactive list.
  *
- * We want to try to free "count" pages, and we want to 
- * cluster them so that we get good swap-out behaviour.
+ * When called by kswapd, we try to deactivate as many pages as needed
+ * to recover from the inactive page shortage. This makes it possible
+ * for kswapd to keep up with memory demand so user processes can get
+ * low latency on memory allocations.
  *
- * OTOH, if we're a user process (and not kswapd), we
- * really care about latency. In that case we don't try
- * to free too many pages.
+ * However, when the system starts to get overloaded we can get called
+ * by user processes. For user processes we want to both reduce the
+ * latency and make sure that multiple user processes together don't
+ * deactivate too many pages. To achieve this we simply do less work
+ * when called from a user process.
  */
 #define DEF_PRIORITY (6)
 static int refill_inactive(unsigned int gfp_mask, int user)
 {
 	int count, start_count, maxtry;
 
-	count = inactive_shortage() + free_shortage();
-	if (user)
+	if (user) {
 		count = (1 << page_cluster);
-	start_count = count;
+		maxtry = 6;
+	} else {
+		count = inactive_shortage();
+		maxtry = 1 << DEF_PRIORITY;
+	}
 
-	maxtry = 6;
+	start_count = count;
 	do {
 		if (current->need_resched) {
 			__set_current_state(TASK_RUNNING);
 			schedule();
+			if (!inactive_shortage())
+				return 1;
 		}
 
-		while (refill_inactive_scan(DEF_PRIORITY, 1)) {
-			if (--count <= 0)
-				goto done;
-		}
+		count -= refill_inactive_scan(DEF_PRIORITY, count);
+		if (count <= 0)
+			goto done;
 
 		/* If refill_inactive_scan failed, try to page stuff out.. */
 		swap_out(DEF_PRIORITY, gfp_mask);
@@ -834,8 +871,7 @@
 	 * before we get around to moving them to the other
 	 * list, so this is a relatively cheap operation.
 	 */
-	if (free_shortage() || nr_inactive_dirty_pages > nr_free_pages() +
-			nr_inactive_clean_pages())
+	if (free_shortage())
 		ret += page_launder(gfp_mask, user);
 
 	/*
@@ -869,7 +905,6 @@
 
 DECLARE_WAIT_QUEUE_HEAD(kswapd_wait);
 DECLARE_WAIT_QUEUE_HEAD(kswapd_done);
-struct task_struct *kswapd_task;
 
 /*
  * The background pageout daemon, started as a kernel thread
@@ -888,11 +923,9 @@
 {
 	struct task_struct *tsk = current;
 
-	tsk->session = 1;
-	tsk->pgrp = 1;
+	daemonize();
 	strcpy(tsk->comm, "kswapd");
 	sigfillset(&tsk->blocked);
-	kswapd_task = tsk;
 	
 	/*
 	 * Tell the memory management that we're a "memory allocator",
@@ -918,18 +951,15 @@
 		if (inactive_shortage() || free_shortage()) 
 			do_try_to_free_pages(GFP_KSWAPD, 0);
 
-		/*
-		 * Do some (very minimal) background scanning. This
-		 * will scan all pages on the active list once
-		 * every minute. This clears old referenced bits
-		 * and moves unused pages to the inactive list.
-		 */
-		refill_inactive_scan(DEF_PRIORITY, 0);
-
-		/* Once a second, recalculate some VM stats. */
+		/* Once a second ... */
 		if (time_after(jiffies, recalc + HZ)) {
 			recalc = jiffies;
+
+			/* Recalculate VM statistics. */
 			recalculate_vm_stats();
+
+			/* Do background page aging. */
+			refill_inactive_scan(DEF_PRIORITY, 0);
 		}
 
 		run_task_queue(&tq_disk);
@@ -964,8 +994,8 @@
 
 void wakeup_kswapd(void)
 {
-	if (current != kswapd_task)
-		wake_up_process(kswapd_task);
+	if (waitqueue_active(&kswapd_wait))
+		wake_up_interruptible(&kswapd_wait);
 }
 
 /*
@@ -997,8 +1027,7 @@
 	struct task_struct *tsk = current;
 	pg_data_t *pgdat;
 
-	tsk->session = 1;
-	tsk->pgrp = 1;
+	daemonize();
 	strcpy(tsk->comm, "kreclaimd");
 	sigfillset(&tsk->blocked);
 	current->flags |= PF_MEMALLOC;
diff -u --recursive --new-file v2.4.4/linux/net/README linux/net/README
--- v2.4.4/linux/net/README	Thu Nov  9 15:57:53 2000
+++ linux/net/README	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
 -------------------+-------------------------------------------
 802 [other	]	alan@lxorguk.ukuu.org.uk	
     [token ring	]	p.norton@computer.org
-appletalk		jschlst@turbolinux.com
+appletalk		jschlst@samba.org
 ax25			g4klx@g4klx.demon.co.uk
 bridge			buytenh@gnu.org
 core			alan@lxorguk.ukuu.org.uk
@@ -13,7 +13,8 @@
 ethernet		alan@lxorguk.ukuu.org.uk
 ipv4			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
 ipv6			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
-ipx/spx			jschlst@turbolinux.com
+ipx			acme@conectiva.com.br
+spx			jschlst@samba.org
 irda                    dagb@cs.uit.no
 lapb			g4klx@g4klx.demon.co.uk
 netrom			g4klx@g4klx.demon.co.uk
diff -u --recursive --new-file v2.4.4/linux/net/atm/mpoa_proc.c linux/net/atm/mpoa_proc.c
--- v2.4.4/linux/net/atm/mpoa_proc.c	Fri Sep  1 09:07:01 2000
+++ linux/net/atm/mpoa_proc.c	Tue May 15 01:29:35 2001
@@ -175,7 +175,7 @@
 
         if (nbytes < 0) return -EINVAL;
         if (nbytes == 0) return 0;
-        if (nbytes > PAGE_SIZE) nbytes = PAGE_SIZE-1;
+        if (nbytes >= PAGE_SIZE) nbytes = PAGE_SIZE-1;
 
         error = verify_area(VERIFY_READ, buff, nbytes);
         if (error) return error;
diff -u --recursive --new-file v2.4.4/linux/net/core/dev.c linux/net/core/dev.c
--- v2.4.4/linux/net/core/dev.c	Thu Apr 19 08:38:50 2001
+++ linux/net/core/dev.c	Sat May 19 18:11:49 2001
@@ -400,7 +400,7 @@
 	struct net_device *dev;
 
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
-		if (strcmp(dev->name, name) == 0)
+		if (strncmp(dev->name, name, IFNAMSIZ) == 0)
 			return dev;
 	}
 	return NULL;
@@ -1070,7 +1070,7 @@
 {
 	void (*stimul)(struct net_device *);
 	struct net_device *dev;
-} netdev_fc_slots[32];
+} netdev_fc_slots[BITS_PER_LONG];
 
 int netdev_register_fc(struct net_device *dev, void (*stimul)(struct net_device *dev))
 {
diff -u --recursive --new-file v2.4.4/linux/net/core/filter.c linux/net/core/filter.c
--- v2.4.4/linux/net/core/filter.c	Thu Apr 12 12:11:39 2001
+++ linux/net/core/filter.c	Wed May 16 10:32:59 2001
@@ -2,7 +2,7 @@
  * Linux Socket Filter - Kernel level socket filtering
  *
  * Author:
- *     Jay Schulist <jschlst@turbolinux.com>
+ *     Jay Schulist <jschlst@samba.org>
  *
  * Based on the design of:
  *     - The Berkeley Packet Filter
@@ -382,6 +382,9 @@
 	struct sock_filter *ftest;
         int pc;
 
+	if ((unsigned int) flen >= (~0U / sizeof(struct sock_filter)))
+		return -EINVAL;
+
        /*
         * Check the filter code now.
         */
@@ -404,7 +407,7 @@
 				   jumps below, where offsets are limited. --ANK (981016)
 				 */
 				if (ftest->k >= (unsigned)(flen-pc-1))
-					return (-EINVAL);
+					return -EINVAL;
 			}
                         else
 			{
@@ -412,7 +415,7 @@
 				 *	For conditionals both must be safe
 				 */
  				if(pc + ftest->jt +1 >= flen || pc + ftest->jf +1 >= flen)
-					return (-EINVAL);
+					return -EINVAL;
 			}
                 }
 
diff -u --recursive --new-file v2.4.4/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.4.4/linux/net/decnet/af_decnet.c	Thu Apr 12 12:11:39 2001
+++ linux/net/decnet/af_decnet.c	Tue May  1 16:05:00 2001
@@ -1431,7 +1431,7 @@
 	struct	sock *sk = sock->sk;
 	struct dn_scp *scp = DN_SK(sk);
 	struct linkinfo_dn link;
-	int r_len;
+	unsigned int r_len;
 	void *r_data = NULL;
 	unsigned int val;
 
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.4.4/linux/net/ipv4/Config.in	Tue Aug 22 08:59:00 2000
+++ linux/net/ipv4/Config.in	Tue May  1 20:59:24 2001
@@ -20,6 +20,7 @@
 fi
 bool '  IP: kernel level autoconfiguration' CONFIG_IP_PNP
 if [ "$CONFIG_IP_PNP" = "y" ]; then
+   bool '    IP: DHCP support' CONFIG_IP_PNP_DHCP
    bool '    IP: BOOTP support' CONFIG_IP_PNP_BOOTP
    bool '    IP: RARP support' CONFIG_IP_PNP_RARP
 # not yet ready..
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.4.4/linux/net/ipv4/af_inet.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/af_inet.c	Tue May  1 20:59:24 2001
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.129 2001/03/02 03:13:05 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.130 2001/04/29 08:21:32 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -135,11 +135,11 @@
 #endif
 
 #ifdef CONFIG_DLCI_MODULE
-int (*dlci_ioctl_hook)(unsigned int, void *) = NULL;
+int (*dlci_ioctl_hook)(unsigned int, void *);
 #endif
 
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-int (*br_ioctl_hook)(unsigned long) = NULL;
+int (*br_ioctl_hook)(unsigned long);
 #endif
 
 /* New destruction routine */
@@ -361,19 +361,19 @@
 
 	sk->destruct = inet_sock_destruct;
 
-	sk->zapped = 0;
-	sk->family = PF_INET;
-	sk->protocol = protocol;
+	sk->zapped	= 0;
+	sk->family	= PF_INET;
+	sk->protocol	= protocol;
 
-	sk->prot = prot;
+	sk->prot	= prot;
 	sk->backlog_rcv = prot->backlog_rcv;
 
-	sk->protinfo.af_inet.ttl=sysctl_ip_default_ttl;
+	sk->protinfo.af_inet.ttl	= sysctl_ip_default_ttl;
 
-	sk->protinfo.af_inet.mc_loop=1;
-	sk->protinfo.af_inet.mc_ttl=1;
-	sk->protinfo.af_inet.mc_index=0;
-	sk->protinfo.af_inet.mc_list=NULL;
+	sk->protinfo.af_inet.mc_loop	= 1;
+	sk->protinfo.af_inet.mc_ttl	= 1;
+	sk->protinfo.af_inet.mc_index	= 0;
+	sk->protinfo.af_inet.mc_list	= NULL;
 
 #ifdef INET_REFCNT_DEBUG
 	atomic_inc(&inet_sock_nr);
@@ -815,8 +815,7 @@
 	int err;
 	int pid;
 
-	switch(cmd) 
-	{
+	switch(cmd) {
 		case FIOSETOWN:
 		case SIOCSPGRP:
 			err = get_user(pid, (int *) arg);
@@ -962,8 +961,8 @@
 };
 
 struct net_proto_family inet_family_ops = {
-	PF_INET,
-	inet_create
+	family:	PF_INET,
+	create:	inet_create
 };
 
 
@@ -982,8 +981,7 @@
 
 	printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n");
 
-	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb))
-	{
+	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
 		printk(KERN_CRIT "inet_proto_init: panic\n");
 		return -EINVAL;
 	}
@@ -999,8 +997,7 @@
 	 */
 
 	printk(KERN_INFO "IP Protocols: ");
-	for(p = inet_protocol_base; p != NULL;) 
-	{
+	for (p = inet_protocol_base; p != NULL;) {
 		struct inet_protocol *tmp = (struct inet_protocol *) p->next;
 		inet_add_protocol(p);
 		printk("%s%s",p->name,tmp?", ":"\n");
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.4.4/linux/net/ipv4/arp.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/arp.c	Wed May 16 10:21:45 2001
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.96 2001/02/02 08:42:59 davem Exp $
+ * Version:	$Id: arp.c,v 1.98 2001/05/16 16:45:35 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
@@ -123,69 +123,71 @@
 static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static void parp_redo(struct sk_buff *skb);
 
-static struct neigh_ops arp_generic_ops =
-{
-	AF_INET,
-	NULL,
-	arp_solicit,
-	arp_error_report,
-	neigh_resolve_output,
-	neigh_connected_output,
-	dev_queue_xmit,
-	dev_queue_xmit
+static struct neigh_ops arp_generic_ops = {
+	family:			AF_INET,
+	solicit:		arp_solicit,
+	error_report:		arp_error_report,
+	output:			neigh_resolve_output,
+	connected_output:	neigh_connected_output,
+	hh_output:		dev_queue_xmit,
+	queue_xmit:		dev_queue_xmit,
 };
 
-static struct neigh_ops arp_hh_ops =
-{
-	AF_INET,
-	NULL,
-	arp_solicit,
-	arp_error_report,
-	neigh_resolve_output,
-	neigh_resolve_output,
-	dev_queue_xmit,
-	dev_queue_xmit
+static struct neigh_ops arp_hh_ops = {
+	family:			AF_INET,
+	solicit:		arp_solicit,
+	error_report:		arp_error_report,
+	output:			neigh_resolve_output,
+	connected_output:	neigh_resolve_output,
+	hh_output:		dev_queue_xmit,
+	queue_xmit:		dev_queue_xmit,
 };
 
-static struct neigh_ops arp_direct_ops =
-{
-	AF_INET,
-	NULL,
-	NULL,
-	NULL,
-	dev_queue_xmit,
-	dev_queue_xmit,
-	dev_queue_xmit,
-	dev_queue_xmit
+static struct neigh_ops arp_direct_ops = {
+	family:			AF_INET,
+	output:			dev_queue_xmit,
+	connected_output:	dev_queue_xmit,
+	hh_output:		dev_queue_xmit,
+	queue_xmit:		dev_queue_xmit,
 };
 
-struct neigh_ops arp_broken_ops =
-{
-	AF_INET,
-	NULL,
-	arp_solicit,
-	arp_error_report,
-	neigh_compat_output,
-	neigh_compat_output,
-	dev_queue_xmit,
-	dev_queue_xmit,
+struct neigh_ops arp_broken_ops = {
+	family:			AF_INET,
+	solicit:		arp_solicit,
+	error_report:		arp_error_report,
+	output:			neigh_compat_output,
+	connected_output:	neigh_compat_output,
+	hh_output:		dev_queue_xmit,
+	queue_xmit:		dev_queue_xmit,
 };
 
-struct neigh_table arp_tbl =
-{
-	NULL,
-	AF_INET,
-	sizeof(struct neighbour) + 4,
-	4,
-	arp_hash,
-	arp_constructor,
-	NULL,
-	NULL,
-	parp_redo,
-	"arp_cache",
-        { NULL, NULL, &arp_tbl, 0, NULL, NULL,
-		  30*HZ, 1*HZ, 60*HZ, 30*HZ, 5*HZ, 3, 3, 0, 3, 1*HZ, (8*HZ)/10, 64, 1*HZ },
-	30*HZ, 128, 512, 1024,
+struct neigh_table arp_tbl = {
+	family:		AF_INET,
+	entry_size:	sizeof(struct neighbour) + 4,
+	key_len:	4,
+	hash:		arp_hash,
+	constructor:	arp_constructor,
+	proxy_redo:	parp_redo,
+	id:		"arp_cache",
+	parms: {
+		tbl:			&arp_tbl,
+		base_reachable_time:	30 * HZ,
+		retrans_time:		1 * HZ,
+		gc_staletime:		60 * HZ,
+		reachable_time:		30 * HZ,
+		delay_probe_time:	5 * HZ,
+		queue_len:		3,
+		ucast_probes:		3,
+		mcast_probes:		3,
+		anycast_delay:		1 * HZ,
+		proxy_delay:		(8 * HZ) / 10,
+		proxy_qlen:		64,
+		locktime:		1 * HZ,
+	},
+	gc_interval:	30 * HZ,
+	gc_thresh1:	128,
+	gc_thresh2:	512,
+	gc_thresh3:	1024,
 };
 
 int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir)
@@ -194,10 +196,10 @@
 	case ARPHRD_ETHER:
 	case ARPHRD_FDDI:
 	case ARPHRD_IEEE802:
-		ip_eth_mc_map(addr, haddr) ; 
-		return 0 ; 
+		ip_eth_mc_map(addr, haddr);
+		return 0; 
 	case ARPHRD_IEEE802_TR:
-		ip_tr_mc_map(addr, haddr) ; 
+		ip_tr_mc_map(addr, haddr);
 		return 0;
 	default:
 		if (dir) {
@@ -343,6 +345,22 @@
 		read_unlock_bh(&neigh->lock);
 }
 
+static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
+{
+	struct rtable *rt;
+	int flag = 0; 
+	/*unsigned long now; */
+
+	if (ip_route_output(&rt, sip, tip, 0, 0) < 0) 
+		return 1;
+	if (rt->u.dst.dev != dev) { 
+		NET_INC_STATS_BH(ArpFilter);
+		flag = 1;
+	} 
+	ip_rt_put(rt); 
+	return flag; 
+} 
+
 /* OBSOLETE FUNCTIONS */
 
 /*
@@ -739,7 +757,12 @@
 		if (addr_type == RTN_LOCAL) {
 			n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 			if (n) {
-				arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+				int dont_send = 0;
+				if (IN_DEV_ARPFILTER(in_dev))
+					dont_send |= arp_filter(sip,tip,dev); 
+				if (!dont_send)
+					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+
 				neigh_release(n);
 			}
 			goto out;
@@ -1162,13 +1185,10 @@
  *	Called once on startup.
  */
 
-static struct packet_type arp_packet_type =
-{
-	__constant_htons(ETH_P_ARP),
-	NULL,		/* All devices */
-	arp_rcv,
-	(void*)1,
-	NULL
+static struct packet_type arp_packet_type = {
+	type:	__constant_htons(ETH_P_ARP),
+	func:	arp_rcv,
+	data:	(void*) 1, /* understand shared skbs */
 };
 
 void __init arp_init (void)
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.4.4/linux/net/ipv4/devinet.c	Sun Mar 25 18:14:25 2001
+++ linux/net/ipv4/devinet.c	Wed May 16 10:21:45 2001
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.41 2001/02/18 09:26:26 davem Exp $
+ *	Version: $Id: devinet.c,v 1.42 2001/05/16 16:45:35 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -1016,7 +1016,7 @@
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[13];
+	ctl_table devinet_vars[14];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -1058,6 +1058,9 @@
          &proc_dointvec},
 	{NET_IPV4_CONF_TAG, "tag",
 	 &ipv4_devconf.tag, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
+	{NET_IPV4_CONF_ARPFILTER, "arp_filter",
+	 &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
 	 {0}},
 
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.4.4/linux/net/ipv4/fib_frontend.c	Wed Dec 22 19:55:38 1999
+++ linux/net/ipv4/fib_frontend.c	Wed May 16 10:31:23 2001
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: FIB frontend.
  *
- * Version:	$Id: fib_frontend.c,v 1.21 1999/12/15 22:39:07 davem Exp $
+ * Version:	$Id: fib_frontend.c,v 1.24 2001/05/13 18:14:46 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -587,13 +587,13 @@
 		rt_cache_flush(-1);
 		break;
 	case NETDEV_DOWN:
+		fib_del_ifaddr(ifa);
 		if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
 			/* Last address was deleted from this interface.
 			   Disable IP.
 			 */
 			fib_disable_ip(ifa->ifa_dev->dev, 1);
 		} else {
-			fib_del_ifaddr(ifa);
 			rt_cache_flush(-1);
 		}
 		break;
@@ -634,15 +634,11 @@
 }
 
 struct notifier_block fib_inetaddr_notifier = {
-	fib_inetaddr_event,
-	NULL,
-	0
+	notifier_call:	fib_inetaddr_event,
 };
 
 struct notifier_block fib_netdev_notifier = {
-	fib_netdev_event,
-	NULL,
-	0
+	notifier_call:	fib_netdev_event,
 };
 
 void __init ip_fib_init(void)
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
--- v2.4.4/linux/net/ipv4/fib_rules.c	Mon Apr 24 13:59:56 2000
+++ linux/net/ipv4/fib_rules.c	Tue May  1 20:59:24 2001
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: policy rules.
  *
- * Version:	$Id: fib_rules.c,v 1.15 2000/04/15 01:48:10 davem Exp $
+ * Version:	$Id: fib_rules.c,v 1.16 2001/04/30 04:39:14 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -76,9 +76,27 @@
 	int		r_dead;
 };
 
-static struct fib_rule default_rule = { NULL, ATOMIC_INIT(2), 0x7FFF, RT_TABLE_DEFAULT, RTN_UNICAST, };
-static struct fib_rule main_rule = { &default_rule, ATOMIC_INIT(2), 0x7FFE, RT_TABLE_MAIN, RTN_UNICAST, };
-static struct fib_rule local_rule = { &main_rule, ATOMIC_INIT(2), 0, RT_TABLE_LOCAL, RTN_UNICAST, };
+static struct fib_rule default_rule = {
+	r_clntref:	ATOMIC_INIT(2),
+	r_preference:	0x7FFF,
+	r_table:	RT_TABLE_DEFAULT,
+	r_action:	RTN_UNICAST,
+};
+
+static struct fib_rule main_rule = {
+	r_next:		&default_rule,
+	r_clntref:	ATOMIC_INIT(2),
+	r_preference:	0x7FFE,
+	r_table:	RT_TABLE_MAIN,
+	r_action:	RTN_UNICAST,
+};
+
+static struct fib_rule local_rule = {
+	r_next:		&main_rule,
+	r_clntref:	ATOMIC_INIT(2),
+	r_table:	RT_TABLE_LOCAL,
+	r_action:	RTN_UNICAST,
+};
 
 static struct fib_rule *fib_rules = &local_rule;
 static rwlock_t fib_rules_lock = RW_LOCK_UNLOCKED;
@@ -374,9 +392,7 @@
 
 
 struct notifier_block fib_rules_notifier = {
-	fib_rules_event,
-	NULL,
-	0
+	notifier_call:	fib_rules_event,
 };
 
 #ifdef CONFIG_RTNETLINK
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.4.4/linux/net/ipv4/icmp.c	Thu Apr 19 08:38:50 2001
+++ linux/net/ipv4/icmp.c	Wed May 16 10:31:26 2001
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.74 2001/04/16 23:58:51 davem Exp $
+ *	Version: $Id: icmp.c,v 1.76 2001/05/10 01:20:58 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -139,11 +139,11 @@
 };
 
 /* Control parameters for ECHO relies. */
-int sysctl_icmp_echo_ignore_all = 0;
-int sysctl_icmp_echo_ignore_broadcasts = 0;
+int sysctl_icmp_echo_ignore_all;
+int sysctl_icmp_echo_ignore_broadcasts;
 
 /* Control parameter - ignore bogus broadcast responses? */
-int sysctl_icmp_ignore_bogus_error_responses =0;
+int sysctl_icmp_ignore_bogus_error_responses;
 
 /*
  *	ICMP control array. This specifies what to do with each ICMP.
@@ -167,7 +167,7 @@
  */
 	
 struct inode icmp_inode;
-struct socket *icmp_socket=&icmp_inode.u.socket_i;
+struct socket *icmp_socket = &icmp_inode.u.socket_i;
 
 /* ICMPv4 socket is only a bit non-reenterable (unlike ICMPv6,
    which is strongly non-reenterable). A bit later it will be made
@@ -651,7 +651,7 @@
 	 */
 
 	ipprot = (struct inet_protocol *) inet_protos[hash];
-	while(ipprot != NULL) {
+	while (ipprot) {
 		struct inet_protocol *nextip;
 
 		nextip = (struct inet_protocol *) ipprot->next;
@@ -695,7 +695,7 @@
 	iph = (struct iphdr *) skb->data;
 	ip = iph->daddr;
 
-	switch(skb->h.icmph->code & 7) {
+	switch (skb->h.icmph->code & 7) {
 		case ICMP_REDIR_NET:
 		case ICMP_REDIR_NETTOS:
 			/*
@@ -753,7 +753,7 @@
 	 *	Too short.
 	 */
 	 
-	if(skb->len<4) {
+	if (skb->len < 4) {
 		ICMP_INC_STATS_BH(IcmpInErrors);
 		return;
 	}
@@ -945,7 +945,7 @@
 int sysctl_icmp_destunreach_time = 1*HZ;
 int sysctl_icmp_timeexceed_time = 1*HZ;
 int sysctl_icmp_paramprob_time = 1*HZ;
-int sysctl_icmp_echoreply_time = 0; /* don't limit it per default. */
+int sysctl_icmp_echoreply_time; /* don't limit it per default. */
 
 /*
  *	This table is the definition of how we handle ICMP.
@@ -1006,6 +1006,7 @@
 	icmp_socket->sk->allocation=GFP_ATOMIC;
 	icmp_socket->sk->sndbuf = SK_WMEM_MAX*2;
 	icmp_socket->sk->protinfo.af_inet.ttl = MAXTTL;
+	icmp_socket->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
 
 	/* Unhash it so that IP input processing does not even
 	 * see it, we do not wish this socket to see incoming
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
--- v2.4.4/linux/net/ipv4/ip_gre.c	Wed Apr 18 14:40:07 2001
+++ linux/net/ipv4/ip_gre.c	Tue May 15 01:29:35 2001
@@ -273,6 +273,7 @@
 	dev->init = ipgre_tunnel_init;
 	dev->features |= NETIF_F_DYNALLOC;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	nt->parms.name[IFNAMSIZ-1] = '\0';
 	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.4.4/linux/net/ipv4/ipconfig.c	Fri Feb  9 11:34:13 2001
+++ linux/net/ipv4/ipconfig.c	Tue May  1 20:59:24 2001
@@ -1,10 +1,10 @@
 /*
- *  $Id: ipconfig.c,v 1.35 2000/12/30 06:46:36 davem Exp $
+ *  $Id: ipconfig.c,v 1.37 2001/04/30 18:54:12 davem Exp $
  *
- *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
- *  information to configure own IP address and routes.
+ *  Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
+ *  user-supplied information to configure own IP address and routes.
  *
- *  Copyright (C) 1996--1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *  Copyright (C) 1996-1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  *  Derived from network configuration code in fs/nfs/nfsroot.c,
  *  originally Copyright (C) 1995, 1996 Gero Kuhlmann and me.
@@ -16,6 +16,16 @@
  *  Fixed ip_auto_config_setup calling at startup in the new "Linker Magic"
  *  initialization scheme.
  *	- Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 08/11/1999
+ *
+ *  DHCP support added.  To users this looks like a whole separate
+ *  protocol, but we know it's just a bag on the side of BOOTP.
+ *		-- Chip Salzenberg <chip@valinux.com>, May 2000
+ *
+ *  Ported DHCP support from 2.2.16 to 2.4.0-test4
+ *              -- Eric Biederman <ebiederman@lnxi.com>, 30 Aug 2000
+ *
+ *  Merged changes from 2.2.19 into 2.4.3
+ *              -- Eric Biederman <ebiederman@lnxi.com>, 22 April Aug 2001
  */
 
 #include <linux/config.h>
@@ -36,6 +46,7 @@
 #include <linux/socket.h>
 #include <linux/route.h>
 #include <linux/udp.h>
+#include <linux/proc_fs.h>
 #include <net/arp.h>
 #include <net/ip.h>
 #include <net/ipconfig.h>
@@ -52,48 +63,94 @@
 #define DBG(x) do { } while(0)
 #endif
 
-/* Define the timeout for waiting for a RARP/BOOTP reply */
-#define CONF_BASE_TIMEOUT	(HZ*5)	/* Initial timeout: 5 seconds */
-#define CONF_RETRIES	 	10	/* 10 retries */
+#if defined(CONFIG_IP_PNP_DHCP)
+#define IPCONFIG_DHCP
+#endif
+#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_DHCP)
+#define IPCONFIG_BOOTP
+#endif
+#if defined(CONFIG_IP_PNP_RARP)
+#define IPCONFIG_RARP
+#endif
+#if defined(IPCONFIG_BOOTP) || defined(IPCONFIG_RARP)
+#define IPCONFIG_DYNAMIC
+#endif
+
+/* Define the friendly delay before and after opening net devices */
+#define CONF_PRE_OPEN		(HZ/2)	/* Before opening: 1/2 second */
+#define CONF_POST_OPEN		(1*HZ)	/* After opening: 1 second */
+
+/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */
+#define CONF_OPEN_RETRIES 	2	/* (Re)open devices twice */
+#define CONF_SEND_RETRIES 	6	/* Send six requests per open */
+#define CONF_INTER_TIMEOUT	(HZ/2)	/* Inter-device timeout: 1/2 second */
+#define CONF_BASE_TIMEOUT	(HZ*2)	/* Initial timeout: 2 seconds */
 #define CONF_TIMEOUT_RANDOM	(HZ)	/* Maximum amount of randomization */
-#define CONF_TIMEOUT_MULT	*5/4	/* Rate of timeout growth */
+#define CONF_TIMEOUT_MULT	*7/4	/* Rate of timeout growth */
 #define CONF_TIMEOUT_MAX	(HZ*30)	/* Maximum allowed timeout */
 
-/* IP configuration */
-static char user_dev_name[IFNAMSIZ] __initdata = { 0, };/* Name of user-selected boot device */
-u32 ic_myaddr __initdata = INADDR_NONE;		/* My IP address */
-u32 ic_servaddr __initdata = INADDR_NONE;	/* Server IP address */
-u32 ic_gateway __initdata = INADDR_NONE;	/* Gateway IP address */
-u32 ic_netmask __initdata = INADDR_NONE;	/* Netmask for local subnet */
-int ic_enable __initdata = 1;			/* Automatic IP configuration enabled */
-int ic_host_name_set __initdata = 0;		/* Host name configured manually */
-int ic_set_manually __initdata = 0;		/* IPconfig parameters set manually */
 
-u32 root_server_addr __initdata = INADDR_NONE;		/* Address of boot server */
-u8 root_server_path[256] __initdata = { 0, };		/* Path to mount as root */
+/*
+ * Public IP configuration
+ */
 
-#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
+/* This is used by platforms which might be able to set the ipconfig
+ * variabled using firmware environment vars.  If this is set, it will
+ * ignore such firmware variables.
+ */
+int ic_set_manually __initdata = 0;		/* IPconfig parameters set manually */
 
-#define CONFIG_IP_PNP_DYNAMIC
+int ic_enable __initdata = 0;			/* IP config enabled? */
 
-int ic_proto_enabled __initdata = 0			/* Protocols enabled */
-#ifdef CONFIG_IP_PNP_BOOTP
+/* Protocol choice */
+int ic_proto_enabled __initdata = 0
+#ifdef IPCONFIG_BOOTP
 			| IC_BOOTP
 #endif
-#ifdef CONFIG_IP_PNP_RARP
+#ifdef CONFIG_IP_PNP_DHCP
+			| IC_USE_DHCP
+#endif
+#ifdef IPCONFIG_RARP
 			| IC_RARP
 #endif
 			;
-static int ic_got_reply __initdata = 0;				/* Protocol(s) we got reply from */
 
-#else
+int ic_host_name_set __initdata = 0;		/* Host name set by us? */
 
-static int ic_proto_enabled __initdata = 0;
+u32 ic_myaddr __initdata = INADDR_NONE;		/* My IP address */
+u32 ic_netmask __initdata = INADDR_NONE;	/* Netmask for local subnet */
+u32 ic_gateway __initdata = INADDR_NONE;	/* Gateway IP address */
 
-#endif
+u32 ic_servaddr __initdata = INADDR_NONE;	/* Boot server IP address */
 
+u32 root_server_addr __initdata = INADDR_NONE;	/* Address of NFS server */
+u8 root_server_path[256] __initdata = { 0, };	/* Path to mount as root */
+
+/* Persistent data: */
+
+int ic_proto_used;			/* Protocol used, if any */
+u32 ic_nameserver = INADDR_NONE;	/* DNS Server IP address */
+u8 ic_domain[64];		/* DNS (not NIS) domain name */
+
+/*
+ * Private state.
+ */
+
+/* Name of user-selected boot device */
+static char user_dev_name[IFNAMSIZ] __initdata = { 0, };
+
+/* Protocols supported by available interfaces */
 static int ic_proto_have_if __initdata = 0;
 
+#ifdef IPCONFIG_DYNAMIC
+static spinlock_t ic_recv_lock = SPIN_LOCK_UNLOCKED;
+static volatile int ic_got_reply __initdata = 0;    /* Proto(s) that replied */
+#endif
+#ifdef IPCONFIG_DHCP
+static int ic_dhcp_msgtype __initdata = 0;	/* DHCP msg type received */
+#endif
+
+
 /*
  *	Network devices
  */
@@ -102,11 +159,12 @@
 	struct ic_device *next;
 	struct net_device *dev;
 	unsigned short flags;
-	int able;
+	short able;
+	u32 xid;
 };
 
 static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
-static struct net_device *ic_dev __initdata = NULL;		/* Selected device */
+static struct net_device *ic_dev __initdata = NULL;	/* Selected device */
 
 static int __init ic_open_devs(void)
 {
@@ -125,7 +183,7 @@
 			if (dev->mtu >= 364)
 				able |= IC_BOOTP;
 			else
-				printk(KERN_WARNING "BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu);
+				printk(KERN_WARNING "DHCP/BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu);
 			if (!(dev->flags & IFF_NOARP))
 				able |= IC_RARP;
 			able &= ic_proto_enabled;
@@ -143,8 +201,13 @@
 			last = &d->next;
 			d->flags = oflags;
 			d->able = able;
+			if (able & IC_BOOTP)
+				get_random_bytes(&d->xid, sizeof(u32));
+			else
+				d->xid = 0;
 			ic_proto_have_if |= able;
-			DBG(("IP-Config: Opened %s (able=%d)\n", dev->name, able));
+			DBG(("IP-Config: %s UP (able=%d, xid=%08x)\n",
+				dev->name, able, d->xid));
 		}
 	}
 	rtnl_shunlock();
@@ -282,18 +345,18 @@
 	 */
 	 
 	if (!ic_host_name_set)
-		strcpy(system_utsname.nodename, in_ntoa(ic_myaddr));
+		sprintf(system_utsname.nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr));
 
 	if (root_server_addr == INADDR_NONE)
 		root_server_addr = ic_servaddr;
 
 	if (ic_netmask == INADDR_NONE) {
 		if (IN_CLASSA(ntohl(ic_myaddr)))
-			ic_netmask = htonl(IN_CLASSA_NET);
+			ic_netmask = __constant_htonl(IN_CLASSA_NET);
 		else if (IN_CLASSB(ntohl(ic_myaddr)))
-			ic_netmask = htonl(IN_CLASSB_NET);
+			ic_netmask = __constant_htonl(IN_CLASSB_NET);
 		else if (IN_CLASSC(ntohl(ic_myaddr)))
-			ic_netmask = htonl(IN_CLASSC_NET);
+			ic_netmask = __constant_htonl(IN_CLASSC_NET);
 		else {
 			printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n",
 				NIPQUAD(ic_myaddr));
@@ -309,16 +372,13 @@
  *	RARP support.
  */
 
-#ifdef CONFIG_IP_PNP_RARP
+#ifdef IPCONFIG_RARP
 
 static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
 
 static struct packet_type rarp_packet_type __initdata = {
-	__constant_htons(ETH_P_RARP),
-	NULL,			/* Listen to all devices */
-	ic_rarp_recv,
-	NULL,
-	NULL
+	type:	__constant_htons(ETH_P_RARP),
+	func:	ic_rarp_recv,
 };
 
 static inline void ic_rarp_init(void)
@@ -341,21 +401,32 @@
 	unsigned char *rarp_ptr = (unsigned char *) (rarp + 1);
 	unsigned long sip, tip;
 	unsigned char *sha, *tha;		/* s for "source", t for "target" */
+	struct ic_device *d;
+
+	/* One reply at a time, please. */
+	spin_lock(&ic_recv_lock);
 
 	/* If we already have a reply, just drop the packet */
 	if (ic_got_reply)
 		goto drop;
 
+	/* Find the ic_device that the packet arrived on */
+	d = ic_first_dev;
+	while (d && d->dev != dev)
+		d = d->next;
+	if (!d)
+		goto drop;	/* should never happen */
+
 	/* If this test doesn't pass, it's not IP, or we should ignore it anyway */
 	if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd))
 		goto drop;
 
 	/* If it's not a RARP reply, delete it. */
-	if (rarp->ar_op != htons(ARPOP_RREPLY))
+	if (rarp->ar_op != __constant_htons(ARPOP_RREPLY))
 		goto drop;
 
 	/* If it's not Ethernet, delete it. */
-	if (rarp->ar_pro != htons(ETH_P_IP))
+	if (rarp->ar_pro != __constant_htons(ETH_P_IP))
 		goto drop;
 
 	/* Extract variable-width fields */
@@ -375,44 +446,39 @@
 	if (ic_servaddr != INADDR_NONE && ic_servaddr != sip)
 		goto drop;
 
-	/* Victory! The packet is what we were looking for! */
-	if (!ic_got_reply) {
-		ic_got_reply = IC_RARP;
-		ic_dev = dev;
-		if (ic_myaddr == INADDR_NONE)
-			ic_myaddr = tip;
-		ic_servaddr = sip;
-	}
+	/* We have a winner! */
+	ic_dev = dev;
+	if (ic_myaddr == INADDR_NONE)
+		ic_myaddr = tip;
+	ic_servaddr = sip;
+	ic_got_reply = IC_RARP;
 
-	/* And throw the packet out... */
 drop:
+	/* Show's over.  Nothing to see here.  */
+	spin_unlock(&ic_recv_lock);
+
+	/* Throw the packet out. */
 	kfree_skb(skb);
 	return 0;
 }
 
 
 /*
- *  Send RARP request packet over all devices which allow RARP.
+ *  Send RARP request packet over a signle interface.
  */
-static void __init ic_rarp_send(void)
+static void __init ic_rarp_send_if(struct ic_device *d)
 {
-	struct ic_device *d;
-
-	for (d=ic_first_dev; d; d=d->next)
-		if (d->able & IC_RARP) {
-			struct net_device *dev = d->dev;
-			arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
-				 dev->dev_addr, dev->dev_addr);
-		}
+	struct net_device *dev = d->dev;
+	arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
+		 dev->dev_addr, dev->dev_addr);
 }
-
 #endif
 
 /*
- *	BOOTP support.
+ *	DHCP/BOOTP support.
  */
 
-#ifdef CONFIG_IP_PNP_BOOTP
+#ifdef IPCONFIG_BOOTP
 
 struct bootp_pkt {		/* BOOTP packet format */
 	struct iphdr iph;	/* IP header */
@@ -426,45 +492,110 @@
 	u16 flags;		/* Just what it says */
 	u32 client_ip;		/* Client's IP address if known */
 	u32 your_ip;		/* Assigned IP address */
-	u32 server_ip;		/* Server's IP address */
+	u32 server_ip;		/* (Next, e.g. NFS) Server's IP address */
 	u32 relay_ip;		/* IP address of BOOTP relay */
 	u8 hw_addr[16];		/* Client's HW address */
 	u8 serv_name[64];	/* Server host name */
 	u8 boot_file[128];	/* Name of boot file */
-	u8 vendor_area[128];	/* Area for extensions */
+	u8 exten[312];		/* DHCP options / BOOTP vendor extensions */
 };
 
-#define BOOTP_REQUEST 1
-#define BOOTP_REPLY 2
-
-static u32 ic_bootp_xid;
+/* packet ops */
+#define BOOTP_REQUEST	1
+#define BOOTP_REPLY	2
+
+/* DHCP message types */
+#define DHCPDISCOVER	1
+#define DHCPOFFER	2
+#define DHCPREQUEST	3
+#define DHCPDECLINE	4
+#define DHCPACK		5
+#define DHCPNAK		6
+#define DHCPRELEASE	7
+#define DHCPINFORM	8
 
 static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
 
 static struct packet_type bootp_packet_type __initdata = {
-	__constant_htons(ETH_P_IP),
-	NULL,			/* Listen to all devices */
-	ic_bootp_recv,
-	NULL,
-	NULL
+	type:	__constant_htons(ETH_P_IP),
+	func:	ic_bootp_recv,
 };
 
 
 /*
- *  Initialize BOOTP extension fields in the request.
+ *  Initialize DHCP/BOOTP extension fields in the request.
  */
+
+static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 };
+
+#ifdef IPCONFIG_DHCP
+
+static void __init
+ic_dhcp_init_options(u8 *options)
+{
+	u8 mt = ((ic_servaddr == INADDR_NONE)
+		 ? DHCPDISCOVER : DHCPREQUEST);
+	u8 *e = options;
+
+#ifdef IPCONFIG_DEBUG
+	printk("DHCP: Sending message type %d\n", mt);
+#endif
+
+	memcpy(e, ic_bootp_cookie, 4);	/* RFC1048 Magic Cookie */
+	e += 4;
+
+	*e++ = 53;		/* DHCP message type */
+	*e++ = 1;
+	*e++ = mt;
+
+	if (mt == DHCPREQUEST) {
+		*e++ = 54;	/* Server ID (IP address) */
+		*e++ = 4;
+		memcpy(e, &ic_servaddr, 4);
+		e += 4;
+
+		*e++ = 50;	/* Requested IP address */
+		*e++ = 4;
+		memcpy(e, &ic_myaddr, 4);
+		e += 4;
+	}
+
+	/* always? */
+	{
+		static const u8 ic_req_params[] = {
+			1,	/* Subnet mask */
+			3,	/* Default gateway */
+			6,	/* DNS server */
+			12,	/* Host name */
+			15,	/* Domain name */
+			17,	/* Boot path */
+			40,	/* NIS domain name */
+		};
+
+		*e++ = 55;	/* Parameter request list */
+		*e++ = sizeof(ic_req_params);
+		memcpy(e, ic_req_params, sizeof(ic_req_params));
+		e += sizeof(ic_req_params);
+	}
+
+	*e++ = 255;	/* End of the list */
+}
+
+#endif /* IPCONFIG_DHCP */
+
 static void __init ic_bootp_init_ext(u8 *e)
 {
-	*e++ = 99;		/* RFC1048 Magic Cookie */
-	*e++ = 130;
-	*e++ = 83;
-	*e++ = 99;
+	memcpy(e, ic_bootp_cookie, 4);	/* RFC1048 Magic Cookie */
+	e += 4;
 	*e++ = 1;		/* Subnet mask request */
 	*e++ = 4;
 	e += 4;
 	*e++ = 3;		/* Default gateway request */
 	*e++ = 4;
 	e += 4;
+	*e++ = 5;		/* Name server reqeust */
+	*e++ = 8;
+	e += 8;
 	*e++ = 12;		/* Host name request */
 	*e++ = 32;
 	e += 32;
@@ -472,25 +603,23 @@
 	*e++ = 32;
 	e += 32;
 	*e++ = 17;		/* Boot path */
-	*e++ = 32;
-	e += 32;
-	*e = 255;		/* End of the list */
+	*e++ = 40;
+	e += 40;
+	*e++ = 255;		/* End of the list */
 }
 
 
 /*
- *  Initialize the BOOTP mechanism.
+ *  Initialize the DHCP/BOOTP mechanism.
  */
 static inline void ic_bootp_init(void)
 {
-	get_random_bytes(&ic_bootp_xid, sizeof(u32));
-	DBG(("BOOTP: XID=%08x\n", ic_bootp_xid));
 	dev_add_pack(&bootp_packet_type);
 }
 
 
 /*
- *  BOOTP cleanup.
+ *  DHCP/BOOTP cleanup.
  */
 static inline void ic_bootp_cleanup(void)
 {
@@ -499,7 +628,7 @@
 
 
 /*
- *  Send BOOTP request to single interface.
+ *  Send DHCP/BOOTP request to single interface.
  */
 static void __init ic_bootp_send_if(struct ic_device *d, u32 jiffies)
 {
@@ -522,19 +651,19 @@
 	h->version = 4;
 	h->ihl = 5;
 	h->tot_len = htons(sizeof(struct bootp_pkt));
-	h->frag_off = htons(IP_DF);
+	h->frag_off = __constant_htons(IP_DF);
 	h->ttl = 64;
 	h->protocol = IPPROTO_UDP;
 	h->daddr = INADDR_BROADCAST;
 	h->check = ip_fast_csum((unsigned char *) h, h->ihl);
 
 	/* Construct UDP header */
-	b->udph.source = htons(68);
-	b->udph.dest = htons(67);
+	b->udph.source = __constant_htons(68);
+	b->udph.dest = __constant_htons(67);
 	b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr));
 	/* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */
 
-	/* Construct BOOTP header */
+	/* Construct DHCP/BOOTP header */
 	b->op = BOOTP_REQUEST;
 	if (dev->type < 256) /* check for false types */
 		b->htype = dev->type;
@@ -545,10 +674,19 @@
 		b->htype = dev->type; /* can cause undefined behavior */
 	}
 	b->hlen = dev->addr_len;
+	b->your_ip = INADDR_NONE;
+	b->server_ip = INADDR_NONE;
 	memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
 	b->secs = htons(jiffies / HZ);
-	b->xid = ic_bootp_xid;
-	ic_bootp_init_ext(b->vendor_area);
+	b->xid = d->xid;
+
+	/* add DHCP options or BOOTP extensions */
+#ifdef IPCONFIG_DHCP
+	if (ic_proto_enabled & IC_USE_DHCP)
+		ic_dhcp_init_options(b->exten);
+	else
+#endif
+		ic_bootp_init_ext(b->exten);
 
 	/* Chain packet down the line... */
 	skb->dev = dev;
@@ -561,19 +699,6 @@
 
 
 /*
- *  Send BOOTP requests to all interfaces.
- */
-static void __init ic_bootp_send(u32 jiffies)
-{
-	struct ic_device *d;
-
-	for(d=ic_first_dev; d; d=d->next)
-		if (d->able & IC_BOOTP)
-			ic_bootp_send_if(d, jiffies);
-}
-
-
-/*
  *  Copy BOOTP-supplied string if not already set.
  */
 static int __init ic_bootp_string(char *dest, char *src, int len, int max)
@@ -582,21 +707,21 @@
 		return 0;
 	if (len > max-1)
 		len = max-1;
-	strncpy(dest, src, len);
+	memcpy(dest, src, len);
 	dest[len] = '\0';
 	return 1;
 }
 
 
 /*
- *  Process BOOTP extension.
+ *  Process BOOTP extensions.
  */
 static void __init ic_do_bootp_ext(u8 *ext)
 {
 #ifdef IPCONFIG_DEBUG
 	u8 *c;
 
-	printk("BOOTP: Got extension %02x",*ext);
+	printk("DHCP/BOOTP: Got extension %d:",*ext);
 	for(c=ext+2; c<ext+2+ext[1]; c++)
 		printk(" %02x", *c);
 	printk("\n");
@@ -611,17 +736,24 @@
 			if (ic_gateway == INADDR_NONE)
 				memcpy(&ic_gateway, ext+1, 4);
 			break;
+		case 6:		/* DNS server */
+			if (ic_nameserver == INADDR_NONE)
+				memcpy(&ic_nameserver, ext+1, 4);
+			break;
 		case 12:	/* Host name */
 			ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN);
 			ic_host_name_set = 1;
 			break;
-		case 40:	/* NIS Domain name */
-			ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN);
+		case 15:	/* Domain name (DNS) */
+			ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain));
 			break;
 		case 17:	/* Root path */
 			if (!root_server_path[0])
 				ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
 			break;
+		case 40:	/* NIS Domain name (_not_ DNS) */
+			ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN);
+			break;
 	}
 }
 
@@ -633,12 +765,23 @@
 {
 	struct bootp_pkt *b = (struct bootp_pkt *) skb->nh.iph;
 	struct iphdr *h = &b->iph;
+	struct ic_device *d;
 	int len;
 
+	/* One reply at a time, please. */
+	spin_lock(&ic_recv_lock);
+
 	/* If we already have a reply, just drop the packet */
 	if (ic_got_reply)
 		goto drop;
 
+	/* Find the ic_device that the packet arrived on */
+	d = ic_first_dev;
+	while (d && d->dev != dev)
+		d = d->next;
+	if (!d)
+		goto drop;  /* should never happen */
+
 	/* Check whether it's a BOOTP packet */
 	if (skb->pkt_type == PACKET_OTHERHOST ||
 	    skb->len < sizeof(struct udphdr) + sizeof(struct iphdr) ||
@@ -647,14 +790,14 @@
 	    ip_fast_csum((char *) h, h->ihl) != 0 ||
 	    skb->len < ntohs(h->tot_len) ||
 	    h->protocol != IPPROTO_UDP ||
-	    b->udph.source != htons(67) ||
-	    b->udph.dest != htons(68) ||
+	    b->udph.source != __constant_htons(67) ||
+	    b->udph.dest != __constant_htons(68) ||
 	    ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr))
 		goto drop;
 
 	/* Fragments are not supported */
-	if (h->frag_off & htons(IP_OFFSET|IP_MF)) {
-		printk(KERN_ERR "BOOTP: Ignoring fragmented reply.\n");
+	if (h->frag_off & __constant_htons(IP_OFFSET | IP_MF)) {
+		printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented reply.\n");
 		goto drop;
 	}
 
@@ -662,41 +805,103 @@
 	len = ntohs(b->udph.len) - sizeof(struct udphdr);
 	if (len < 300 ||				    /* See RFC 951:2.1 */
 	    b->op != BOOTP_REPLY ||
-	    b->xid != ic_bootp_xid) {
+	    b->xid != d->xid) {
 		printk("?");
 		goto drop;
 	}
 
-	/* Extract basic fields */
-	ic_myaddr = b->your_ip;
-	ic_servaddr = b->server_ip;
-	ic_got_reply = IC_BOOTP;
-	ic_dev = dev;
-
 	/* Parse extensions */
-	if (b->vendor_area[0] == 99 &&	/* Check magic cookie */
-	    b->vendor_area[1] == 130 &&
-	    b->vendor_area[2] == 83 &&
-	    b->vendor_area[3] == 99) {
-		u8 *ext = &b->vendor_area[4];
+	if (!memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */
                 u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
+		u8 *ext;
+
+#ifdef IPCONFIG_DHCP
+
+		u32 server_id = INADDR_NONE;
+		int mt = 0;
+
+		ext = &b->exten[4];
 		while (ext < end && *ext != 0xff) {
-			if (*ext == 0)		/* Padding */
-				ext++;
-			else {
-				u8 *opt = ext;
-				ext += ext[1] + 2;
-				if (ext <= end)
-					ic_do_bootp_ext(opt);
+			u8 *opt = ext++;
+			if (*opt == 0)	/* Padding */
+				continue;
+			ext += *ext + 1;
+			if (ext >= end)
+				break;
+			switch (*opt) {
+			case 53:	/* Message type */
+				if (opt[1])
+					mt = opt[2];
+				break;
+			case 54:	/* Server ID (IP address) */
+				if (opt[1] >= 4)
+					memcpy(&server_id, opt + 2, 4);
+				break;
 			}
 		}
+
+#ifdef IPCONFIG_DEBUG
+		printk("DHCP: Got message type %d\n", mt);
+#endif
+
+		switch (mt) {
+		    case DHCPOFFER:
+			/* While in the process of accepting one offer,
+			   ignore all others. */
+			if (ic_myaddr != INADDR_NONE)
+				goto drop;
+			/* Let's accept that offer. */
+			ic_myaddr = b->your_ip;
+			ic_servaddr = server_id;
+#ifdef IPCONFIG_DEBUG
+			printk("DHCP: Offered address %u.%u.%u.%u", NIPQUAD(ic_myaddr));
+			printk(" by server %u.%u.%u.%u\n", NIPQUAD(ic_servaddr));
+#endif
+			break;
+
+		    case DHCPACK:
+			/* Yeah! */
+			break;
+
+		    default:
+			/* Urque.  Forget it*/
+			ic_myaddr = INADDR_NONE;
+			ic_servaddr = INADDR_NONE;
+			goto drop;
+		}
+
+		ic_dhcp_msgtype = mt;
+
+#endif /* IPCONFIG_DHCP */
+
+		ext = &b->exten[4];
+		while (ext < end && *ext != 0xff) {
+			u8 *opt = ext++;
+			if (*opt == 0)	/* Padding */
+				continue;
+			ext += *ext + 1;
+			if (ext < end)
+				ic_do_bootp_ext(opt);
+		}
 	}
 
+	/* We have a winner! */
+	ic_dev = dev;
+	ic_myaddr = b->your_ip;
+	ic_servaddr = b->server_ip;
 	if (ic_gateway == INADDR_NONE && b->relay_ip)
 		ic_gateway = b->relay_ip;
+	if (ic_nameserver == INADDR_NONE)
+		ic_nameserver = ic_servaddr;
+	ic_got_reply = IC_BOOTP;
 
 drop:
+	/* Show's over.  Nothing to see here.  */
+	spin_unlock(&ic_recv_lock);
+
+	/* Throw the packet out. */
 	kfree_skb(skb);
+
 	return 0;
 }	
 
@@ -705,36 +910,34 @@
 
 
 /*
- *	Dynamic IP configuration -- BOOTP and RARP.
+ *	Dynamic IP configuration -- DHCP, BOOTP, RARP.
  */
 
-#ifdef CONFIG_IP_PNP_DYNAMIC
+#ifdef IPCONFIG_DYNAMIC
 
 static int __init ic_dynamic(void)
 {
 	int retries;
-	unsigned long timeout, jiff;
-	unsigned long start_jiffies;
-	int do_rarp = ic_proto_have_if & IC_RARP;
+	struct ic_device *d;
+	unsigned long start_jiffies, timeout, jiff;
 	int do_bootp = ic_proto_have_if & IC_BOOTP;
+	int do_rarp = ic_proto_have_if & IC_RARP;
 
 	/*
-	 * If neither BOOTP nor RARP was selected, return with an error. This
-	 * routine gets only called when some pieces of information are mis-
-	 * sing, and without BOOTP and RARP we are not able to get that in-
-	 * formation.
+	 * If none of DHCP/BOOTP/RARP was selected, return with an error.
+	 * This routine gets only called when some pieces of information
+	 * are missing, and without DHCP/BOOTP/RARP we are unable to get it.
 	 */
 	if (!ic_proto_enabled) {
 		printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n");
 		return -1;
 	}
 
-#ifdef CONFIG_IP_PNP_BOOTP
+#ifdef IPCONFIG_BOOTP
 	if ((ic_proto_enabled ^ ic_proto_have_if) & IC_BOOTP)
-		printk(KERN_ERR "BOOTP: No suitable device found.\n");
+		printk(KERN_ERR "DHCP/BOOTP: No suitable device found.\n");
 #endif
-
-#ifdef CONFIG_IP_PNP_RARP
+#ifdef IPCONFIG_RARP
 	if ((ic_proto_enabled ^ ic_proto_have_if) & IC_RARP)
 		printk(KERN_ERR "RARP: No suitable device found.\n");
 #endif
@@ -744,16 +947,16 @@
 		return -1;
 
 	/*
-	 * Setup RARP and BOOTP protocols
+	 * Setup protocols
 	 */
-#ifdef CONFIG_IP_PNP_RARP
-	if (do_rarp)
-		ic_rarp_init();
-#endif
-#ifdef CONFIG_IP_PNP_BOOTP
+#ifdef IPCONFIG_BOOTP
 	if (do_bootp)
 		ic_bootp_init();
 #endif
+#ifdef IPCONFIG_RARP
+	if (do_rarp)
+		ic_rarp_init();
+#endif
 
 	/*
 	 * Send requests and wait, until we get an answer. This loop
@@ -763,61 +966,119 @@
 	 * [Actually we could now, but the nothing else running note still 
 	 *  applies.. - AC]
 	 */
-	printk(KERN_NOTICE "Sending %s%s%s requests...",
-	        do_bootp ? "BOOTP" : "",
-		do_bootp && do_rarp ? " and " : "",
-		do_rarp ? "RARP" : "");
+	printk(KERN_NOTICE "Sending %s%s%s requests .",
+	       do_bootp
+		? ((ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP") : "",
+	       (do_bootp && do_rarp) ? " and " : "",
+	       do_rarp ? "RARP" : "");
+
 	start_jiffies = jiffies;
-	retries = CONF_RETRIES;
+	d = ic_first_dev;
+	retries = CONF_SEND_RETRIES;
 	get_random_bytes(&timeout, sizeof(timeout));
 	timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM);
 	for(;;) {
-#ifdef CONFIG_IP_PNP_BOOTP
-		if (do_bootp)
-			ic_bootp_send(jiffies - start_jiffies);
+#ifdef IPCONFIG_BOOTP
+		if (do_bootp && (d->able & IC_BOOTP))
+			ic_bootp_send_if(d, jiffies - start_jiffies);
 #endif
-#ifdef CONFIG_IP_PNP_RARP
-		if (do_rarp)
-			ic_rarp_send();
+#ifdef IPCONFIG_RARP
+		if (do_rarp && (d->able & IC_RARP))
+			ic_rarp_send_if(d);
 #endif
-		printk(".");
-		jiff = jiffies + timeout;
+
+		jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
 		while (jiffies < jiff && !ic_got_reply)
 			barrier();
+#ifdef IPCONFIG_DHCP
+		/* DHCP isn't done until we get a DHCPACK. */
+		if ((ic_got_reply & IC_BOOTP)
+		    && (ic_proto_enabled & IC_USE_DHCP)
+		    && ic_dhcp_msgtype != DHCPACK)
+		{
+			ic_got_reply = 0;
+			printk(",");
+			continue;
+		}
+#endif /* IPCONFIG_DHCP */
+
 		if (ic_got_reply) {
 			printk(" OK\n");
 			break;
 		}
+
+		if ((d = d->next))
+			continue;
+
 		if (! --retries) {
 			printk(" timed out!\n");
 			break;
 		}
+
+		d = ic_first_dev;
+
 		timeout = timeout CONF_TIMEOUT_MULT;
 		if (timeout > CONF_TIMEOUT_MAX)
 			timeout = CONF_TIMEOUT_MAX;
+
+		printk(".");
 	}
 
-#ifdef CONFIG_IP_PNP_RARP
-	if (do_rarp)
-		ic_rarp_cleanup();
-#endif
-#ifdef CONFIG_IP_PNP_BOOTP
+#ifdef IPCONFIG_BOOTP
 	if (do_bootp)
 		ic_bootp_cleanup();
 #endif
+#ifdef IPCONFIG_RARP
+	if (do_rarp)
+		ic_rarp_cleanup();
+#endif
 
 	if (!ic_got_reply)
 		return -1;
 
 	printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
-		(ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP",
+		((ic_got_reply & IC_RARP) ? "RARP" 
+		 : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
 		NIPQUAD(ic_servaddr));
 	printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
 
 	return 0;
 }
 
-#endif
+#endif /* IPCONFIG_DYNAMIC */
+
+#ifdef CONFIG_PROC_FS
+
+static int pnp_get_info(char *buffer, char **start,
+			off_t offset, int length)
+{
+	int len;
+
+	if (ic_proto_used & IC_PROTO)
+	    sprintf(buffer, "#PROTO: %s\n",
+		    (ic_proto_used & IC_RARP) ? "RARP"
+		    : (ic_proto_used & IC_USE_DHCP) ? "DHCP" : "BOOTP");
+	else
+	    strcpy(buffer, "#MANUAL\n");
+	len = strlen(buffer);
+
+	if (ic_domain[0])
+		len += sprintf(buffer + len,
+			       "domain %s\n", ic_domain);
+	if (ic_nameserver != INADDR_NONE)
+		len += sprintf(buffer + len,
+			       "nameserver %u.%u.%u.%u\n", NIPQUAD(ic_nameserver));
+
+	if (offset > len)
+		offset = len;
+	*start = buffer + offset;
+
+	if (offset + length > len)
+		length = len - offset;
+	return length;
+}
+
+#endif /* CONFIG_PROC_FS */
 
 /*
  *	IP Autoconfig dispatcher.
@@ -825,15 +1086,33 @@
 
 static int __init ip_auto_config(void)
 {
+	int retries = CONF_OPEN_RETRIES;
+	unsigned long jiff;
+
+#ifdef CONFIG_PROC_FS
+	proc_net_create("pnp", 0, pnp_get_info);
+#endif /* CONFIG_PROC_FS */
+
 	if (!ic_enable)
 		return 0;
 
 	DBG(("IP-Config: Entered.\n"));
 
+ try_try_again:
+	/* Give hardware a chance to settle */
+	jiff = jiffies + CONF_PRE_OPEN;
+	while (jiffies < jiff)
+		;
+
 	/* Setup all network devices */
 	if (ic_open_devs() < 0)
 		return -1;
 
+	/* Give drivers a chance to settle */
+	jiff = jiffies + CONF_POST_OPEN;
+	while (jiffies < jiff)
+			;
+
 	/*
 	 * If the config information is insufficient (e.g., our IP address or
 	 * IP address of the boot server is missing or we have multiple network
@@ -845,19 +1124,51 @@
 	    (root_server_addr == INADDR_NONE && ic_servaddr == INADDR_NONE) ||
 #endif
 	    ic_first_dev->next) {
-#ifdef CONFIG_IP_PNP_DYNAMIC
+#ifdef IPCONFIG_DYNAMIC
+
 		if (ic_dynamic() < 0) {
-			printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n");
 			ic_close_devs();
+
+			/*
+			 * I don't know why, but sometimes the
+			 * eepro100 driver (at least) gets upset and
+			 * doesn't work the first time it's opened.
+			 * But then if you close it and reopen it, it
+			 * works just fine.  So we need to try that at
+			 * least once before giving up.
+			 *
+			 * Also, if the root will be NFS-mounted, we
+			 * have nowhere to go if DHCP fails.  So we
+			 * just have to keep trying forever.
+			 *
+			 * 				-- Chip
+			 */
+#ifdef CONFIG_ROOT_NFS
+			if (ROOT_DEV == MKDEV(UNNAMED_MAJOR, 255)) {
+				printk(KERN_ERR 
+					"IP-Config: Retrying forever (NFS root)...\n");
+				goto try_try_again;
+			}
+#endif
+
+			if (--retries) {
+				printk(KERN_ERR 
+				       "IP-Config: Reopening network devices...\n");
+				goto try_try_again;
+			}
+
+			/* Oh, well.  At least we tried. */
+			printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n");
 			return -1;
 		}
-#else
+#else /* !DYNAMIC */
 		printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n");
 		ic_close_devs();
 		return -1;
-#endif
+#endif /* IPCONFIG_DYNAMIC */
 	} else {
-		ic_dev = ic_first_dev->dev;	/* Device selected manually or only one device -> use it */
+		/* Device selected manually or only one device -> use it */
+		ic_dev = ic_first_dev->dev;
 	}
 
 	/*
@@ -874,10 +1185,30 @@
 	if (ic_setup_if() < 0 || ic_setup_routes() < 0)
 		return -1;
 
-	DBG(("IP-Config: device=%s, local=%08x, server=%08x, boot=%08x, gw=%08x, mask=%08x\n",
-	    ic_dev->name, ic_myaddr, ic_servaddr, root_server_addr, ic_gateway, ic_netmask));
-	DBG(("IP-Config: host=%s, domain=%s, path=`%s'\n", system_utsname.nodename,
-	    system_utsname.domainname, root_server_path));
+	/*
+	 * Record which protocol was actually used.
+	 */
+#ifdef IPCONFIG_DYNAMIC
+	ic_proto_used = ic_got_reply | (ic_proto_enabled & IC_USE_DHCP);
+#endif
+
+#ifndef IPCONFIG_SILENT
+	/*
+	 * Clue in the operator.
+	 */
+	printk("IP-Config: Complete:");
+	printk("\n      device=%s", ic_dev->name);
+	printk(", addr=%u.%u.%u.%u", NIPQUAD(ic_myaddr));
+	printk(", mask=%u.%u.%u.%u", NIPQUAD(ic_netmask));
+	printk(", gw=%u.%u.%u.%u", NIPQUAD(ic_gateway));
+	printk(",\n     host=%s, domain=%s, nis-domain=%s",
+	       system_utsname.nodename, ic_domain, system_utsname.domainname);
+	printk(",\n     bootserver=%u.%u.%u.%u", NIPQUAD(ic_servaddr));
+	printk(", rootserver=%u.%u.%u.%u", NIPQUAD(root_server_addr));
+	printk(", rootpath=%s", root_server_path);
+	printk("\n");
+#endif /* !SILENT */
+
 	return 0;
 }
 
@@ -889,7 +1220,7 @@
  *  command line parameter. It consists of option fields separated by colons in
  *  the following order:
  *
- *  <client-ip>:<server-ip>:<gw-ip>:<netmask>:<host name>:<device>:<bootp|rarp>
+ *  <client-ip>:<server-ip>:<gw-ip>:<netmask>:<host name>:<device>:<PROTO>
  *
  *  Any of the fields can be empty which means to use a default value:
  *	<client-ip>	- address given by BOOTP or RARP
@@ -900,28 +1231,38 @@
  *	<host name>	- <client-ip> in ASCII notation, or the name returned
  *			  by BOOTP
  *	<device>	- use all available devices
- *	<bootp|rarp|both|off> - use both protocols to determine my own address
+ *	<PROTO>:
+ *	   off|none	    - don't do autoconfig at all (DEFAULT)
+ *	   on|any           - use any configured protocol
+ *	   dhcp|bootp|rarp  - use only the specified protocol
+ *	   both             - use both BOOTP and RARP (not DHCP)
  */
 static int __init ic_proto_name(char *name)
 {
-	if (!strcmp(name, "off")) {
-		ic_proto_enabled = 0;
+	if (!strcmp(name, "on") || !strcmp(name, "any")) {
+		return 1;
+	}
+#ifdef CONFIG_IP_PNP_DHCP
+	else if (!strcmp(name, "dhcp")) {
+		ic_proto_enabled &= ~IC_RARP;
 		return 1;
 	}
+#endif
 #ifdef CONFIG_IP_PNP_BOOTP
 	else if (!strcmp(name, "bootp")) {
-		ic_proto_enabled &= ~IC_RARP;
+		ic_proto_enabled &= ~(IC_RARP | IC_USE_DHCP);
 		return 1;
 	}
 #endif
 #ifdef CONFIG_IP_PNP_RARP
 	else if (!strcmp(name, "rarp")) {
-		ic_proto_enabled &= ~IC_BOOTP;
+		ic_proto_enabled &= ~(IC_BOOTP | IC_USE_DHCP);
 		return 1;
 	}
 #endif
-#ifdef CONFIG_IP_PNP_DYNAMIC
+#ifdef IPCONFIG_DYNAMIC
 	else if (!strcmp(name, "both")) {
+		ic_proto_enabled &= ~IC_USE_DHCP; /* backward compat :-( */
 		return 1;
 	}
 #endif
@@ -934,10 +1275,13 @@
 	int num = 0;
 
 	ic_set_manually = 1;
-	if (!strcmp(addrs, "off")) {
-		ic_enable = 0;
+
+	ic_enable = (*addrs && 
+		(strcmp(addrs, "off") != 0) && 
+		(strcmp(addrs, "none") != 0));
+	if (!ic_enable)
 		return 1;
-	}
+
 	if (ic_proto_name(addrs))
 		return 1;
 
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v2.4.4/linux/net/ipv4/ipip.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv4/ipip.c	Thu May 24 15:00:59 2001
@@ -1,7 +1,7 @@
 /*
  *	Linux NET3:	IP/IP protocol decoder. 
  *
- *	Version: $Id: ipip.c,v 1.45 2001/04/19 22:32:55 davem Exp $
+ *	Version: $Id: ipip.c,v 1.46 2001/05/17 04:12:18 davem Exp $
  *
  *	Authors:
  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
@@ -244,6 +244,7 @@
 	dev->init = ipip_tunnel_init;
 	dev->features |= NETIF_F_DYNALLOC;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	nt->parms.name[IFNAMSIZ-1] = '\0';
 	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c
--- v2.4.4/linux/net/ipv4/netfilter/ip_nat_core.c	Fri Apr 27 14:15:01 2001
+++ linux/net/ipv4/netfilter/ip_nat_core.c	Wed May 16 10:31:27 2001
@@ -890,13 +890,14 @@
 }
 
 /* Clear NAT section of all conntracks, in case we're loaded again. */
-static int __exit clean_nat(const struct ip_conntrack *i, void *data)
+static int clean_nat(const struct ip_conntrack *i, void *data)
 {
 	memset((void *)&i->nat, 0, sizeof(i->nat));
 	return 0;
 }
 
-void __exit ip_nat_cleanup(void)
+/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */
+void ip_nat_cleanup(void)
 {
 	ip_ct_selective_cleanup(&clean_nat, NULL);
 	ip_conntrack_destroyed = NULL;
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/netfilter/ip_tables.c linux/net/ipv4/netfilter/ip_tables.c
--- v2.4.4/linux/net/ipv4/netfilter/ip_tables.c	Mon Dec  4 18:43:02 2000
+++ linux/net/ipv4/netfilter/ip_tables.c	Tue May 15 01:29:35 2001
@@ -1243,6 +1243,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		name[IPT_TABLE_MAXNAMELEN-1] = '\0';
 		t = find_table_lock(name, &ret, &ipt_mutex);
 		if (t) {
 			struct ipt_getinfo info;
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v2.4.4/linux/net/ipv4/proc.c	Thu Aug 10 13:01:26 2000
+++ linux/net/ipv4/proc.c	Wed May 16 10:21:45 2001
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.44 2000/08/09 11:59:04 davem Exp $
+ * Version:	$Id: proc.c,v 1.45 2001/05/16 16:45:35 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -170,7 +170,7 @@
 	len = sprintf(buffer,
 		      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
 		      " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
-		      " OutOfWindowIcmps LockDroppedIcmps"
+		      " OutOfWindowIcmps LockDroppedIcmps ArpFilter"
 		      " TW TWRecycled TWKilled"
 		      " PAWSPassive PAWSActive PAWSEstab"
 		      " DelayedACKs DelayedACKLocked DelayedACKLost"
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/protocol.c linux/net/ipv4/protocol.c
--- v2.4.4/linux/net/ipv4/protocol.c	Tue Oct 10 10:33:52 2000
+++ linux/net/ipv4/protocol.c	Sat May 19 17:56:43 2001
@@ -5,7 +5,7 @@
  *
  *		INET protocol dispatch tables.
  *
- * Version:	$Id: protocol.c,v 1.12 2000/10/03 07:29:00 anton Exp $
+ * Version:	$Id: protocol.c,v 1.14 2001/05/18 02:25:49 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -16,6 +16,8 @@
  *		Alan Cox	: Added new fields for init and ready for
  *				  proper fragmentation (_NO_ 4K limits!)
  *		Richard Colella	: Hang on hash collision
+ *		Vince Laviano	: Modified inet_del_protocol() to correctly
+ *				  maintain copy bit.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -50,15 +52,11 @@
 
 #ifdef CONFIG_IP_MULTICAST
 
-static struct inet_protocol igmp_protocol = 
-{
-	igmp_rcv,		/* IGMP handler		*/
-	NULL,			/* IGMP error control	*/
-	IPPROTO_PREVIOUS,	/* next			*/
-	IPPROTO_IGMP,		/* protocol ID		*/
-	0,			/* copy			*/
-	NULL,			/* data			*/
-	"IGMP"			/* name			*/
+static struct inet_protocol igmp_protocol = {
+	handler:	igmp_rcv,
+	next:		IPPROTO_PREVIOUS,
+	protocol:	IPPROTO_IGMP,
+	name:		"IGMP"
 };
 
 #undef  IPPROTO_PREVIOUS
@@ -66,44 +64,33 @@
 
 #endif
 
-static struct inet_protocol tcp_protocol = 
-{
-	tcp_v4_rcv,		/* TCP handler		*/
-	tcp_v4_err,		/* TCP error control	*/  
-	IPPROTO_PREVIOUS,
-	IPPROTO_TCP,		/* protocol ID		*/
-	0,			/* copy			*/
-	NULL,			/* data			*/
-	"TCP"			/* name			*/
+static struct inet_protocol tcp_protocol = {
+	handler:	tcp_v4_rcv,
+	err_handler:	tcp_v4_err,
+	next:		IPPROTO_PREVIOUS,
+	protocol:	IPPROTO_TCP,
+	name:		"TCP"
 };
 
 #undef  IPPROTO_PREVIOUS
 #define IPPROTO_PREVIOUS &tcp_protocol
 
-static struct inet_protocol udp_protocol = 
-{
-	udp_rcv,		/* UDP handler		*/
-	udp_err,		/* UDP error control	*/
-	IPPROTO_PREVIOUS,	/* next			*/
-	IPPROTO_UDP,		/* protocol ID		*/
-	0,			/* copy			*/
-	NULL,			/* data			*/
-	"UDP"			/* name			*/
+static struct inet_protocol udp_protocol = {
+	handler:	udp_rcv,
+	err_handler:	udp_err,
+	next:		IPPROTO_PREVIOUS,
+	protocol:	IPPROTO_UDP,
+	name:		"UDP"
 };
 
 #undef  IPPROTO_PREVIOUS
 #define IPPROTO_PREVIOUS &udp_protocol
 
-
-static struct inet_protocol icmp_protocol = 
-{
-	icmp_rcv,		/* ICMP handler		*/
-	NULL,			/* ICMP error control	*/
-	IPPROTO_PREVIOUS,	/* next			*/
-	IPPROTO_ICMP,		/* protocol ID		*/
-	0,			/* copy			*/
-	NULL,			/* data			*/
-	"ICMP"			/* name			*/
+static struct inet_protocol icmp_protocol = {
+	handler:	icmp_rcv,
+	next:		IPPROTO_PREVIOUS,
+	protocol:	IPPROTO_ICMP,
+	name:		"ICMP"
 };
 
 #undef  IPPROTO_PREVIOUS
@@ -134,10 +121,8 @@
 	 */
 	 
 	p2 = (struct inet_protocol *) prot->next;
-	while(p2 != NULL) 
-	{
-		if (p2->protocol == prot->protocol) 
-		{
+	while (p2) {
+		if (p2->protocol == prot->protocol) {
 			prot->copy = 1;
 			break;
 		}
@@ -158,38 +143,39 @@
 
 	hash = prot->protocol & (MAX_INET_PROTOS - 1);
 	br_write_lock_bh(BR_NETPROTO_LOCK);
-	if (prot == inet_protos[hash]) 
-	{
+	if (prot == inet_protos[hash]) {
 		inet_protos[hash] = (struct inet_protocol *) inet_protos[hash]->next;
 		br_write_unlock_bh(BR_NETPROTO_LOCK);
-		return(0);
+		return 0;
 	}
 
 	p = (struct inet_protocol *) inet_protos[hash];
-	while(p != NULL) 
-	{
+
+	if (p != NULL && p->protocol == prot->protocol)
+		lp = p;
+
+	while (p) {
 		/*
 		 * We have to worry if the protocol being deleted is
 		 * the last one on the list, then we may need to reset
 		 * someone's copied bit.
 		 */
-		if (p->next != NULL && p->next == prot) 
-		{
+		if (p->next && p->next == prot) {
 			/*
 			 * if we are the last one with this protocol and
 			 * there is a previous one, reset its copy bit.
 			 */
-			if (p->copy == 0 && lp != NULL) 
+			if (prot->copy == 0 && lp != NULL)
 				lp->copy = 0;
 			p->next = prot->next;
 			br_write_unlock_bh(BR_NETPROTO_LOCK);
-			return(0);
+			return 0;
 		}
 		if (p->next != NULL && p->next->protocol == prot->protocol) 
-			lp = p;
+			lp = p->next;
 
 		p = (struct inet_protocol *) p->next;
 	}
 	br_write_unlock_bh(BR_NETPROTO_LOCK);
-	return(-1);
+	return -1;
 }
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.4.4/linux/net/ipv4/raw.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/raw.c	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
  *
  *		RAW - implementation of IP "raw" sockets.
  *
- * Version:	$Id: raw.c,v 1.60 2001/02/23 06:32:11 davem Exp $
+ * Version:	$Id: raw.c,v 1.61 2001/05/03 20:56:04 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -14,8 +14,9 @@
  *		Alan Cox	:	verify_area() fixed up
  *		Alan Cox	:	ICMP error handling
  *		Alan Cox	:	EMSGSIZE if you send too big a packet
- *		Alan Cox	: 	Now uses generic datagrams and shared skbuff
- *					library. No more peek crashes, no more backlogs
+ *		Alan Cox	: 	Now uses generic datagrams and shared
+ *					skbuff library. No more peek crashes,
+ *					no more backlogs
  *		Alan Cox	:	Checks sk->broadcast.
  *		Alan Cox	:	Uses skb_free_datagram/skb_copy_datagram
  *		Alan Cox	:	Raw passes ip options too
@@ -101,11 +102,11 @@
 {
 	struct sock *s = sk;
 
-	for(s = sk; s; s = s->next) {
-		if((s->num == num) 				&&
-		   !(s->daddr && s->daddr != raddr) 		&&
-		   !(s->rcv_saddr && s->rcv_saddr != laddr)	&&
-		   !(s->bound_dev_if && s->bound_dev_if != dif))
+	for (s = sk; s; s = s->next) {
+		if (s->num == num 				&&
+		    !(s->daddr && s->daddr != raddr) 		&&
+		    !(s->rcv_saddr && s->rcv_saddr != laddr)	&&
+		    !(s->bound_dev_if && s->bound_dev_if != dif))
 			break; /* gotcha */
 	}
 	return s;
@@ -117,7 +118,7 @@
  */
 static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
 {
-	int    type;
+	int type;
 
 	type = skb->h.icmph->type;
 	if (type < 32)
@@ -145,19 +146,19 @@
 			     iph->saddr, iph->daddr,
 			     skb->dev->ifindex);
 
-	while(sk != NULL) {
+	while (sk) {
 		struct sock *sknext = __raw_v4_lookup(sk->next, iph->protocol,
 						      iph->saddr, iph->daddr,
 						      skb->dev->ifindex);
 		if (iph->protocol != IPPROTO_ICMP ||
-		    ! icmp_filter(sk, skb)) {
+		    !icmp_filter(sk, skb)) {
 			struct sk_buff *clone;
 
-			if(sknext == NULL)
+			if (!sknext)
 				break;
 			clone = skb_clone(skb, GFP_ATOMIC);
 			/* Not releasing hash table! */
-			if(clone)
+			if (clone)
 				raw_rcv(sk, clone);
 		}
 		sk = sknext;
@@ -203,14 +204,15 @@
 		err = icmp_err_convert[code].errno;
 		harderr = icmp_err_convert[code].fatal;
 		if (code == ICMP_FRAG_NEEDED) {
-			harderr = (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT);
+			harderr = sk->protinfo.af_inet.pmtudisc !=
+					IP_PMTUDISC_DONT;
 			err = EMSGSIZE;
 		}
 	}
 
 	if (sk->protinfo.af_inet.recverr) {
 		struct iphdr *iph = (struct iphdr*)skb->data;
-		u8 *payload = skb->data+(iph->ihl<<2);
+		u8 *payload = skb->data + (iph->ihl << 2);
 
 		if (sk->protinfo.af_inet.hdrincl)
 			payload = skb->data;
@@ -227,8 +229,7 @@
 {
 	/* Charge it to the socket. */
 	
-	if (sock_queue_rcv_skb(sk,skb)<0)
-	{
+	if (sock_queue_rcv_skb(sk, skb) < 0) {
 		IP_INC_STATS(IpInDiscards);
 		kfree_skb(skb);
 		return NET_RX_DROP;
@@ -240,7 +241,7 @@
 
 int raw_rcv(struct sock *sk, struct sk_buff *skb)
 {
-	skb_push(skb, skb->data-skb->nh.raw);
+	skb_push(skb, skb->data - skb->nh.raw);
 
 	raw_rcv_skb(sk, skb);
 	return 0;
@@ -248,9 +249,9 @@
 
 struct rawfakehdr 
 {
-	struct  iovec *iov;
+	struct	iovec *iov;
 	u32	saddr;
-	struct dst_entry *dst;
+	struct	dst_entry *dst;
 };
 
 /*
@@ -261,7 +262,8 @@
  *	Callback support is trivial for SOCK_RAW
  */
   
-static int raw_getfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+static int raw_getfrag(const void *p, char *to, unsigned int offset,
+			unsigned int fraglen)
 {
 	struct rawfakehdr *rfh = (struct rawfakehdr *) p;
 	return memcpy_fromiovecend(to, rfh->iov, offset, fraglen);
@@ -271,27 +273,28 @@
  *	IPPROTO_RAW needs extra work.
  */
  
-static int raw_getrawfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+static int raw_getrawfrag(const void *p, char *to, unsigned int offset,
+				unsigned int fraglen)
 {
 	struct rawfakehdr *rfh = (struct rawfakehdr *) p;
 
 	if (memcpy_fromiovecend(to, rfh->iov, offset, fraglen))
 		return -EFAULT;
 
-	if (offset==0) {
+	if (!offset) {
 		struct iphdr *iph = (struct iphdr *)to;
 		if (!iph->saddr)
 			iph->saddr = rfh->saddr;
-		iph->check=0;
-		iph->tot_len=htons(fraglen);	/* This is right as you can't frag
-						   RAW packets */
+		iph->check   = 0;
+		iph->tot_len = htons(fraglen); /* This is right as you can't
+						  frag RAW packets */
 		/*
 	 	 *	Deliberate breach of modularity to keep 
 	 	 *	ip_build_xmit clean (well less messy).
 		 */
 		if (!iph->id)
 			ip_select_ident(iph, rfh->dst, NULL);
-		iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
+		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	}
 	return 0;
 }
@@ -317,15 +320,17 @@
 	   If len was ULONG_MAX-10 it would be cathastrophe  --ANK
 	 */
 
+	err = -EMSGSIZE;
 	if (len < 0 || len > 0xFFFF)
-		return -EMSGSIZE;
+		goto out;
 
 	/*
 	 *	Check the flags.
 	 */
 
-	if (msg->msg_flags & MSG_OOB)		/* Mirror BSD error message compatibility */
-		return -EOPNOTSUPP;
+	err = -EOPNOTSUPP;
+	if (msg->msg_flags & MSG_OOB)	/* Mirror BSD error message */
+		goto out;               /* compatibility */
 			 
 	/*
 	 *	Get and verify the address. 
@@ -333,14 +338,18 @@
 
 	if (msg->msg_namelen) {
 		struct sockaddr_in *usin = (struct sockaddr_in*)msg->msg_name;
+		err = -EINVAL;
 		if (msg->msg_namelen < sizeof(*usin))
-			return(-EINVAL);
+			goto out;
 		if (usin->sin_family != AF_INET) {
 			static int complained;
 			if (!complained++)
-				printk(KERN_INFO "%s forgot to set AF_INET in raw sendmsg. Fix it!\n", current->comm);
+				printk(KERN_INFO "%s forgot to set AF_INET in "
+						 "raw sendmsg. Fix it!\n",
+						 current->comm);
+			err = -EINVAL;
 			if (usin->sin_family)
-				return -EINVAL;
+				goto out;
 		}
 		daddr = usin->sin_addr.s_addr;
 		/* ANK: I did not forget to get protocol from port field.
@@ -348,8 +357,9 @@
 		 * IP_HDRINCL is much more convenient.
 		 */
 	} else {
+		err = -EINVAL;
 		if (sk->state != TCP_ESTABLISHED) 
-			return(-EINVAL);
+			goto out;
 		daddr = sk->daddr;
 	}
 
@@ -358,11 +368,11 @@
 	ipc.oif = sk->bound_dev_if;
 
 	if (msg->msg_controllen) {
-		int tmp = ip_cmsg_send(msg, &ipc);
-		if (tmp)
-			return tmp;
+		err = ip_cmsg_send(msg, &ipc);
+		if (err)
+			goto out;
 		if (ipc.opt)
-			free=1;
+			free = 1;
 	}
 
 	rfh.saddr = ipc.addr;
@@ -385,7 +395,7 @@
 		}
 	}
 	tos = RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute;
-	if (msg->msg_flags&MSG_DONTROUTE)
+	if (msg->msg_flags & MSG_DONTROUTE)
 		tos |= RTO_ONLINK;
 
 	if (MULTICAST(daddr)) {
@@ -401,31 +411,31 @@
 		goto done;
 
 	err = -EACCES;
-	if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
+	if (rt->rt_flags & RTCF_BROADCAST && !sk->broadcast)
 		goto done;
 
-	if (msg->msg_flags&MSG_CONFIRM)
+	if (msg->msg_flags & MSG_CONFIRM)
 		goto do_confirm;
 back_from_confirm:
 
-	rfh.iov = msg->msg_iov;
-	rfh.saddr = rt->rt_src;
-	rfh.dst = &rt->u.dst;
+	rfh.iov		= msg->msg_iov;
+	rfh.saddr	= rt->rt_src;
+	rfh.dst		= &rt->u.dst;
 	if (!ipc.addr)
 		ipc.addr = rt->rt_dst;
-	err=ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag : raw_getfrag,
-			  &rfh, len, &ipc, rt, msg->msg_flags);
+	err = ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag :
+		       	    raw_getfrag, &rfh, len, &ipc, rt, msg->msg_flags);
 
 done:
 	if (free)
 		kfree(ipc.opt);
 	ip_rt_put(rt);
 
-	return err<0 ? err : len;
+out:	return err < 0 ? err : len;
 
 do_confirm:
 	dst_confirm(&rt->u.dst);
-	if (!(msg->msg_flags&MSG_PROBE) || len)
+	if (!(msg->msg_flags & MSG_PROBE) || len)
 		goto back_from_confirm;
 	err = 0;
 	goto done;
@@ -445,19 +455,22 @@
 static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
 	struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+	int ret = -EINVAL;
 	int chk_addr_ret;
 
-	if((sk->state != TCP_CLOSE) || (addr_len < sizeof(struct sockaddr_in)))
-		return -EINVAL;
+	if (sk->state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
+		goto out;
 	chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
-	if(addr->sin_addr.s_addr != 0 && chk_addr_ret != RTN_LOCAL &&
-	   chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
-		return -EADDRNOTAVAIL;
+	ret = -EADDRNOTAVAIL;
+	if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
+	    chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
+		goto out;
 	sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
-	if(chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
+	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
 		sk->saddr = 0;  /* Use device */
 	sk_dst_reset(sk);
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 /*
@@ -466,29 +479,30 @@
  */
 
 int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
-		int noblock, int flags,int *addr_len)
+		int noblock, int flags, int *addr_len)
 {
-	int copied=0;
+	int copied = 0;
+	int err = -EOPNOTSUPP;
+	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
 	struct sk_buff *skb;
-	int err;
-	struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
 
 	if (flags & MSG_OOB)
-		return -EOPNOTSUPP;
+		goto out;
 
 	if (addr_len)
-		*addr_len=sizeof(*sin);
+		*addr_len = sizeof(*sin);
 
-	if (flags & MSG_ERRQUEUE)
-		return ip_recv_error(sk, msg, len);
+	if (flags & MSG_ERRQUEUE) {
+		err = ip_recv_error(sk, msg, len);
+		goto out;
+	}
 
-	skb=skb_recv_datagram(sk,flags,noblock,&err);
-	if(skb==NULL)
- 		return err;
+	skb = skb_recv_datagram(sk, flags, noblock, &err);
+	if (!skb)
+		goto out;
 
 	copied = skb->len;
-	if (len < copied)
-	{
+	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
@@ -508,7 +522,7 @@
 		ip_cmsg_recv(msg, skb);
 done:
 	skb_free_datagram(sk, skb);
-	return (err ? : copied);
+out:	return err ? : copied;
 }
 
 static int raw_init(struct sock *sk)
@@ -530,19 +544,21 @@
 
 static int raw_geticmpfilter(struct sock *sk, char *optval, int *optlen)
 {
-	int len;
+	int len, ret = -EFAULT;
 
-	if (get_user(len,optlen))
-		return -EFAULT;
+	if (get_user(len, optlen))
+		goto out;
+	ret = -EINVAL;
 	if (len < 0)
-		return -EINVAL;
+		goto out;
 	if (len > sizeof(struct icmp_filter))
 		len = sizeof(struct icmp_filter);
-	if (put_user(len, optlen))
-		return -EFAULT;
-	if (copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len))
-		return -EFAULT;
-	return 0;
+	ret = -EFAULT;
+	if (put_user(len, optlen) ||
+	    copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len))
+		goto out;
+	ret = 0;
+out:	return ret;
 }
 
 static int raw_setsockopt(struct sock *sk, int level, int optname, 
@@ -551,13 +567,12 @@
 	if (level != SOL_RAW)
 		return ip_setsockopt(sk, level, optname, optval, optlen);
 
-	switch (optname) {
-	case ICMP_FILTER:
+	if (optname == ICMP_FILTER) {
 		if (sk->num != IPPROTO_ICMP)
 			return -EOPNOTSUPP;
-		return raw_seticmpfilter(sk, optval, optlen);
-	};
-
+		else
+			return raw_seticmpfilter(sk, optval, optlen);
+	}
 	return -ENOPROTOOPT;
 }
 
@@ -567,26 +582,23 @@
 	if (level != SOL_RAW)
 		return ip_getsockopt(sk, level, optname, optval, optlen);
 
-	switch (optname) {
-	case ICMP_FILTER:
+	if (optname == ICMP_FILTER) {
 		if (sk->num != IPPROTO_ICMP)
 			return -EOPNOTSUPP;
-		return raw_geticmpfilter(sk, optval, optlen);
-	};
-
+		else
+			return raw_geticmpfilter(sk, optval, optlen);
+	}
 	return -ENOPROTOOPT;
 }
 
 static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	switch(cmd) {
-		case SIOCOUTQ:
-		{
+	switch (cmd) {
+		case SIOCOUTQ: {
 			int amount = atomic_read(&sk->wmem_alloc);
 			return put_user(amount, (int *)arg);
 		}
-		case SIOCINQ:
-		{
+		case SIOCINQ: {
 			struct sk_buff *skb;
 			int amount = 0;
 
@@ -609,13 +621,11 @@
 
 static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
 {
-	unsigned int dest, src;
-	__u16 destp, srcp;
+	unsigned int dest = sp->daddr,
+		     src = sp->rcv_saddr;
+	__u16 destp = 0,
+	      srcp  = sp->num;
 
-	dest  = sp->daddr;
-	src   = sp->rcv_saddr;
-	destp = 0;
-	srcp  = sp->num;
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
 		i, src, srcp, dest, destp, sp->state, 
@@ -629,15 +639,15 @@
 int raw_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	int len = 0, num = 0, i;
-	off_t pos = 0;
+	off_t pos = 128;
 	off_t begin;
 	char tmpbuf[129];
 
 	if (offset < 128) 
 		len += sprintf(buffer, "%-127s\n",
 			       "  sl  local_address rem_address   st tx_queue "
-			       "rx_queue tr tm->when retrnsmt   uid  timeout inode");
-	pos = 128;
+			       "rx_queue tr tm->when retrnsmt   uid  timeout "
+			       "inode");
 	read_lock(&raw_v4_lock);
 	for (i = 0; i < RAWV4_HTABLE_SIZE; i++) {
 		struct sock *sk;
@@ -649,8 +659,8 @@
 			if (pos <= offset)
 				continue;
 			get_raw_sock(sk, tmpbuf, i);
-			len += sprintf(buffer+len, "%-127s\n", tmpbuf);
-			if(len >= length)
+			len += sprintf(buffer + len, "%-127s\n", tmpbuf);
+			if (len >= length)
 				goto out;
 		}
 	}
@@ -659,7 +669,7 @@
 	begin = len - (pos - offset);
 	*start = buffer + begin;
 	len -= begin;
-	if(len > length)
+	if (len > length)
 		len = length;
 	if (len < 0)
 		len = 0; 
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.4.4/linux/net/ipv4/route.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/route.c	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.93 2001/02/22 01:03:05 davem Exp $
+ * Version:	$Id: route.c,v 1.94 2001/05/05 01:01:02 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -101,21 +101,21 @@
 
 #define RT_GC_TIMEOUT (300*HZ)
 
-int ip_rt_min_delay = 2*HZ;
-int ip_rt_max_delay = 10*HZ;
+int ip_rt_min_delay		= 2 * HZ;
+int ip_rt_max_delay		= 10 * HZ;
 int ip_rt_max_size;
-int ip_rt_gc_timeout = RT_GC_TIMEOUT;
-int ip_rt_gc_interval = 60*HZ;
-int ip_rt_gc_min_interval = 5*HZ;
-int ip_rt_redirect_number = 9;
-int ip_rt_redirect_load = HZ/50;
-int ip_rt_redirect_silence = ((HZ/50) << (9+1));
-int ip_rt_error_cost = HZ;
-int ip_rt_error_burst = 5*HZ;
-int ip_rt_gc_elasticity = 8;
-int ip_rt_mtu_expires = 10*60*HZ;
-int ip_rt_min_pmtu = 512+20+20;
-int ip_rt_min_advmss = 256;
+int ip_rt_gc_timeout		= RT_GC_TIMEOUT;
+int ip_rt_gc_interval		= 60 * HZ;
+int ip_rt_gc_min_interval	= 5 * HZ;
+int ip_rt_redirect_number	= 9;
+int ip_rt_redirect_load		= HZ / 50;
+int ip_rt_redirect_silence	= ((HZ / 50) << (9 + 1));
+int ip_rt_error_cost		= HZ;
+int ip_rt_error_burst		= 5 * HZ;
+int ip_rt_gc_elasticity		= 8;
+int ip_rt_mtu_expires		= 10 * 60 * HZ;
+int ip_rt_min_pmtu		= 512 + 20 + 20;
+int ip_rt_min_advmss		= 256;
 
 static unsigned long rt_deadline;
 
@@ -128,28 +128,25 @@
  *	Interface to generic destination cache.
  */
 
-static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32);
-static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
-					   struct sk_buff *);
-static void		  ipv4_dst_destroy(struct dst_entry * dst);
-static struct dst_entry * ipv4_negative_advice(struct dst_entry *);
-static void		  ipv4_link_failure(struct sk_buff *skb);
+static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
+static struct dst_entry *ipv4_dst_reroute(struct dst_entry *dst,
+					   struct sk_buff *skb);
+static void		 ipv4_dst_destroy(struct dst_entry *dst);
+static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
+static void		 ipv4_link_failure(struct sk_buff *skb);
 static int rt_garbage_collect(void);
 
 
-struct dst_ops ipv4_dst_ops =
-{
-	AF_INET,
-	__constant_htons(ETH_P_IP),
-	0,
-
-	rt_garbage_collect,
-	ipv4_dst_check,
-	ipv4_dst_reroute,
-	ipv4_dst_destroy,
-	ipv4_negative_advice,
-	ipv4_link_failure,
-	sizeof(struct rtable),
+struct dst_ops ipv4_dst_ops = {
+	family:			AF_INET,
+	protocol:		__constant_htons(ETH_P_IP),
+	gc:			rt_garbage_collect,
+	check:			ipv4_dst_check,
+	reroute:		ipv4_dst_reroute,
+	destroy:		ipv4_dst_destroy,
+	negative_advice:	ipv4_negative_advice,
+	link_failure:		ipv4_link_failure,
+	entry_size:		sizeof(struct rtable),
 };
 
 #ifdef CONFIG_INET_ECN
@@ -201,32 +198,36 @@
 static unsigned			rt_hash_mask;
 static int			rt_hash_log;
 
-static int rt_intern_hash(unsigned hash, struct rtable * rth, struct rtable ** res);
+static int rt_intern_hash(unsigned hash, struct rtable *rth,
+				struct rtable **res);
 
 static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
 {
-	unsigned hash = ((daddr&0xF0F0F0F0)>>4)|((daddr&0x0F0F0F0F)<<4);
-	hash ^= saddr^tos;
-	hash ^= (hash>>16);
-	return (hash^(hash>>8)) & rt_hash_mask;
+	unsigned hash = ((daddr & 0xF0F0F0F0) >> 4) |
+			((daddr & 0x0F0F0F0F) << 4);
+	hash ^= saddr ^ tos;
+	hash ^= (hash >> 16);
+	return (hash ^ (hash >> 8)) & rt_hash_mask;
 }
 
-static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length)
+static int rt_cache_get_info(char *buffer, char **start, off_t offset,
+				int length)
 {
-	int len=0;
-	off_t pos=0;
+	int len = 0;
+	off_t pos = 128;
 	char temp[129];
 	struct rtable *r;
 	int i;
 
-	pos = 128;
-
-	if (offset<128)	{
-		sprintf(buffer,"%-127s\n", "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\tHHUptod\tSpecDst");
+	if (offset < 128) {
+		sprintf(buffer, "%-127s\n",
+			"Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
+			"Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t"
+			"HHUptod\tSpecDst");
 		len = 128;
   	}
 	
-	for (i = rt_hash_mask; i>=0; i--) {
+	for (i = rt_hash_mask; i >= 0; i--) {
 		read_lock_bh(&rt_hash_table[i].lock);
 		for (r = rt_hash_table[i].chain; r; r = r->u.rt_next) {
 			/*
@@ -238,7 +239,8 @@
 				len = 0;
 				continue;
 			}
-			sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
+			sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
+				"%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
 				r->u.dst.dev ? r->u.dst.dev->name : "*",
 				(unsigned long)r->rt_dst,
 				(unsigned long)r->rt_gateway,
@@ -246,14 +248,19 @@
 				atomic_read(&r->u.dst.__refcnt),
 				r->u.dst.__use,
 				0,
-				(unsigned long)r->rt_src, (int)r->u.dst.advmss + 40,
+				(unsigned long)r->rt_src,
+				(int)r->u.dst.advmss + 40,
 				r->u.dst.window,
-				(int)((r->u.dst.rtt>>3) + r->u.dst.rttvar),
+				(int)((r->u.dst.rtt >> 3) + r->u.dst.rttvar),
 				r->key.tos,
-				r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
-				r->u.dst.hh ? (r->u.dst.hh->hh_output == dev_queue_xmit) : 0,
+				r->u.dst.hh ?
+					atomic_read(&r->u.dst.hh->hh_refcnt) :
+					-1,
+				r->u.dst.hh ?
+			       		(r->u.dst.hh->hh_output ==
+					 dev_queue_xmit) : 0,
 				r->rt_spec_dst);
-			sprintf(buffer+len,"%-127s\n",temp);
+			sprintf(buffer + len, "%-127s\n", temp);
 			len += 128;
 			if (pos >= offset+length) {
 				read_unlock_bh(&rt_hash_table[i].lock);
@@ -264,9 +271,9 @@
         }
 
 done:
-  	*start = buffer+len-(pos-offset);
-  	len = pos-offset;
-  	if (len>length)
+  	*start = buffer + len - (pos - offset);
+  	len = pos - offset;
+  	if (len > length)
   		len = length;
   	return len;
 }
@@ -286,45 +293,47 @@
 {
 	/* Kill broadcast/multicast entries very aggresively, if they
 	   collide in hash table with more useful entries */
-	return ((rth->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
-		&& rth->key.iif && rth->u.rt_next);
+	return (rth->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
+		rth->key.iif && rth->u.rt_next;
 }
 
 static __inline__ int rt_valuable(struct rtable *rth)
 {
-	return ((rth->rt_flags&(RTCF_REDIRECTED|RTCF_NOTIFY))
-		|| rth->u.dst.expires);
+	return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
+		rth->u.dst.expires;
 }
 
 static __inline__ int rt_may_expire(struct rtable *rth, int tmo1, int tmo2)
 {
 	int age;
+	int ret = 0;
 
 	if (atomic_read(&rth->u.dst.__refcnt))
-		return 0;
+		goto out;
 
+	ret = 1;
 	if (rth->u.dst.expires && (long)(rth->u.dst.expires - jiffies) <= 0)
-		return 1;
+		goto out;
 
 	age = jiffies - rth->u.dst.lastuse;
-	if (age <= tmo1 && !rt_fast_clean(rth))
-		return 0;
-	if (age <= tmo2 && rt_valuable(rth))
-		return 0;
-	return 1;
+	ret = 0;
+	if ((age <= tmo1 && !rt_fast_clean(rth)) ||
+	    (age <= tmo2 && rt_valuable(rth)))
+		goto out;
+	ret = 1;
+out:	return ret;
 }
 
 /* This runs via a timer and thus is always in BH context. */
 static void SMP_TIMER_NAME(rt_check_expire)(unsigned long dummy)
 {
-	int i, t;
 	static int rover;
+	int i = rover, t;
 	struct rtable *rth, **rthp;
 	unsigned long now = jiffies;
 
-	i = rover;
-
-	for (t=(ip_rt_gc_interval<<rt_hash_log); t>=0; t -= ip_rt_gc_timeout) {
+	for (t = ip_rt_gc_interval << rt_hash_log; t >= 0;
+	     t -= ip_rt_gc_timeout) {
 		unsigned tmo = ip_rt_gc_timeout;
 
 		i = (i + 1) & rt_hash_mask;
@@ -345,9 +354,7 @@
 				continue;
 			}
 
-			/*
-			 * Cleanup aged off entries.
-			 */
+			/* Cleanup aged off entries. */
 			*rthp = rth->u.rt_next;
 			rt_free(rth);
 		}
@@ -369,18 +376,18 @@
 static void SMP_TIMER_NAME(rt_run_flush)(unsigned long dummy)
 {
 	int i;
-	struct rtable * rth, * next;
+	struct rtable *rth, *next;
 
 	rt_deadline = 0;
 
-	for (i=rt_hash_mask; i>=0; i--) {
+	for (i = rt_hash_mask; i >= 0; i--) {
 		write_lock_bh(&rt_hash_table[i].lock);
 		rth = rt_hash_table[i].chain;
 		if (rth)
 			rt_hash_table[i].chain = NULL;
 		write_unlock_bh(&rt_hash_table[i].lock);
 
-		for (; rth; rth=next) {
+		for (; rth; rth = next) {
 			next = rth->u.rt_next;
 			rt_free(rth);
 		}
@@ -460,23 +467,24 @@
 	 */
 	if (now - last_gc < ip_rt_gc_min_interval &&
 	    atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
-		return 0;
+		goto out;
 
 	/* Calculate number of entries, which we want to expire now. */
-	goal = atomic_read(&ipv4_dst_ops.entries) - (ip_rt_gc_elasticity<<rt_hash_log);
+	goal = atomic_read(&ipv4_dst_ops.entries) -
+		(ip_rt_gc_elasticity << rt_hash_log);
 	if (goal <= 0) {
 		if (equilibrium < ipv4_dst_ops.gc_thresh)
 			equilibrium = ipv4_dst_ops.gc_thresh;
 		goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
 		if (goal > 0) {
-			equilibrium += min(goal/2, rt_hash_mask+1);
+			equilibrium += min(goal / 2, rt_hash_mask + 1);
 			goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
 		}
 	} else {
 		/* We are in dangerous area. Try to reduce cache really
 		 * aggressively.
 		 */
-		goal = max(goal/2, rt_hash_mask+1);
+		goal = max(goal / 2, rt_hash_mask + 1);
 		equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
 	}
 
@@ -491,7 +499,7 @@
 	do {
 		int i, k;
 
-		for (i=rt_hash_mask, k=rover; i>=0; i--) {
+		for (i = rt_hash_mask, k = rover; i >= 0; i--) {
 			unsigned tmo = expire;
 
 			k = (k + 1) & rt_hash_mask;
@@ -530,15 +538,16 @@
 
 		expire >>= 1;
 #if RT_CACHE_DEBUG >= 2
-		printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire, atomic_read(&ipv4_dst_ops.entries), goal, i);
+		printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire,
+				atomic_read(&ipv4_dst_ops.entries), goal, i);
 #endif
 
 		if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
-			return 0;
+			goto out;
 	} while (!in_softirq() && jiffies - now < 1);
 
 	if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
-		return 0;
+		goto out;
 	if (net_ratelimit())
 		printk("dst cache overflow\n");
 	return 1;
@@ -549,12 +558,13 @@
 	    atomic_read(&ipv4_dst_ops.entries) < ipv4_dst_ops.gc_thresh)
 		expire = ip_rt_gc_timeout;
 #if RT_CACHE_DEBUG >= 2
-	printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire, atomic_read(&ipv4_dst_ops.entries), goal, rover);
+	printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire,
+			atomic_read(&ipv4_dst_ops.entries), goal, rover);
 #endif
-	return 0;
+out:	return 0;
 }
 
-static int rt_intern_hash(unsigned hash, struct rtable * rt, struct rtable ** rp)
+static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
 {
 	struct rtable	*rth, **rthp;
 	unsigned long	now = jiffies;
@@ -604,11 +614,11 @@
 			if (attempts-- > 0) {
 				int saved_elasticity = ip_rt_gc_elasticity;
 				int saved_int = ip_rt_gc_min_interval;
-				ip_rt_gc_elasticity = 1;
-				ip_rt_gc_min_interval = 0;
+				ip_rt_gc_elasticity	= 1;
+				ip_rt_gc_min_interval	= 0;
 				rt_garbage_collect();
-				ip_rt_gc_min_interval = saved_int;
-				ip_rt_gc_elasticity = saved_elasticity;
+				ip_rt_gc_min_interval	= saved_int;
+				ip_rt_gc_elasticity	= saved_elasticity;
 				goto restart;
 			}
 
@@ -622,9 +632,10 @@
 	rt->u.rt_next = rt_hash_table[hash].chain;
 #if RT_CACHE_DEBUG >= 2
 	if (rt->u.rt_next) {
-		struct rtable * trt;
-		printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst));
-		for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next)
+		struct rtable *trt;
+		printk("rt_cache @%02x: %u.%u.%u.%u", hash,
+				NIPQUAD(rt->rt_dst));
+		for (trt = rt->u.rt_next; trt; trt = trt->u.rt_next)
 			printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
 		printk("\n");
 	}
@@ -687,9 +698,8 @@
 			iph->id = htons(inet_getid(rt->peer));
 			return;
 		}
-	} else {
+	} else
 		printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", NET_CALLER(iph));
-	}
 
 	ip_select_fb_ident(iph);
 }
@@ -700,13 +710,13 @@
 
 	write_lock_bh(&rt_hash_table[hash].lock);
 	ip_rt_put(rt);
-	for (rthp = &rt_hash_table[hash].chain; *rthp; rthp = &(*rthp)->u.rt_next) {
+	for (rthp = &rt_hash_table[hash].chain; *rthp;
+	     rthp = &(*rthp)->u.rt_next)
 		if (*rthp == rt) {
 			*rthp = rt->u.rt_next;
 			rt_free(rt);
 			break;
 		}
-	}
 	write_unlock_bh(&rt_hash_table[hash].lock);
 }
 
@@ -738,14 +748,16 @@
 			goto reject_redirect;
 	}
 
-	for (i=0; i<2; i++) {
-		for (k=0; k<2; k++) {
-			unsigned hash = rt_hash_code(daddr, skeys[i]^(ikeys[k]<<5), tos);
+	for (i = 0; i < 2; i++) {
+		for (k = 0; k < 2; k++) {
+			unsigned hash = rt_hash_code(daddr,
+						     skeys[i] ^ (ikeys[k] << 5),
+						     tos);
 
 			rthp=&rt_hash_table[hash].chain;
 
 			read_lock(&rt_hash_table[hash].lock);
-			while ( (rth = *rthp) != NULL) {
+			while ((rth = *rthp) != NULL) {
 				struct rtable *rt;
 
 				if (rth->key.dst != daddr ||
@@ -774,23 +786,21 @@
 					return;
 				}
 
-				/*
-				 * Copy all the information.
-				 */
+				/* Copy all the information. */
 				*rt = *rth;
-				rt->u.dst.__use = 1;
+				rt->u.dst.__use		= 1;
 				atomic_set(&rt->u.dst.__refcnt, 1);
 				if (rt->u.dst.dev)
 					dev_hold(rt->u.dst.dev);
-				rt->u.dst.lastuse = jiffies;
-				rt->u.dst.neighbour = NULL;
-				rt->u.dst.hh = NULL;
-				rt->u.dst.obsolete = 0;
+				rt->u.dst.lastuse	= jiffies;
+				rt->u.dst.neighbour	= NULL;
+				rt->u.dst.hh		= NULL;
+				rt->u.dst.obsolete	= 0;
 
-				rt->rt_flags |= RTCF_REDIRECTED;
+				rt->rt_flags		|= RTCF_REDIRECTED;
 
 				/* Gateway is different ... */
-				rt->rt_gateway = new_gw;
+				rt->rt_gateway		= new_gw;
 
 				/* Redirect received -> path was valid */
 				dst_confirm(&rth->u.dst);
@@ -799,7 +809,8 @@
 					atomic_inc(&rt->peer->refcnt);
 
 				if (arp_bind_neighbour(&rt->u.dst) ||
-				    !(rt->u.dst.neighbour->nud_state&NUD_VALID)) {
+				    !(rt->u.dst.neighbour->nud_state &
+					    NUD_VALID)) {
 					if (rt->u.dst.neighbour)
 						neigh_event_send(rt->u.dst.neighbour, NULL);
 					ip_rt_put(rth);
@@ -823,8 +834,10 @@
 reject_redirect:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n"
-		       "  Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n",
+		printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about "
+			"%u.%u.%u.%u ignored.\n"
+			"  Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, "
+			"tos %02x\n",
 		       NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
 		       NIPQUAD(saddr), NIPQUAD(daddr), tos);
 #endif
@@ -834,23 +847,28 @@
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 {
 	struct rtable *rt = (struct rtable*)dst;
+	struct dst_entry *ret = dst;
 
-	if (rt != NULL) {
+	if (rt) {
 		if (dst->obsolete) {
 			ip_rt_put(rt);
-			return NULL;
-		}
-		if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
-			unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
+			ret = NULL;
+		} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
+			   rt->u.dst.expires) {
+			unsigned hash = rt_hash_code(rt->key.dst,
+						     rt->key.src ^
+							(rt->key.oif << 5),
+						     rt->key.tos);
 #if RT_CACHE_DEBUG >= 1
-			printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n",
+			printk(KERN_DEBUG "ip_rt_advice: redirect to "
+					  "%u.%u.%u.%u/%02x dropped\n",
 				NIPQUAD(rt->rt_dst), rt->key.tos);
 #endif
 			rt_del(hash, rt);
-			return NULL;
+			ret = NULL;
 		}
 	}
-	return dst;
+	return ret;
 }
 
 /*
@@ -897,15 +915,17 @@
 	/* Check for load limit; set rate_last to the latest sent
 	 * redirect.
 	 */
-	if (jiffies - rt->u.dst.rate_last > (ip_rt_redirect_load<<rt->u.dst.rate_tokens)) {
+	if (jiffies - rt->u.dst.rate_last >
+	    (ip_rt_redirect_load << rt->u.dst.rate_tokens)) {
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
 		rt->u.dst.rate_last = jiffies;
 		++rt->u.dst.rate_tokens;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 		if (IN_DEV_LOG_MARTIANS(in_dev) &&
-		    rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit())
-			printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for "
-				"%u.%u.%u.%u to %u.%u.%u.%u.\n",
+		    rt->u.dst.rate_tokens == ip_rt_redirect_number &&
+		    net_ratelimit())
+			printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores "
+				"redirects for %u.%u.%u.%u to %u.%u.%u.%u.\n",
 				NIPQUAD(rt->rt_src), rt->rt_iif,
 				NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
 #endif
@@ -921,23 +941,23 @@
 	int code;
 
 	switch (rt->u.dst.error) {
-	case EINVAL:
-	default:
-		kfree_skb(skb);
-		return 0;
-	case EHOSTUNREACH:
-		code = ICMP_HOST_UNREACH;
-		break;
-	case ENETUNREACH:
-		code = ICMP_NET_UNREACH;
-		break;
-	case EACCES:
-		code = ICMP_PKT_FILTERED;
-		break;
+		case EINVAL:
+		default:
+			goto out;
+		case EHOSTUNREACH:
+			code = ICMP_HOST_UNREACH;
+			break;
+		case ENETUNREACH:
+			code = ICMP_NET_UNREACH;
+			break;
+		case EACCES:
+			code = ICMP_PKT_FILTERED;
+			break;
 	}
 
 	now = jiffies;
-	if ((rt->u.dst.rate_tokens += (now - rt->u.dst.rate_last)) > ip_rt_error_burst)
+	rt->u.dst.rate_tokens += now - rt->u.dst.rate_last;
+	if (rt->u.dst.rate_tokens > ip_rt_error_burst)
 		rt->u.dst.rate_tokens = ip_rt_error_burst;
 	rt->u.dst.rate_last = now;
 	if (rt->u.dst.rate_tokens >= ip_rt_error_cost) {
@@ -945,7 +965,7 @@
 		icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
 	}
 
-	kfree_skb(skb);
+out:	kfree_skb(skb);
 	return 0;
 } 
 
@@ -961,7 +981,7 @@
 {
 	int i;
 	
-	for (i = 0; i < sizeof(mtu_plateau)/sizeof(mtu_plateau[0]); i++)
+	for (i = 0; i < sizeof(mtu_plateau) / sizeof(mtu_plateau[0]); i++)
 		if (old_mtu > mtu_plateau[i])
 			return mtu_plateau[i];
 	return 68;
@@ -980,26 +1000,28 @@
 	if (ipv4_config.no_pmtu_disc)
 		return 0;
 
-	for (i=0; i<2; i++) {
+	for (i = 0; i < 2; i++) {
 		unsigned hash = rt_hash_code(daddr, skeys[i], tos);
 
 		read_lock(&rt_hash_table[hash].lock);
-		for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
+		for (rth = rt_hash_table[hash].chain; rth;
+		     rth = rth->u.rt_next) {
 			if (rth->key.dst == daddr &&
 			    rth->key.src == skeys[i] &&
-			    rth->rt_dst == daddr &&
-			    rth->rt_src == iph->saddr &&
+			    rth->rt_dst  == daddr &&
+			    rth->rt_src  == iph->saddr &&
 			    rth->key.tos == tos &&
 			    rth->key.iif == 0 &&
-			    !(rth->u.dst.mxlock&(1<<RTAX_MTU))) {
+			    !(rth->u.dst.mxlock & (1 << RTAX_MTU))) {
 				unsigned short mtu = new_mtu;
 
 				if (new_mtu < 68 || new_mtu >= old_mtu) {
 
 					/* BSD 4.2 compatibility hack :-( */
-					if (mtu == 0 && old_mtu >= rth->u.dst.pmtu &&
-					    old_mtu >= 68 + (iph->ihl<<2))
-						old_mtu -= iph->ihl<<2;
+					if (mtu == 0 &&
+					    old_mtu >= rth->u.dst.pmtu &&
+					    old_mtu >= 68 + (iph->ihl << 2))
+						old_mtu -= iph->ihl << 2;
 
 					mtu = guess_mtu(old_mtu);
 				}
@@ -1008,10 +1030,12 @@
 						dst_confirm(&rth->u.dst);
 						if (mtu < ip_rt_min_pmtu) {
 							mtu = ip_rt_min_pmtu;
-							rth->u.dst.mxlock |= (1<<RTAX_MTU);
+							rth->u.dst.mxlock |=
+								(1 << RTAX_MTU);
 						}
 						rth->u.dst.pmtu = mtu;
-						dst_set_expires(&rth->u.dst, ip_rt_mtu_expires);
+						dst_set_expires(&rth->u.dst,
+							ip_rt_mtu_expires);
 					}
 					est_mtu = mtu;
 				}
@@ -1025,29 +1049,29 @@
 void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu)
 {
 	if (dst->pmtu > mtu && mtu >= 68 &&
-	    !(dst->mxlock&(1<<RTAX_MTU))) {
+	    !(dst->mxlock & (1 << RTAX_MTU))) {
 		if (mtu < ip_rt_min_pmtu) {
 			mtu = ip_rt_min_pmtu;
-			dst->mxlock |= (1<<RTAX_MTU);
+			dst->mxlock |= (1 << RTAX_MTU);
 		}
 		dst->pmtu = mtu;
 		dst_set_expires(dst, ip_rt_mtu_expires);
 	}
 }
 
-static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32 cookie)
+static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
 	dst_release(dst);
 	return NULL;
 }
 
-static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
-					   struct sk_buff *skb)
+static struct dst_entry *ipv4_dst_reroute(struct dst_entry *dst,
+					  struct sk_buff *skb)
 {
 	return NULL;
 }
 
-static void ipv4_dst_destroy(struct dst_entry * dst)
+static void ipv4_dst_destroy(struct dst_entry *dst)
 {
 	struct rtable *rt = (struct rtable *) dst;
 	struct inet_peer *peer = rt->peer;
@@ -1097,23 +1121,25 @@
 	else if (fib_lookup(&rt->key, &res) == 0) {
 #ifdef CONFIG_IP_ROUTE_NAT
 		if (res.type == RTN_NAT)
-			src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+			src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
+						RT_SCOPE_UNIVERSE);
 		else
 #endif
 			src = FIB_RES_PREFSRC(res);
 		fib_res_put(&res);
 	} else
-		src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+		src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
+					RT_SCOPE_UNIVERSE);
 	memcpy(addr, &src, 4);
 }
 
 #ifdef CONFIG_NET_CLS_ROUTE
 static void set_class_tag(struct rtable *rt, u32 tag)
 {
-	if (!(rt->u.dst.tclassid&0xFFFF))
-		rt->u.dst.tclassid |= tag&0xFFFF;
-	if (!(rt->u.dst.tclassid&0xFFFF0000))
-		rt->u.dst.tclassid |= tag&0xFFFF0000;
+	if (!(rt->u.dst.tclassid & 0xFFFF))
+		rt->u.dst.tclassid |= tag & 0xFFFF;
+	if (!(rt->u.dst.tclassid & 0xFFFF0000))
+		rt->u.dst.tclassid |= tag & 0xFFFF0000;
 }
 #endif
 
@@ -1122,12 +1148,14 @@
 	struct fib_info *fi = res->fi;
 
 	if (fi) {
-		if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+		if (FIB_RES_GW(*res) &&
+		    FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
 			rt->rt_gateway = FIB_RES_GW(*res);
-		memcpy(&rt->u.dst.mxlock, fi->fib_metrics, sizeof(fi->fib_metrics));
+		memcpy(&rt->u.dst.mxlock, fi->fib_metrics,
+			sizeof(fi->fib_metrics));
 		if (fi->fib_mtu == 0) {
 			rt->u.dst.pmtu = rt->u.dst.dev->mtu;
-			if (rt->u.dst.mxlock&(1<<RTAX_MTU) &&
+			if (rt->u.dst.mxlock & (1 << RTAX_MTU) &&
 			    rt->rt_gateway != rt->rt_dst &&
 			    rt->u.dst.pmtu > 576)
 				rt->u.dst.pmtu = 576;
@@ -1135,15 +1163,16 @@
 #ifdef CONFIG_NET_CLS_ROUTE
 		rt->u.dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
 #endif
-	} else {
+	} else
 		rt->u.dst.pmtu	= rt->u.dst.dev->mtu;
-	}
+
 	if (rt->u.dst.pmtu > IP_MAX_MTU)
 		rt->u.dst.pmtu = IP_MAX_MTU;
 	if (rt->u.dst.advmss == 0)
-		rt->u.dst.advmss = max(rt->u.dst.dev->mtu-40, ip_rt_min_advmss);
-	if (rt->u.dst.advmss > 65535-40)
-		rt->u.dst.advmss = 65535-40;
+		rt->u.dst.advmss = max(rt->u.dst.dev->mtu - 40,
+					ip_rt_min_advmss);
+	if (rt->u.dst.advmss > 65535 - 40)
+		rt->u.dst.advmss = 65535 - 40;
 
 #ifdef CONFIG_NET_CLS_ROUTE
 #ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -1154,9 +1183,8 @@
         rt->rt_type = res->type;
 }
 
-static int
-ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
-		  u8 tos, struct net_device *dev, int our)
+static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
+				u8 tos, struct net_device *dev, int our)
 {
 	unsigned hash;
 	struct rtable *rth;
@@ -1177,7 +1205,8 @@
 		if (!LOCAL_MCAST(daddr))
 			goto e_inval;
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
-	} else if (fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag) < 0)
+	} else if (fib_validate_source(saddr, 0, tos, 0,
+					dev, &spec_dst, &itag) < 0)
 		goto e_inval;
 
 	rth = dst_alloc(&ipv4_dst_ops);
@@ -1223,8 +1252,8 @@
 #endif
 
 	in_dev_put(in_dev);
-	hash = rt_hash_code(daddr, saddr^(dev->ifindex<<5), tos);
-	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+	hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);
+	return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
 
 e_nobufs:
 	in_dev_put(in_dev);
@@ -1260,24 +1289,22 @@
 	int		err = -EINVAL;
 	int		free_res = 0;
 
-	/*
-	 *	IP on this device is disabled.
-	 */
+	/* IP on this device is disabled. */
 
 	if (!in_dev)
-		return -EINVAL;
+		goto out;
 
-	key.dst = daddr;
-	key.src = saddr;
-	key.tos = tos;
+	key.dst		= daddr;
+	key.src		= saddr;
+	key.tos		= tos;
 #ifdef CONFIG_IP_ROUTE_FWMARK
-	key.fwmark = skb->nfmark;
+	key.fwmark	= skb->nfmark;
 #endif
-	key.iif = dev->ifindex;
-	key.oif = 0;
-	key.scope = RT_SCOPE_UNIVERSE;
+	key.iif		= dev->ifindex;
+	key.oif		= 0;
+	key.scope	= RT_SCOPE_UNIVERSE;
 
-	hash = rt_hash_code(daddr, saddr^(key.iif<<5), tos);
+	hash = rt_hash_code(daddr, saddr ^ (key.iif << 5), tos);
 
 	/* Check for the most weird martians, which can be not detected
 	   by fib_lookup.
@@ -1338,7 +1365,8 @@
 
 	if (res.type == RTN_LOCAL) {
 		int result;
-		result = fib_validate_source(saddr, daddr, tos, loopback_dev.ifindex,
+		result = fib_validate_source(saddr, daddr, tos,
+					     loopback_dev.ifindex,
 					     dev, &spec_dst, &itag);
 		if (result < 0)
 			goto martian_source;
@@ -1360,27 +1388,29 @@
 	out_dev = in_dev_get(FIB_RES_DEV(res));
 	if (out_dev == NULL) {
 		if (net_ratelimit())
-			printk(KERN_CRIT "Bug in ip_route_input_slow(). Please, report\n");
+			printk(KERN_CRIT "Bug in ip_route_input_slow(). "
+					 "Please, report\n");
 		goto e_inval;
 	}
 
-	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev, &spec_dst, &itag);
+	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev,
+				  &spec_dst, &itag);
 	if (err < 0)
 		goto martian_source;
 
 	if (err)
 		flags |= RTCF_DIRECTSRC;
 
-	if (out_dev == in_dev && err && !(flags&(RTCF_NAT|RTCF_MASQ)) &&
-	    (IN_DEV_SHARED_MEDIA(out_dev)
-	     || inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
+	if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
+	    (IN_DEV_SHARED_MEDIA(out_dev) ||
+	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
 		flags |= RTCF_DOREDIRECT;
 
 	if (skb->protocol != __constant_htons(ETH_P_IP)) {
 		/* Not IP (i.e. ARP). Do not create route, if it is
 		 * invalid for proxy arp. DNAT routes are always valid.
 		 */
-		if (out_dev == in_dev && !(flags&RTCF_DNAT))
+		if (out_dev == in_dev && !(flags & RTCF_DNAT))
 			goto e_inval;
 	}
 
@@ -1438,16 +1468,17 @@
 		in_dev_put(out_dev);
 	if (free_res)
 		fib_res_put(&res);
-	return err;
+out:	return err;
 
 brd_input:
 	if (skb->protocol != __constant_htons(ETH_P_IP))
 		goto e_inval;
 
-	if (ZERONET(saddr)) {
+	if (ZERONET(saddr))
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
-	} else {
-		err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag);
+	else {
+		err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
+					  &itag);
 		if (err < 0)
 			goto martian_source;
 		if (err)
@@ -1508,7 +1539,8 @@
 martian_destination:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n",
+		printk(KERN_WARNING "martian destination %u.%u.%u.%u from "
+			"%u.%u.%u.%u, dev %s\n",
 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
 #endif
 e_inval:
@@ -1526,15 +1558,16 @@
 		 *	RFC1812 recommendation, if source is martian,
 		 *	the only hint is MAC header.
 		 */
-		printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n",
+		printk(KERN_WARNING "martian source %u.%u.%u.%u from "
+			"%u.%u.%u.%u, on dev %s\n",
 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
 		if (dev->hard_header_len) {
 			int i;
 			unsigned char *p = skb->mac.raw;
 			printk(KERN_WARNING "ll header: ");
-			for (i=0; i<dev->hard_header_len; i++, p++) {
+			for (i = 0; i < dev->hard_header_len; i++, p++) {
 				printk("%02x", *p);
-				if(i<(dev->hard_header_len-1))
+				if (i < (dev->hard_header_len - 1))
 					printk(":");
 			}
 			printk("\n");
@@ -1552,10 +1585,10 @@
 	int iif = dev->ifindex;
 
 	tos &= IPTOS_RT_MASK;
-	hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
+	hash = rt_hash_code(daddr, saddr ^ (iif << 5), tos);
 
 	read_lock(&rt_hash_table[hash].lock);
-	for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
+	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
 		if (rth->key.dst == daddr &&
 		    rth->key.src == saddr &&
 		    rth->key.iif == iif &&
@@ -1597,7 +1630,8 @@
 #endif
 			    ) {
 				read_unlock(&inetdev_lock);
-				return ip_route_input_mc(skb, daddr, saddr, tos, dev, our);
+				return ip_route_input_mc(skb, daddr, saddr,
+							 tos, dev, our);
 			}
 		}
 		read_unlock(&inetdev_lock);
@@ -1622,31 +1656,33 @@
 	int err;
 	u32 tos;
 
-	tos = oldkey->tos & (IPTOS_RT_MASK|RTO_ONLINK);
-	key.dst = oldkey->dst;
-	key.src = oldkey->src;
-	key.tos = tos&IPTOS_RT_MASK;
-	key.iif = loopback_dev.ifindex;
-	key.oif = oldkey->oif;
+	tos		= oldkey->tos & (IPTOS_RT_MASK | RTO_ONLINK);
+	key.dst		= oldkey->dst;
+	key.src		= oldkey->src;
+	key.tos		= tos & IPTOS_RT_MASK;
+	key.iif		= loopback_dev.ifindex;
+	key.oif		= oldkey->oif;
 #ifdef CONFIG_IP_ROUTE_FWMARK
-	key.fwmark = oldkey->fwmark;
+	key.fwmark	= oldkey->fwmark;
 #endif
-	key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
-	res.fi = NULL;
+	key.scope	= (tos & RTO_ONLINK) ? RT_SCOPE_LINK :
+						RT_SCOPE_UNIVERSE;
+	res.fi		= NULL;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
-	res.r = NULL;
+	res.r		= NULL;
 #endif
 
 	if (oldkey->src) {
-		if (MULTICAST(oldkey->src)
-		    || BADCLASS(oldkey->src)
-		    || ZERONET(oldkey->src))
-			return -EINVAL;
+		err = -EINVAL;
+		if (MULTICAST(oldkey->src) ||
+		    BADCLASS(oldkey->src) ||
+		    ZERONET(oldkey->src))
+			goto out;
 
 		/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
 		dev_out = ip_dev_find(oldkey->src);
 		if (dev_out == NULL)
-			return -EINVAL;
+			goto out;
 
 		/* I removed check for oif == dev_out->oif here.
 		   It was wrong by three reasons:
@@ -1682,23 +1718,27 @@
 	}
 	if (oldkey->oif) {
 		dev_out = dev_get_by_index(oldkey->oif);
+		err = -ENODEV;
 		if (dev_out == NULL)
-			return -ENODEV;
+			goto out;
 		if (__in_dev_get(dev_out) == NULL) {
 			dev_put(dev_out);
-			return -ENODEV;	/* Wrong error code */
+			goto out;	/* Wrong error code */
 		}
 
 		if (LOCAL_MCAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF) {
 			if (!key.src)
-				key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+				key.src = inet_select_addr(dev_out, 0,
+								RT_SCOPE_LINK);
 			goto make_route;
 		}
 		if (!key.src) {
 			if (MULTICAST(oldkey->dst))
-				key.src = inet_select_addr(dev_out, 0, key.scope);
+				key.src = inet_select_addr(dev_out, 0,
+								key.scope);
 			else if (!oldkey->dst)
-				key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
+				key.src = inet_select_addr(dev_out, 0,
+								RT_SCOPE_HOST);
 		}
 	}
 
@@ -1738,13 +1778,15 @@
 			 */
 
 			if (key.src == 0)
-				key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+				key.src = inet_select_addr(dev_out, 0,
+							   RT_SCOPE_LINK);
 			res.type = RTN_UNICAST;
 			goto make_route;
 		}
 		if (dev_out)
 			dev_put(dev_out);
-		return -ENETUNREACH;
+		err = -ENETUNREACH;
+		goto out;
 	}
 	free_res = 1;
 
@@ -1771,7 +1813,7 @@
 		fib_select_multipath(&key, &res);
 	else
 #endif
-	if (res.prefixlen==0 && res.type == RTN_UNICAST && key.oif == 0)
+	if (!res.prefixlen && res.type == RTN_UNICAST && !key.oif)
 		fib_select_default(&key, &res);
 
 	if (!key.src)
@@ -1794,11 +1836,11 @@
 	else if (BADCLASS(key.dst) || ZERONET(key.dst))
 		goto e_inval;
 
-	if (dev_out->flags&IFF_LOOPBACK)
+	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
 	if (res.type == RTN_BROADCAST) {
-		flags |= RTCF_BROADCAST|RTCF_LOCAL;
+		flags |= RTCF_BROADCAST | RTCF_LOCAL;
 		if (res.fi) {
 			fib_info_put(res.fi);
 			res.fi = NULL;
@@ -1806,7 +1848,8 @@
 	} else if (res.type == RTN_MULTICAST) {
 		flags |= RTCF_MULTICAST|RTCF_LOCAL;
 		read_lock(&inetdev_lock);
-		if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), oldkey->dst))
+		if (!__in_dev_get(dev_out) ||
+		    !ip_check_mc(__in_dev_get(dev_out), oldkey->dst))
 			flags &= ~RTCF_LOCAL;
 		read_unlock(&inetdev_lock);
 		/* If multicast route do not exist use
@@ -1847,19 +1890,20 @@
 
 	rth->u.dst.output=ip_output;
 
-	if (flags&RTCF_LOCAL) {
+	if (flags & RTCF_LOCAL) {
 		rth->u.dst.input = ip_local_deliver;
 		rth->rt_spec_dst = key.dst;
 	}
-	if (flags&(RTCF_BROADCAST|RTCF_MULTICAST)) {
+	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
 		rth->rt_spec_dst = key.src;
-		if (flags&RTCF_LOCAL && !(dev_out->flags&IFF_LOOPBACK))
+		if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK))
 			rth->u.dst.output = ip_mc_output;
 #ifdef CONFIG_IP_MROUTE
 		if (res.type == RTN_MULTICAST) {
 			struct in_device *in_dev = in_dev_get(dev_out);
 			if (in_dev) {
-				if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(oldkey->dst)) {
+				if (IN_DEV_MFORWARD(in_dev) &&
+				    !LOCAL_MCAST(oldkey->dst)) {
 					rth->u.dst.input = ip_mr_input;
 					rth->u.dst.output = ip_mc_output;
 				}
@@ -1873,14 +1917,14 @@
 
 	rth->rt_flags = flags;
 
-	hash = rt_hash_code(oldkey->dst, oldkey->src^(oldkey->oif<<5), tos);
+	hash = rt_hash_code(oldkey->dst, oldkey->src ^ (oldkey->oif << 5), tos);
 	err = rt_intern_hash(hash, rth, rp);
 done:
 	if (free_res)
 		fib_res_put(&res);
 	if (dev_out)
 		dev_put(dev_out);
-	return err;
+out:	return err;
 
 e_inval:
 	err = -EINVAL;
@@ -1895,10 +1939,10 @@
 	unsigned hash;
 	struct rtable *rth;
 
-	hash = rt_hash_code(key->dst, key->src^(key->oif<<5), key->tos);
+	hash = rt_hash_code(key->dst, key->src ^ (key->oif << 5), key->tos);
 
 	read_lock_bh(&rt_hash_table[hash].lock);
-	for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
+	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
 		if (rth->key.dst == key->dst &&
 		    rth->key.src == key->src &&
 		    rth->key.iif == 0 &&
@@ -1906,9 +1950,10 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		    rth->key.fwmark == key->fwmark &&
 #endif
-		    !((rth->key.tos^key->tos)&(IPTOS_RT_MASK|RTO_ONLINK)) &&
-		    ((key->tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
-		) {
+		    !((rth->key.tos ^ key->tos) &
+			    (IPTOS_RT_MASK | RTO_ONLINK)) &&
+		    ((key->tos & RTO_TPROXY) ||
+		     !(rth->rt_flags & RTCF_TPROXY))) {
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
@@ -1923,8 +1968,8 @@
 }	
 
 #ifdef CONFIG_RTNETLINK
-
-static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
+static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+			int nowait)
 {
 	struct rtable *rt = (struct rtable*)skb->dst;
 	struct rtmsg *r;
@@ -1934,19 +1979,18 @@
 #ifdef CONFIG_IP_MROUTE
 	struct rtattr *eptr;
 #endif
-
 	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
 	r = NLMSG_DATA(nlh);
 	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
-	r->rtm_family = AF_INET;
-	r->rtm_dst_len = 32;
-	r->rtm_src_len = 0;
-	r->rtm_tos = rt->key.tos;
-	r->rtm_table = RT_TABLE_MAIN;
-	r->rtm_type = rt->rt_type;
-	r->rtm_scope = RT_SCOPE_UNIVERSE;
+	r->rtm_family	 = AF_INET;
+	r->rtm_dst_len	= 32;
+	r->rtm_src_len	= 0;
+	r->rtm_tos	= rt->key.tos;
+	r->rtm_table	= RT_TABLE_MAIN;
+	r->rtm_type	= rt->rt_type;
+	r->rtm_scope	= RT_SCOPE_UNIVERSE;
 	r->rtm_protocol = RTPROT_UNSPEC;
-	r->rtm_flags = (rt->rt_flags&~0xFFFF) | RTM_F_CLONED;
+	r->rtm_flags	= (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
 	if (rt->rt_flags & RTCF_NOTIFY)
 		r->rtm_flags |= RTM_F_NOTIFY;
 	RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);
@@ -1968,17 +2012,15 @@
 		RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);
 	if (rtnetlink_put_metrics(skb, &rt->u.dst.mxlock) < 0)
 		goto rtattr_failure;
-	ci.rta_lastuse = jiffies - rt->u.dst.lastuse;
-	ci.rta_used = rt->u.dst.__use;
-	ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
+	ci.rta_lastuse	= jiffies - rt->u.dst.lastuse;
+	ci.rta_used	= rt->u.dst.__use;
+	ci.rta_clntref	= atomic_read(&rt->u.dst.__refcnt);
 	if (rt->u.dst.expires)
 		ci.rta_expires = rt->u.dst.expires - jiffies;
 	else
 		ci.rta_expires = 0;
-	ci.rta_error = rt->u.dst.error;
-	ci.rta_id = 0;
-	ci.rta_ts = 0;
-	ci.rta_tsage = 0;
+	ci.rta_error	= rt->u.dst.error;
+	ci.rta_id	= ci.rta_ts = ci.rta_tsage = 0;
 	if (rt->peer) {
 		ci.rta_id = rt->peer->ip_id_count;
 		if (rt->peer->tcp_ts_stamp) {
@@ -1994,7 +2036,8 @@
 #ifdef CONFIG_IP_MROUTE
 		u32 dst = rt->rt_dst;
 
-		if (MULTICAST(dst) && !LOCAL_MCAST(dst) && ipv4_devconf.mc_forwarding) {
+		if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
+		    ipv4_devconf.mc_forwarding) {
 			int err = ipmr_get_route(skb, r, nowait);
 			if (err <= 0) {
 				if (!nowait) {
@@ -2009,9 +2052,7 @@
 			}
 		} else
 #endif
-		{
 			RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->key.iif);
-		}
 	}
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -2031,12 +2072,12 @@
 	u32 dst = 0;
 	u32 src = 0;
 	int iif = 0;
-	int err;
+	int err = -ENOBUFS;
 	struct sk_buff *skb;
 
 	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
-	if (skb == NULL)
-		return -ENOBUFS;
+	if (!skb)
+		goto out;
 
 	/* Reserve room for dummy headers, this skb can pass
 	   through good chunk of routing engine.
@@ -2044,20 +2085,20 @@
 	skb->mac.raw = skb->data;
 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
-	if (rta[RTA_SRC-1])
-		memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 4);
-	if (rta[RTA_DST-1])
-		memcpy(&dst, RTA_DATA(rta[RTA_DST-1]), 4);
-	if (rta[RTA_IIF-1])
-		memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
+	if (rta[RTA_SRC - 1])
+		memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);
+	if (rta[RTA_DST - 1])
+		memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);
+	if (rta[RTA_IIF - 1])
+		memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));
 
 	if (iif) {
-		struct net_device *dev;
-		dev = __dev_get_by_index(iif);
+		struct net_device *dev = __dev_get_by_index(iif);
+		err = -ENODEV;
 		if (!dev)
-			return -ENODEV;
-		skb->protocol = __constant_htons(ETH_P_IP);
-		skb->dev = dev;
+			goto out;
+		skb->protocol	= __constant_htons(ETH_P_IP);
+		skb->dev	= dev;
 		local_bh_disable();
 		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
 		local_bh_enable();
@@ -2066,13 +2107,13 @@
 			err = -rt->u.dst.error;
 	} else {
 		int oif = 0;
-		if (rta[RTA_OIF-1])
-			memcpy(&oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));
+		if (rta[RTA_OIF - 1])
+			memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
 		err = ip_route_output(&rt, dst, src, rtm->rtm_tos, oif);
 	}
 	if (err) {
 		kfree_skb(skb);
-		return err;
+		goto out;
 	}
 
 	skb->dst = &rt->u.dst;
@@ -2081,19 +2122,21 @@
 
 	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
 
-	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
-	if (err == 0)
-		return 0;
-	if (err < 0)
-		return -EMSGSIZE;
+	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
+				RTM_NEWROUTE, 0);
+	if (!err)
+		goto out;
+	if (err < 0) {
+		err = -EMSGSIZE;
+		goto out;
+	}
 
 	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
-	if (err < 0)
-		return err;
-	return 0;
+	if (err > 0)
+		err = 0;
+out:	return err;
 }
 
-
 int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 {
 	struct rtable *rt;
@@ -2102,17 +2145,19 @@
 
 	s_h = cb->args[0];
 	s_idx = idx = cb->args[1];
-	for (h=0; h <= rt_hash_mask; h++) {
+	for (h = 0; h <= rt_hash_mask; h++) {
 		if (h < s_h) continue;
 		if (h > s_h)
 			s_idx = 0;
 		read_lock_bh(&rt_hash_table[h].lock);
-		for (rt = rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
+		for (rt = rt_hash_table[h].chain, idx = 0; rt;
+		     rt = rt->u.rt_next, idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					 cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
+					 cb->nlh->nlmsg_seq,
+					 RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
 				read_unlock_bh(&rt_hash_table[h].lock);
 				goto done;
@@ -2135,91 +2180,181 @@
 	rt_cache_flush(0);
 }
 
-
-
 #ifdef CONFIG_SYSCTL
-
 static int flush_delay;
 
-static
-int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
-			      void *buffer, size_t *lenp)
+static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write,
+					struct file *filp, void *buffer,
+					size_t *lenp)
 {
 	if (write) {
 		proc_dointvec(ctl, write, filp, buffer, lenp);
 		rt_cache_flush(flush_delay);
 		return 0;
-	} else
-		return -EINVAL;
+	} 
+
+	return -EINVAL;
 }
 
-static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name, int nlen,
-			 void *oldval, size_t *oldlenp,
-			 void *newval, size_t newlen, 
-			 void **context)
+static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name,
+						int nlen, void *oldval,
+						size_t *oldlenp, void *newval,
+						size_t newlen, void **context)
 {
 	int delay;
 	if (newlen != sizeof(int))
 		return -EINVAL;
-	if (get_user(delay,(int *)newval))
+	if (get_user(delay, (int *)newval))
 		return -EFAULT; 
 	rt_cache_flush(delay); 
 	return 0;
 }
 
 ctl_table ipv4_route_table[] = {
-        {NET_IPV4_ROUTE_FLUSH, "flush",
-         &flush_delay, sizeof(int), 0644, NULL,
-         &ipv4_sysctl_rtcache_flush, &ipv4_sysctl_rtcache_flush_strategy },
-	{NET_IPV4_ROUTE_MIN_DELAY, "min_delay",
-         &ip_rt_min_delay, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_MAX_DELAY, "max_delay",
-         &ip_rt_max_delay, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_GC_THRESH, "gc_thresh",
-         &ipv4_dst_ops.gc_thresh, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_MAX_SIZE, "max_size",
-         &ip_rt_max_size, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_GC_MIN_INTERVAL, "gc_min_interval",
-         &ip_rt_gc_min_interval, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_GC_TIMEOUT, "gc_timeout",
-         &ip_rt_gc_timeout, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_GC_INTERVAL, "gc_interval",
-         &ip_rt_gc_interval, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_REDIRECT_LOAD, "redirect_load",
-         &ip_rt_redirect_load, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_REDIRECT_NUMBER, "redirect_number",
-         &ip_rt_redirect_number, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_REDIRECT_SILENCE, "redirect_silence",
-         &ip_rt_redirect_silence, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_ERROR_COST, "error_cost",
-         &ip_rt_error_cost, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_ERROR_BURST, "error_burst",
-         &ip_rt_error_burst, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_GC_ELASTICITY, "gc_elasticity",
-         &ip_rt_gc_elasticity, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_MTU_EXPIRES, "mtu_expires",
-         &ip_rt_mtu_expires, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_MIN_PMTU, "min_pmtu",
-         &ip_rt_min_pmtu, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_MIN_ADVMSS, "min_adv_mss",
-         &ip_rt_min_advmss, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	 {0}
+        {
+		ctl_name:	NET_IPV4_ROUTE_FLUSH,
+		procname:	"flush",
+		data:		&flush_delay,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&ipv4_sysctl_rtcache_flush,
+		strategy:	&ipv4_sysctl_rtcache_flush_strategy,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MIN_DELAY,
+		procname:	"min_delay",
+		data:		&ip_rt_min_delay,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MAX_DELAY,
+		procname:	"max_delay",
+		data:		&ip_rt_max_delay,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_THRESH,
+		procname:	"gc_thresh",
+		data:		&ipv4_dst_ops.gc_thresh,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MAX_SIZE,
+		procname:	"max_size",
+		data:		&ip_rt_max_size,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_MIN_INTERVAL,
+		procname:	"gc_min_interval",
+		data:		&ip_rt_gc_min_interval,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_TIMEOUT,
+		procname:	"gc_timeout",
+		data:		&ip_rt_gc_timeout,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_INTERVAL,
+		procname:	"gc_interval",
+		data:		&ip_rt_gc_interval,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_REDIRECT_LOAD,
+		procname:	"redirect_load",
+		data:		&ip_rt_redirect_load,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_REDIRECT_NUMBER,
+		procname:	"redirect_number",
+		data:		&ip_rt_redirect_number,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_REDIRECT_SILENCE,
+		procname:	"redirect_silence",
+		data:		&ip_rt_redirect_silence,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_ERROR_COST,
+		procname:	"error_cost",
+		data:		&ip_rt_error_cost,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_ERROR_BURST,
+		procname:	"error_burst",
+		data:		&ip_rt_error_burst,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_ELASTICITY,
+		procname:	"gc_elasticity",
+		data:		&ip_rt_gc_elasticity,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MTU_EXPIRES,
+		procname:	"mtu_expires",
+		data:		&ip_rt_mtu_expires,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MIN_PMTU,
+		procname:	"min_pmtu",
+		data:		&ip_rt_min_pmtu,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MIN_ADVMSS,
+		procname:	"min_adv_mss",
+		data:		&ip_rt_min_advmss,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	 { 0 }
 };
 #endif
 
@@ -2229,13 +2364,13 @@
 static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
 			   int length, int *eof, void *data)
 {
-	*start=buffer;
+	*start = buffer;
 
-	if ((offset&3) || (length&3))
+	if ((offset & 3) || (length & 3))
 		return -EIO;
 
-	if (offset + length >= sizeof(struct ip_rt_acct)*256) {
-		length = sizeof(struct ip_rt_acct)*256 - offset;
+	if (offset + length >= sizeof(struct ip_rt_acct) * 256) {
+		length = sizeof(struct ip_rt_acct) * 256 - offset;
 		*eof = 1;
 	}
 	if (length > 0) {
@@ -2247,9 +2382,9 @@
 #ifdef CONFIG_SMP
 		if (smp_num_cpus > 1 || cpu_logical_map(0) != 0) {
 			int i;
-			int cnt = length/4;
+			int cnt = length / 4;
 
-			for (i=0; i<smp_num_cpus; i++) {
+			for (i = 0; i < smp_num_cpus; i++) {
 				int cpu = cpu_logical_map(i);
 				int k;
 
@@ -2257,9 +2392,9 @@
 					continue;
 
 				src = (u32*)(((u8*)ip_rt_acct) + offset +
-					     cpu*256*sizeof(struct ip_rt_acct));
+					cpu * 256 * sizeof(struct ip_rt_acct));
 
-				for (k=0; k<cnt; k++)
+				for (k = 0; k < cnt; k++)
 					dst[k] += src[k];
 			}
 		}
@@ -2275,13 +2410,13 @@
 	int i, order, goal;
 
 #ifdef CONFIG_NET_CLS_ROUTE
-	for (order=0;
-	     (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*NR_CPUS; order++)
+	for (order = 0;
+	     (PAGE_SIZE << order) < 256 * sizeof(ip_rt_acct) * NR_CPUS; order++)
 		/* NOTHING */;
 	ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);
 	if (!ip_rt_acct)
 		panic("IP: failed to allocate ip_rt_acct\n");
-	memset(ip_rt_acct, 0, PAGE_SIZE<<order);
+	memset(ip_rt_acct, 0, PAGE_SIZE << order);
 #endif
 
 	ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
@@ -2300,7 +2435,7 @@
 	do {
 		rt_hash_mask = (1UL << order) * PAGE_SIZE /
 			sizeof(struct rt_hash_bucket);
-		while (rt_hash_mask & (rt_hash_mask-1))
+		while (rt_hash_mask & (rt_hash_mask - 1))
 			rt_hash_mask--;
 		rt_hash_table = (struct rt_hash_bucket *)
 			__get_free_pages(GFP_ATOMIC, order);
@@ -2311,9 +2446,9 @@
 
 	printk("IP: routing cache hash table of %u buckets, %ldKbytes\n",
 	       rt_hash_mask,
-	       (long) (rt_hash_mask*sizeof(struct rt_hash_bucket))/1024);
+	       (long) (rt_hash_mask * sizeof(struct rt_hash_bucket)) / 1024);
 
-	for (rt_hash_log=0; (1<<rt_hash_log) != rt_hash_mask; rt_hash_log++)
+	for (rt_hash_log = 0; (1 << rt_hash_log) != rt_hash_mask; rt_hash_log++)
 		/* NOTHING */;
 
 	rt_hash_mask--;
@@ -2322,8 +2457,8 @@
 		rt_hash_table[i].chain = NULL;
 	}
 
-	ipv4_dst_ops.gc_thresh = (rt_hash_mask+1);
-	ip_rt_max_size = (rt_hash_mask+1)*16;
+	ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
+	ip_rt_max_size = (rt_hash_mask + 1) * 16;
 
 	devinet_init();
 	ip_fib_init();
@@ -2334,8 +2469,8 @@
 	/* All the timers, started at system startup tend
 	   to synchronize. Perturb it a bit.
 	 */
-	rt_periodic_timer.expires = jiffies + net_random()%ip_rt_gc_interval
-		+ ip_rt_gc_interval;
+	rt_periodic_timer.expires = jiffies + net_random() % ip_rt_gc_interval +
+					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
 	proc_net_create ("rt_cache", 0, rt_cache_get_info);
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c
--- v2.4.4/linux/net/ipv4/syncookies.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/syncookies.c	Wed May 16 10:31:27 2001
@@ -9,7 +9,7 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  * 
- *  $Id: syncookies.c,v 1.13 2001/02/13 01:17:26 davem Exp $
+ *  $Id: syncookies.c,v 1.14 2001/05/05 01:01:55 davem Exp $
  *
  *  Missing: IPv6 support. 
  */
@@ -31,14 +31,14 @@
  * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
  */
 static __u16 const msstab[] = {
-	64-1,
-	256-1,	
-	512-1,
-	536-1,
-	1024-1,	
-	1440-1,
-	1460-1,
-	4312-1,
+	64 - 1,
+	256 - 1,	
+	512 - 1,
+	536 - 1,
+	1024 - 1,	
+	1440 - 1,
+	1460 - 1,
+	4312 - 1,
 	(__u16)-1
 };
 /* The number doesn't include the -1 terminator */
@@ -48,24 +48,23 @@
  * Generate a syncookie.  mssp points to the mss, which is returned
  * rounded down to the value encoded in the cookie.
  */
-__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
-			      __u16 *mssp)
+__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
 {
 	int mssind;
 	const __u16 mss = *mssp;
 
 	tcp_lastsynq_overflow = jiffies;
 	/* XXX sort msstab[] by probability?  Binary search? */
-	for (mssind = 0; mss > msstab[mssind+1]; mssind++)
+	for (mssind = 0; mss > msstab[mssind + 1]; mssind++)
 		;
-	*mssp = msstab[mssind]+1;
+	*mssp = msstab[mssind] + 1;
 
 	NET_INC_STATS_BH(SyncookiesSent);
 
 	return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
 				     skb->h.th->source, skb->h.th->dest,
 				     ntohl(skb->h.th->seq),
-				     jiffies / (HZ*60), mssind);
+				     jiffies / (HZ * 60), mssind);
 }
 
 /* 
@@ -91,16 +90,16 @@
 	mssind = check_tcp_syn_cookie(cookie,
 				      skb->nh.iph->saddr, skb->nh.iph->daddr,
 				      skb->h.th->source, skb->h.th->dest,
-				      seq, jiffies/(HZ*60), COUNTER_TRIES);
+				      seq, jiffies / (HZ * 60), COUNTER_TRIES);
 
-	return mssind < NUM_MSS ? msstab[mssind]+1 : 0;
+	return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
 }
 
 extern struct or_calltable or_ipv4;
 
-static inline struct sock *
-get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req,
-		struct dst_entry *dst)
+static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
+					   struct open_request *req,
+					   struct dst_entry *dst)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct sock *child;
@@ -114,41 +113,40 @@
 	return child;
 }
 
-struct sock *
-cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
+struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+			     struct ip_options *opt)
 {
-	__u32 cookie = ntohl(skb->h.th->ack_seq)-1; 
+	__u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 
+	struct sock *ret = sk;
 	struct open_request *req; 
 	int mss; 
 	struct rtable *rt; 
 	__u8 rcv_wscale;
 
-	if (!sysctl_tcp_syncookies)
-		return sk;
-	if (!skb->h.th->ack)
-		return sk; 
+	if (!sysctl_tcp_syncookies || !skb->h.th->ack)
+		goto out;
 
 	mss = cookie_check(skb, cookie);
-	if (mss == 0) {
+	if (!mss) {
 	 	NET_INC_STATS_BH(SyncookiesFailed);
-		return sk;
+		goto out;
 	}
 
 	NET_INC_STATS_BH(SyncookiesRecv);
 
 	req = tcp_openreq_alloc();
-	if (req == NULL)
-		return NULL;	
-
-	req->rcv_isn = htonl(skb->h.th->seq)-1;
-	req->snt_isn = cookie; 
-	req->mss = mss;
- 	req->rmt_port = skb->h.th->source;
+	ret = NULL;
+	if (!req)
+		goto out;
+
+	req->rcv_isn		= htonl(skb->h.th->seq) - 1;
+	req->snt_isn		= cookie; 
+	req->mss		= mss;
+ 	req->rmt_port		= skb->h.th->source;
 	req->af.v4_req.loc_addr = skb->nh.iph->daddr;
 	req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
-	req->class = &or_ipv4; /* for savety */
-
-	req->af.v4_req.opt = NULL;
+	req->class		= &or_ipv4; /* for savety */
+	req->af.v4_req.opt	= NULL;
 
 	/* We throwed the options of the initial SYN away, so we hope
 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
@@ -166,9 +164,9 @@
 	}
 
 	req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
-	req->wscale_ok = req->sack_ok = 0; 
-	req->expires = 0UL; 
-	req->retrans = 0; 
+	req->wscale_ok	= req->sack_ok = 0; 
+	req->expires	= 0UL; 
+	req->retrans	= 0; 
 	
 	/*
 	 * We need to lookup the route here to get at the correct
@@ -183,18 +181,18 @@
 			    sk->protinfo.af_inet.tos | RTO_CONN,
 			    0)) { 
 		tcp_openreq_free(req);
-		return NULL; 
+		goto out; 
 	}
 
 	/* Try to redo what tcp_v4_send_synack did. */
 	req->window_clamp = rt->u.dst.window;  
-	tcp_select_initial_window(tcp_full_space(sk),req->mss,
+	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 				  &req->rcv_wnd, &req->window_clamp, 
 				  0, &rcv_wscale);
 	/* BTW win scale with syncookies is 0 by definition */
-	req->rcv_wscale = rcv_wscale; 
+	req->rcv_wscale	  = rcv_wscale; 
 
-	return get_cookie_sock(sk, skb, req, &rt->u.dst);
+	ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
+out:	return ret;
 }
-
 #endif
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.4.4/linux/net/ipv4/tcp.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv4/tcp.c	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.202 2001/04/20 20:46:19 davem Exp $
+ * Version:	$Id: tcp.c,v 1.205 2001/05/05 22:25:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1122,8 +1122,16 @@
 
 				/* Time to copy data. We are close to the end! */
 				err = tcp_copy_to_page(sk, from, skb, page, off, copy);
-				if (err)
+				if (err) {
+					/* If this page was new, give it to the
+					 * socket so it does not get leaked.
+					 */
+					if (TCP_PAGE(sk) == NULL) {
+						TCP_PAGE(sk) = page;
+						TCP_OFF(sk) = 0;
+					}
 					goto do_error;
+				}
 
 				/* Update the skb. */
 				if (merge) {
@@ -1182,12 +1190,9 @@
 	return copied;
 
 do_fault:
-	if (skb->len==0) {
-		if (tp->send_head == skb) {
-			tp->send_head = skb->prev;
-			if (tp->send_head == (struct sk_buff*)&sk->write_queue)
-				tp->send_head = NULL;
-		}
+	if (skb->len == 0) {
+		if (tp->send_head == skb)
+			tp->send_head = NULL;
 		__skb_unlink(skb, skb->list);
 		tcp_free_skb(sk, skb);
 	}
@@ -2352,7 +2357,7 @@
 		break;
 	case TCP_LINGER2:
 		val = tp->linger2;
-		if (val > 0)
+		if (val >= 0)
 			val = (val ? : sysctl_tcp_fin_timeout)/HZ;
 		break;
 	case TCP_DEFER_ACCEPT:
diff -u --recursive --new-file v2.4.4/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.4.4/linux/net/ipv4/tcp_input.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv4/tcp_input.c	Thu May 24 15:00:59 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.228 2001/04/20 20:46:19 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.231 2001/05/22 05:15:16 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -2527,12 +2527,12 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int eaten = -1;
 
+	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
+		goto drop;
+
 	th = skb->h.th;
 	__skb_pull(skb, th->doff*4);
 
-        if (skb->len == 0 && !th->fin)
-		goto drop;
-
 	TCP_ECN_accept_cwr(tp, skb);
 
 	if (tp->dsack) {
@@ -3711,8 +3711,12 @@
 		queued = tcp_rcv_synsent_state_process(sk, skb, th, len);
 		if (queued >= 0)
 			return queued;
-		queued = 0;
-		goto step6;
+
+		/* Do step6 onward by hand. */
+		tcp_urg(sk, skb, th);
+		__kfree_skb(skb);
+		tcp_data_snd_check(sk);
+		return 0;
 	}
 
 	if (tcp_fast_parse_options(skb, th, tp) && tp->saw_tstamp &&
@@ -3853,7 +3857,6 @@
 	} else
 		goto discard;
 
-step6:
 	/* step 6: check the URG bit */
 	tcp_urg(sk, skb, th);
 
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/Config.in linux/net/ipv6/Config.in
--- v2.4.4/linux/net/ipv6/Config.in	Mon May 22 09:50:55 2000
+++ linux/net/ipv6/Config.in	Wed May 16 10:31:27 2001
@@ -1,10 +1,6 @@
 #
 # IPv6 configuration
 # 
-bool '    IPv6: enable EUI-64 token format' CONFIG_IPV6_EUI64
-if [ "$CONFIG_IPV6_EUI64" = "y" ]; then
-   bool '      IPv6: disable provider based addresses' CONFIG_IPV6_NO_PB
-fi
 if [ "$CONFIG_NETLINK" = "y" ]; then
    if [ "$CONFIG_RTNETLINK" = "n" ]; then
       bool '    IPv6: routing messages via old netlink' CONFIG_IPV6_NETLINK
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.4.4/linux/net/ipv6/addrconf.c	Fri Apr 27 14:15:01 2001
+++ linux/net/ipv6/addrconf.c	Wed May 16 10:31:27 2001
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: addrconf.c,v 1.62 2001/04/26 19:11:59 davem Exp $
+ *	$Id: addrconf.c,v 1.65 2001/05/03 07:02:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -22,6 +22,10 @@
  *	Andi Kleen			:	kill doube kfree on module
  *						unload.
  *	Maciej W. Rozycki		:	FDDI support
+ *	sekiya@USAGI			:	Don't send too many RS
+ *						packets.
+ *	yoshfuji@USAGI			:       Fixed interval between DAD
+ *						packets.
  */
 
 #include <linux/config.h>
@@ -639,14 +643,8 @@
 	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
 		return;
 
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_inc(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
-	ipv6_dev_mc_inc(dev, &maddr);
-#endif
 }
 
 static void addrconf_leave_solict(struct net_device *dev, struct in6_addr *addr)
@@ -656,18 +654,11 @@
 	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
 		return;
 
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_dec(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
-	ipv6_dev_mc_dec(dev, &maddr);
-#endif
 }
 
 
-#ifdef CONFIG_IPV6_EUI64
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
 	switch (dev->type) {
@@ -702,7 +693,6 @@
 	read_unlock_bh(&idev->lock);
 	return err;
 }
-#endif
 
 /*
  *	Add prefix route.
@@ -876,7 +866,6 @@
 
 		plen = pinfo->prefix_len >> 3;
 
-#ifdef CONFIG_IPV6_EUI64
 		if (pinfo->prefix_len == 64) {
 			memcpy(&addr, &pinfo->prefix, 8);
 			if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
@@ -886,15 +875,6 @@
 			}
 			goto ok;
 		}
-#endif
-#ifndef CONFIG_IPV6_NO_PB
-		if (pinfo->prefix_len == ((sizeof(struct in6_addr) - dev->addr_len)<<3)) {
-			memcpy(&addr, &pinfo->prefix, plen);
-			memcpy(addr.s6_addr + plen, dev->dev_addr,
-			       dev->addr_len);
-			goto ok;
-		}
-#endif
 		printk(KERN_DEBUG "IPv6 addrconf: prefix with wrong length %d\n", pinfo->prefix_len);
 		in6_dev_put(in6_dev);
 		return;
@@ -1224,7 +1204,6 @@
 	if (idev == NULL)
 		return;
 
-#ifdef CONFIG_IPV6_EUI64
 	memset(&addr, 0, sizeof(struct in6_addr));
 
 	addr.s6_addr[0] = 0xFE;
@@ -1232,18 +1211,6 @@
 
 	if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0)
 		addrconf_add_linklocal(idev, &addr);
-#endif
-
-#ifndef CONFIG_IPV6_NO_PB
-	memset(&addr, 0, sizeof(struct in6_addr));
-
-	addr.s6_addr[0] = 0xFE;
-	addr.s6_addr[1] = 0x80;
-
-	memcpy(addr.s6_addr + (sizeof(struct in6_addr) - dev->addr_len), 
-	       dev->dev_addr, dev->addr_len);
-	addrconf_add_linklocal(idev, &addr);
-#endif
 }
 
 static void addrconf_sit_config(struct net_device *dev)
@@ -1509,19 +1476,13 @@
 	}
 
 	ifp->probes--;
-	addrconf_mod_timer(ifp, AC_DAD, ifp->idev->cnf.rtr_solicit_interval);
+	addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time);
 	spin_unlock_bh(&ifp->lock);
 
 	/* send a neighbour solicitation for our addr */
 	memset(&unspec, 0, sizeof(unspec));
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(&ifp->addr, &mcaddr);
+	addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
 	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
-#endif
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(&ifp->addr, &mcaddr);
-	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
-#endif
 
 	in6_ifa_put(ifp);
 }
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.4.4/linux/net/ipv6/ndisc.c	Thu Apr 26 22:17:26 2001
+++ linux/net/ipv6/ndisc.c	Wed May 16 10:31:27 2001
@@ -21,6 +21,7 @@
  *	Janos Farkas			:	kmalloc failure checks
  *	Alexey Kuznetsov		:	state machine reworked
  *						and moved to net/core.
+ *	Pekka Savola			:	RFC2461 validation
  */
 
 /* Set to 3 to get tracing... */
@@ -242,14 +243,8 @@
 
 	if (dev == NULL || __in6_dev_get(dev) == NULL)
 		return -EINVAL;
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_inc(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
-	ipv6_dev_mc_inc(dev, &maddr);
-#endif
 	return 0;
 }
 
@@ -261,14 +256,8 @@
 
 	if (dev == NULL || __in6_dev_get(dev) == NULL)
 		return;
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
-	ipv6_dev_mc_dec(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_dec(dev, &maddr);
-#endif
 }
 
 
@@ -393,6 +382,12 @@
 	int err;
 	int send_llinfo;
 
+	if (saddr == NULL) {
+		if (ipv6_get_lladdr(dev, &addr_buf))
+			return;
+		saddr = &addr_buf;
+	}
+
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 	send_llinfo = dev->addr_len && ipv6_addr_type(saddr) != IPV6_ADDR_ANY;
 	if (send_llinfo)
@@ -405,14 +400,6 @@
 		return;
 	}
 
-	if (saddr == NULL) {
-		if (ipv6_get_lladdr(dev, &addr_buf)) {
-			kfree_skb(skb);
-			return;
-		}
-		saddr = &addr_buf;
-	}
-
 	if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
 		kfree_skb(skb);
 		return;
@@ -550,14 +537,8 @@
 		neigh_app_ns(neigh);
 #endif
 	} else {
-#ifdef CONFIG_IPV6_EUI64
-		addrconf_addr_solict_mult_new(target, &mcaddr);
+		addrconf_addr_solict_mult(target, &mcaddr);
 		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
-#endif
-#ifndef CONFIG_IPV6_NO_PB
-		addrconf_addr_solict_mult_old(target, &mcaddr);
-		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
-#endif
 	}
 }
 
@@ -581,9 +562,9 @@
 
 	optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
 
-	if (skb->nh.ipv6h->hop_limit != 255) {
-		printk(KERN_INFO
-		       "NDISC: fake router advertisment received\n");
+	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP RA: source address is not linklocal\n");
 		return;
 	}
 
@@ -756,13 +737,9 @@
 	int on_link = 0;
 	int optlen;
 
-	if (skb->nh.ipv6h->hop_limit != 255) {
-		printk(KERN_WARNING "NDISC: fake ICMP redirect received\n");
-		return;
-	}
-
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
-		printk(KERN_WARNING "ICMP redirect: source address is not linklocal\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect: source address is not linklocal\n");
 		return;
 	}
 
@@ -770,7 +747,8 @@
 	optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
 
 	if (optlen < 0) {
-		printk(KERN_WARNING "ICMP redirect: packet too small\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect: packet too small\n");
 		return;
 	}
 
@@ -779,14 +757,16 @@
 	dest = target + 1;
 
 	if (ipv6_addr_type(dest) & IPV6_ADDR_MULTICAST) {
-		printk(KERN_WARNING "ICMP redirect for multicast addr\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect for multicast addr\n");
 		return;
 	}
 
 	if (ipv6_addr_cmp(dest, target) == 0) {
 		on_link = 1;
 	} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
-		printk(KERN_WARNING "ICMP redirect: target address is not linklocal\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect: target address is not linklocal\n");
 		return;
 	}
 
@@ -798,6 +778,11 @@
 		return;
 	}
 
+	/* XXX: RFC2461 8.1: 
+	 *	The IP source address of the Redirect MUST be the same as the current
+	 *	first-hop router for the specified ICMP Destination Address.
+	 */
+		
 	/* passed validation tests */
 
 	/*
@@ -974,8 +959,52 @@
 
 	__skb_push(skb, skb->data-skb->h.raw);
 
+	if (skb->nh.ipv6h->hop_limit != 255) {
+		if (net_ratelimit())
+			printk(KERN_WARNING
+			       "ICMP NDISC: fake message with non-255 Hop Limit received: %d\n",
+			       		skb->nh.ipv6h->hop_limit);
+		return 0;
+	}
+
+	if (msg->icmph.icmp6_code != 0) {
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP NDISC: code is not zero\n");
+		return 0;
+	}
+
+	/* XXX: RFC2461 Validation of [all ndisc messages]:
+	 *	All included ndisc options MUST be of non-zero length
+	 *	(Some checking in ndisc_find_option)
+	 */
+
 	switch (msg->icmph.icmp6_type) {
 	case NDISC_NEIGHBOUR_SOLICITATION:
+		/* XXX: import nd_neighbor_solicit from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8+16) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NS: packet too short\n");
+			return 0;
+		}
+
+		if (ipv6_addr_type(&msg->target)&IPV6_ADDR_MULTICAST) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NS: target address is multicast\n");
+			return 0;
+		}
+
+		/* XXX: RFC2461 7.1.1:
+		 * 	If the IP source address is the unspecified address, there
+		 *	MUST NOT be source link-layer address option in the message.
+		 *
+		 *	NOTE! Linux kernel < 2.4.4 broke this rule.
+		 */
+		 	
+		/* XXX: RFC2461 7.1.1:
+		 *	If the IP source address is the unspecified address, the IP
+      		 *	destination address MUST be a solicited-node multicast address.
+		 */
+
 		if ((ifp = ipv6_get_ifaddr(&msg->target, dev)) != NULL) {
 			int addr_type = ipv6_addr_type(saddr);
 
@@ -1010,7 +1039,9 @@
 
 				ipv6_addr_all_nodes(&maddr);
 				ndisc_send_na(dev, NULL, &maddr, &ifp->addr, 
-					      ifp->idev->cnf.forwarding, 0, 1, 1);
+					      ifp->idev->cnf.forwarding, 0, 
+					      ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, 
+					      1);
 				in6_ifa_put(ifp);
 				return 0;
 			}
@@ -1032,7 +1063,9 @@
 
 				if (neigh) {
 					ndisc_send_na(dev, neigh, saddr, &ifp->addr, 
-						      ifp->idev->cnf.forwarding, 1, inc, inc);
+						      ifp->idev->cnf.forwarding, 1, 
+						      ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, 
+						      1);
 					neigh_release(neigh);
 				}
 			}
@@ -1059,7 +1092,7 @@
 
 					if (neigh) {
 						ndisc_send_na(dev, neigh, saddr, &msg->target,
-							      0, 1, 0, inc);
+							      0, 1, 0, 1);
 						neigh_release(neigh);
 					}
 				} else {
@@ -1077,11 +1110,25 @@
 		return 0;
 
 	case NDISC_NEIGHBOUR_ADVERTISEMENT:
+		/* XXX: import nd_neighbor_advert from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 16+8 ) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NA: packet too short\n");
+			return 0;
+		}
+
+		if (ipv6_addr_type(&msg->target)&IPV6_ADDR_MULTICAST) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "NDISC NA: target address is multicast\n");
+			return 0;
+		}
+
 		if ((ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST) &&
 		    msg->icmph.icmp6_solicited) {
 			ND_PRINTK0("NDISC: solicited NA is multicasted\n");
 			return 0;
 		}
+		
 		if ((ifp = ipv6_get_ifaddr(&msg->target, dev))) {
 			if (ifp->flags & IFA_F_TENTATIVE) {
 				addrconf_dad_failure(ifp);
@@ -1092,7 +1139,7 @@
 			   about it. It could be misconfiguration, or
 			   an smart proxy agent tries to help us :-)
 			 */
-			ND_PRINTK0("%s: someone avertise our address!\n",
+			ND_PRINTK0("%s: someone advertises our address!\n",
 				   ifp->idev->dev->name);
 			in6_ifa_put(ifp);
 			return 0;
@@ -1125,12 +1172,35 @@
 		break;
 
 	case NDISC_ROUTER_ADVERTISEMENT:
+		/* XXX: import nd_router_advert from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8+4+4) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP RA: packet too short\n");
+			return 0;
+		}
 		ndisc_router_discovery(skb);
 		break;
 
 	case NDISC_REDIRECT:
+		/* XXX: import nd_redirect from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8+16+16) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP redirect: packet too short\n");
+			return 0;
+		}
 		ndisc_redirect_rcv(skb);
 		break;
+
+	case NDISC_ROUTER_SOLICITATION:
+		/* No RS support in the kernel, but we do some required checks */
+
+		/* XXX: import nd_router_solicit from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP RS: packet too short\n");
+			return 0;
+		}
+		break;
 	};
 
 	return 0;
@@ -1228,7 +1298,7 @@
 
 	if((err = ops->create(ndisc_socket, IPPROTO_ICMPV6)) < 0) {
 		printk(KERN_DEBUG 
-		       "Failed to initializee the NDISC control socket (err %d).\n",
+		       "Failed to initialize the NDISC control socket (err %d).\n",
 		       err);
 		sock_release(ndisc_socket);
 		ndisc_socket = NULL; /* For safety. */
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/netfilter/ip6_tables.c linux/net/ipv6/netfilter/ip6_tables.c
--- v2.4.4/linux/net/ipv6/netfilter/ip6_tables.c	Mon Jan 22 13:30:21 2001
+++ linux/net/ipv6/netfilter/ip6_tables.c	Tue May 15 01:29:35 2001
@@ -1286,6 +1286,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
 		t = find_table_lock(name, &ret, &ip6t_mutex);
 		if (t) {
 			struct ip6t_getinfo info;
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/protocol.c linux/net/ipv6/protocol.c
--- v2.4.4/linux/net/ipv6/protocol.c	Tue Oct 10 10:33:52 2000
+++ linux/net/ipv6/protocol.c	Sat May 19 17:56:43 2001
@@ -5,7 +5,7 @@
  *
  *		PF_INET6 protocol dispatch tables.
  *
- * Version:	$Id: protocol.c,v 1.9 2000/10/03 07:29:01 anton Exp $
+ * Version:	$Id: protocol.c,v 1.10 2001/05/18 02:25:49 davem Exp $
  *
  * Authors:	Pedro Roque	<roque@di.fc.ul.pt>
  *
@@ -15,6 +15,14 @@
  *		2 of the License, or (at your option) any later version.
  */
 
+/*
+ *      Changes:
+ *
+ *      Vince Laviano (vince@cs.stanford.edu)       16 May 2001
+ *      - Removed unused variable 'inet6_protocol_base'
+ *      - Modified inet6_del_protocol() to correctly maintain copy bit.
+ */
+
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -32,7 +40,6 @@
 #include <net/ipv6.h>
 #include <net/protocol.h>
 
-struct inet6_protocol *inet6_protocol_base;
 struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
 
 void inet6_add_protocol(struct inet6_protocol *prot)
@@ -80,6 +87,10 @@
 	}
 
 	p = (struct inet6_protocol *) inet6_protos[hash];
+
+        if (p != NULL && p->protocol == prot->protocol)
+                lp = p;
+
 	while(p != NULL) {
 		/*
 		 * We have to worry if the protocol being deleted is
@@ -91,14 +102,14 @@
 			 * if we are the last one with this protocol and
 			 * there is a previous one, reset its copy bit.
 			 */
-			if (p->copy == 0 && lp != NULL) 
+			if (prot->copy == 0 && lp != NULL)
 				lp->copy = 0;
 			p->next = prot->next;
 			br_write_unlock_bh(BR_NETPROTO_LOCK);
 			return(0);
 		}
 		if (p->next != NULL && p->next->protocol == prot->protocol) 
-			lp = p;
+			lp = p->next;
 
 		p = (struct inet6_protocol *) p->next;
 	}
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.4.4/linux/net/ipv6/route.c	Thu Apr 26 22:17:26 2001
+++ linux/net/ipv6/route.c	Wed May 16 10:31:27 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: route.c,v 1.50 2001/04/25 20:46:35 davem Exp $
+ *	$Id: route.c,v 1.51 2001/05/03 07:02:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -892,12 +892,6 @@
 	if (!(rt->rt6i_flags&RTF_GATEWAY))
 		goto out;
 
-#if !defined(CONFIG_IPV6_EUI64) || defined(CONFIG_IPV6_NO_PB)
-	/*
-	 *	During transition gateways have more than
-	 *	one link local address. Certainly, it is violation
-	 *	of basic principles, but it is temporary.
-	 */
 	/*
 	 *	RFC 1970 specifies that redirects should only be
 	 *	accepted if they come from the nexthop to the target.
@@ -929,7 +923,6 @@
 	}
 
 source_ok:
-#endif
 
 	/*
 	 *	We have finally decided to accept it.
diff -u --recursive --new-file v2.4.4/linux/net/ipv6/sit.c linux/net/ipv6/sit.c
--- v2.4.4/linux/net/ipv6/sit.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv6/sit.c	Thu May 24 15:00:59 2001
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: sit.c,v 1.50 2001/04/19 22:32:55 davem Exp $
+ *	$Id: sit.c,v 1.51 2001/05/17 04:12:18 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -182,6 +182,7 @@
 	dev->init = ipip6_tunnel_init;
 	dev->features |= NETIF_F_DYNALLOC;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	nt->parms.name[IFNAMSIZ-1] = '\0';
 	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
diff -u --recursive --new-file v2.4.4/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.4.4/linux/net/ipx/af_ipx.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipx/af_ipx.c	Wed May 16 10:31:27 2001
@@ -71,6 +71,8 @@
  *			sysctl for ipx_pprop_broacasting, fix the ipx sysctl
  *			handling, making it dynamic, some cleanups, thanks to
  *			Petr Vandrovec for review and good suggestions. (acme)
+ *	Revision 047:	Cleanups, CodingStyle changes, move the ncp connection
+ *			hack out of line (acme)
  *
  *	Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *	pair. Also, now usage count is managed this way
@@ -116,8 +118,13 @@
 #include <linux/init.h>
 #include <linux/if_arp.h>
 
+#ifdef CONFIG_SYSCTL
 extern void ipx_register_sysctl(void);
 extern void ipx_unregister_sysctl(void);
+#else
+#define ipx_register_sysctl()
+#define ipx_unregister_sysctl()
+#endif
 
 /* Configuration Variables */
 static unsigned char ipxcfg_max_hops = 16;
@@ -175,16 +182,12 @@
 	ipx_config_data	vals;
 
 	vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
-	vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
+	vals.ipxcfg_auto_select_primary	   = ipxcfg_auto_select_primary;
 
 	return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
 }
 
-/**************************************************************************\
-*                                                                          *
-* Handlers for the socket list.                                            *
-*                                                                          *
-\**************************************************************************/
+/* Handlers for the socket list. */
 
 static inline void ipxitf_hold(ipx_interface *intrfc)
 {
@@ -220,26 +223,28 @@
 	/* Determine interface with which socket is associated */
 	intrfc = sk->protinfo.af_ipx.intrfc;
 	if (!intrfc)
-		return;
+		goto out;
 
 	ipxitf_hold(intrfc);
 	spin_lock_bh(&intrfc->if_sklist_lock);
 	s = intrfc->if_sklist;
 	if (s == sk) {
 		intrfc->if_sklist = s->next;
-		goto out;
+		goto out_unlock;
 	}
 
 	while (s && s->next) {
 		if (s->next == sk) {
 			s->next = sk->next;
-			goto out;
+			goto out_unlock;
 		}
 		s = s->next;
 	}
-out:	spin_unlock_bh(&intrfc->if_sklist_lock);
+out_unlock:
+	spin_unlock_bh(&intrfc->if_sklist_lock);
 	sock_put(sk);
 	ipxitf_put(intrfc);
+out:	return;
 }
 
 static void ipx_destroy_socket(struct sock *sk)
@@ -267,21 +272,16 @@
 
 static void ipxitf_clear_primary_net(void)
 {
-	if (ipxcfg_auto_select_primary && ipx_interfaces)
-		ipx_primary_net = ipx_interfaces;
-	else
-		ipx_primary_net = NULL;
+	ipx_primary_net = ipxcfg_auto_select_primary ? ipx_interfaces : NULL;
 }
 
 static ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
 						unsigned short datalink)
 {
-	ipx_interface *i;
+	ipx_interface *i = ipx_interfaces;
 
-	for (i = ipx_interfaces;
-		i && (i->if_dev != dev || i->if_dlink_type != datalink);
-		i = i->if_next)
-		;
+	while (i && (i->if_dev != dev || i->if_dlink_type != datalink))
+		i = i->if_next;
 
 	return i;
 }
@@ -320,8 +320,6 @@
 /* Sockets are bound to a particular IPX interface. */
 static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk)
 {
-	struct sock *s;
-
 	ipxitf_hold(intrfc);
 	sock_hold(sk);
 	spin_lock_bh(&intrfc->if_sklist_lock);
@@ -330,8 +328,9 @@
 	if (!intrfc->if_sklist)
 		intrfc->if_sklist = sk;
 	else {
-		for (s = intrfc->if_sklist; s->next; s = s->next)
-			;
+		struct sock *s = intrfc->if_sklist;
+		while (s->next)
+			s = s->next;
 		s->next = sk;
 	}
 	spin_unlock_bh(&intrfc->if_sklist_lock);
@@ -342,12 +341,11 @@
 static struct sock *__ipxitf_find_socket(ipx_interface *intrfc,
 					 unsigned short port)
 {
-	struct sock *s;
+	struct sock *s = intrfc->if_sklist;
+
+	while (s && s->protinfo.af_ipx.port != port)
+	     s = s->next;
 
-	for (s = intrfc->if_sklist;
-	     s && s->protinfo.af_ipx.port != port;
-	     s = s->next)
-		;
 	return s;
 }
 
@@ -393,7 +391,6 @@
 
 static void __ipxitf_down(ipx_interface *intrfc)
 {
-	ipx_interface *i;
 	struct sock *s, *t;
 
 	/* Delete all routes associated with this interface */
@@ -401,12 +398,12 @@
 
 	spin_lock_bh(&intrfc->if_sklist_lock);
 	/* error sockets */
-	for (s = intrfc->if_sklist; s; ) {
+	for (s = intrfc->if_sklist; s;) {
 		s->err = ENOLINK;
 		s->error_report(s);
 		s->protinfo.af_ipx.intrfc = NULL;
-		s->protinfo.af_ipx.port = 0;
-		s->zapped=1;	/* Indicates it is no longer bound */
+		s->protinfo.af_ipx.port	  = 0;
+		s->zapped = 1;	/* Indicates it is no longer bound */
 		t = s;
 		s = s->next;
 		t->next = NULL;
@@ -418,10 +415,9 @@
 	if (intrfc == ipx_interfaces)
 		ipx_interfaces = intrfc->if_next;
 	else {
-		for (i = ipx_interfaces;
-		     i && i->if_next != intrfc;
-		     i = i->if_next)
-			;
+		ipx_interface *i = ipx_interfaces;
+		while (i && i->if_next != intrfc)
+		     i = i->if_next;
 		if (i && i->if_next == intrfc)
 			i->if_next = intrfc->if_next;
 	}
@@ -482,15 +478,15 @@
 /* caller must hold a reference to intrfc */
 
 #ifdef CONFIG_IPX_INTERN
-static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
+static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb,
+				int copy)
 {
 	struct ipxhdr *ipx = skb->nh.ipxh;
+	int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
+				   IPX_NODE_LEN);
 	struct sock *s;
 	int ret;
 
-	int is_broadcast = (memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
-				   IPX_NODE_LEN) == 0);
-
 	spin_lock_bh(&intrfc->if_sklist_lock);
 	s = intrfc->if_sklist;
 
@@ -529,6 +525,40 @@
 	return ret;
 }
 #else
+static struct sock *ncp_connection_hack(ipx_interface *intrfc,
+					struct ipxhdr *ipx)
+{
+	/* The packet's target is a NCP connection handler. We want to hand it
+	 * to the correct socket directly within the kernel, so that the
+	 * mars_nwe packet distribution process does not have to do it. Here we
+	 * only care about NCP and BURST packets.
+	 *
+	 * You might call this a hack, but believe me, you do not want a
+	 * complete NCP layer in the kernel, and this is VERY fast as well. */
+	struct sock *sk = NULL;
+ 	int connection = 0;
+	u8 *ncphdr = (u8 *)(ipx + 1);
+
+ 	if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */
+		connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3);
+	else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */
+		connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8);
+
+	if (connection) {
+		/* Now we have to look for a special NCP connection handling
+		 * socket. Only these sockets have ipx_ncp_conn != 0, set by
+		 * SIOCIPXNCPCONN. */
+		spin_lock_bh(&intrfc->if_sklist_lock);
+		for (sk = intrfc->if_sklist;
+		     sk && sk->protinfo.af_ipx.ipx_ncp_conn != connection;
+		     sk = sk->next);
+		if (sk)
+			sock_hold(sk);
+		spin_unlock_bh(&intrfc->if_sklist_lock);
+	}
+	return sk;
+}
+
 static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb,
 				int copy)
 {
@@ -537,43 +567,8 @@
 	struct sk_buff *skb1 = NULL, *skb2 = NULL;
 	int ret;
 
-	if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) {
-		/* 
-	 	 * The packet's target is a NCP connection handler. We want to
-	 	 * hand it to the correct socket directly within the kernel,
-	 	 * so that the mars_nwe packet distribution process
-	 	 * does not have to do it. Here we only care about NCP and
-	 	 * BURST packets.
-	 	 * You might call this a hack, but believe me, you do not
-	 	 * want a complete NCP layer in the kernel, and this is
-	 	 * VERY fast as well.
-	 	 */
-	 	int connection = 0;
-		u8 *ncphdr = (u8 *)(ipx + 1);
-
-	 	if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22)
-	  		/* The packet is a NCP request */
-			connection = (((int) *(ncphdr + 5)) << 8) |
-					(int) *(ncphdr+3);
-		else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77)
-			/* The packet is a BURST packet */
-			connection = (((int) *(ncphdr+9)) << 8) |
-					(int) *(ncphdr+8);
-
-        	if (connection) {
-			/* Now we have to look for a special NCP connection
-			 * handling socket. Only these sockets have
-			 * ipx_ncp_conn != 0, set by SIOCIPXNCPCONN. */
-			spin_lock_bh(&intrfc->if_sklist_lock);
-			for (sock1 = intrfc->if_sklist;
-			     sock1 &&
-			     sock1->protinfo.af_ipx.ipx_ncp_conn != connection;
-			     sock1 = sock1->next);
-			if (sock1)
-				sock_hold(sock1);
-			spin_unlock_bh(&intrfc->if_sklist_lock);
-		}
-        }
+	if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451)
+		sock1 = ncp_connection_hack(intrfc, ipx);
         if (!sock1)
 		/* No special socket found, forward the packet the normal way */
 		sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
@@ -587,22 +582,15 @@
 	 */
 
 	if (ipx_primary_net && intrfc != ipx_primary_net) {
-		switch (ntohs(ipx->ipx_dest.sock)) {
-			case 0x452:
-			case 0x453:
-			case 0x456:
-				/*
-				 * The appropriate thing to do here is to
-				 * dup the packet and route to the primary net
-				 * interface via ipxitf_send; however, we'll 
-				 * cheat and just demux it here.
-				 */
-				sock2 = ipxitf_find_socket(ipx_primary_net,
-					ipx->ipx_dest.sock);
-				break;
-			default:
-				break;
-		}
+		const int dsock = ntohs(ipx->ipx_dest.sock);
+
+		if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456)
+			/* The appropriate thing to do here is to dup the
+			 * packet and route to the primary net interface via
+			 * ipxitf_send; however, we'll cheat and just demux it
+			 * here. */
+			sock2 = ipxitf_find_socket(ipx_primary_net,
+							ipx->ipx_dest.sock);
 	}
 
 	/*
@@ -673,8 +661,7 @@
 	skb2 = alloc_skb(len, GFP_ATOMIC);
 	if (skb2) {
 		skb_reserve(skb2, out_offset);
-		skb2->nh.raw =
-		skb2->h.raw = skb_put(skb2,skb->len);
+		skb2->nh.raw = skb2->h.raw = skb_put(skb2, skb->len);
 		memcpy(skb2->h.raw, skb->h.raw, skb->len);
 		memcpy(skb2->cb, skb->cb, sizeof(skb->cb));
 	}
@@ -742,7 +729,7 @@
 				skb_orphan(skb);
 			ipxitf_demux_socket(intrfc, skb, send_to_wire);
 			if (!send_to_wire)
-				return 0;
+				goto out;
 		}
 	}
 
@@ -758,14 +745,14 @@
 		 */
 		skb = skb_unshare(skb, GFP_ATOMIC);
 		if (!skb)
-			return 0;
+			goto out;
 		if (++ipx->ipx_tctrl > ipxcfg_max_hops)
 			send_to_wire = 0;
 	}
 
 	if (!send_to_wire) {
 		kfree_skb(skb);
-		return 0;
+		goto out;
 	}
 
 	/* Determine the appropriate hardware address */
@@ -778,16 +765,16 @@
 	/* Make any compensation for differing physical/data link size */
 	skb = ipxitf_adjust_skbuff(intrfc, skb);
 	if (!skb)
-		return 0;
+		goto out;
 
 	/* set up data link and physical headers */
-	skb->dev = dev;
-	skb->protocol = htons(ETH_P_IPX);
+	skb->dev	= dev;
+	skb->protocol	= __constant_htons(ETH_P_IPX);
 	dl->datalink_header(dl, skb, dest_node);
 
 	/* Send it out */
 	dev_queue_xmit(skb);
-	return 0;
+out:	return 0;
 }
 
 static int ipxrtr_add_route(__u32, ipx_interface *, unsigned char *);
@@ -976,15 +963,14 @@
 
 static void ipxitf_insert(ipx_interface *intrfc)
 {
-	ipx_interface *i;
-
 	intrfc->if_next = NULL;
 	spin_lock_bh(&ipx_interfaces_lock);
 	if (!ipx_interfaces)
 		ipx_interfaces = intrfc;
 	else {
-		for (i = ipx_interfaces; i->if_next; i = i->if_next)
-			;
+		ipx_interface *i = ipx_interfaces;
+		while (i->if_next)
+			i = i->if_next;
 		i->if_next = intrfc;
 	}
 	spin_unlock_bh(&ipx_interfaces_lock);
@@ -998,7 +984,7 @@
 				   struct datalink_proto *dlink,
 				   unsigned char internal, int ipx_offset)
 {
-	ipx_interface *intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
+	ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC);
 
 	if (intrfc) {
 		intrfc->if_dev		= dev;
@@ -1020,23 +1006,26 @@
 static int ipxitf_create_internal(ipx_interface_definition *idef)
 {
 	ipx_interface *intrfc;
-	int ret;
+	int ret = -EEXIST;
 
 	/* Only one primary network allowed */
 	if (ipx_primary_net)
-		return -EEXIST;
+		goto out;
 
 	/* Must have a valid network number */
+	ret = -EADDRNOTAVAIL;
 	if (!idef->ipx_network)
-		return -EADDRNOTAVAIL;
+		goto out;
 	intrfc = ipxitf_find_using_net(idef->ipx_network);
+	ret = -EADDRINUSE;
 	if (intrfc) {
 		ipxitf_put(intrfc);
-		return -EADDRINUSE;
+		goto out;
 	}
 	intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0);
+	ret = -EAGAIN;
 	if (!intrfc)
-		return -EAGAIN;
+		goto out;
 	memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
 	ipx_internal_net = ipx_primary_net = intrfc;
 	ipxitf_hold(intrfc);
@@ -1044,26 +1033,29 @@
 
 	ret = ipxitf_add_local_route(intrfc);
 	ipxitf_put(intrfc);
-	return ret;
+out:	return ret;
 }
 
 static int ipx_map_frame_type(unsigned char type)
 {
+	int ret = 0;
+
 	switch (type) {
 		case IPX_FRAME_ETHERII:
-			return htons(ETH_P_IPX);
-
+			ret = __constant_htons(ETH_P_IPX);
+			break;
 		case IPX_FRAME_8022:
-			return htons(ETH_P_802_2);
-
+			ret = __constant_htons(ETH_P_802_2);
+			break;
 		case IPX_FRAME_SNAP:
-			return htons(ETH_P_SNAP);
-
+			ret = __constant_htons(ETH_P_SNAP);
+			break;
 		case IPX_FRAME_8023:
-			return htons(ETH_P_802_3);
+			ret = __constant_htons(ETH_P_802_3);
+			break;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int ipxitf_create(ipx_interface_definition *idef)
@@ -1074,39 +1066,42 @@
 	ipx_interface *intrfc;
 	int err;
 
-	if (idef->ipx_special == IPX_INTERNAL)
-		return ipxitf_create_internal(idef);
+	if (idef->ipx_special == IPX_INTERNAL) {
+		err = ipxitf_create_internal(idef);
+		goto out;
+	}
 
+	err = -EEXIST;
 	if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net)
-		return -EEXIST;
+		goto out;
 
 	intrfc = ipxitf_find_using_net(idef->ipx_network);
+	err = -EADDRINUSE;
 	if (idef->ipx_network && intrfc) {
 		ipxitf_put(intrfc);
-		return -EADDRINUSE;
+		goto out;
 	}
 
 	if (intrfc)
 		ipxitf_put(intrfc);
 
 	dev = dev_get_by_name(idef->ipx_device);
+	err = -ENODEV;
 	if (!dev)
-		return -ENODEV;
+		goto out;
 
 	switch (idef->ipx_dlink_type) {
 		case IPX_FRAME_TR_8022:
 			printk(KERN_WARNING "IPX frame type 802.2TR is "
 				"obsolete Use 802.2 instead.\n");
 			/* fall through */
-
 		case IPX_FRAME_8022:
-			dlink_type 	= htons(ETH_P_802_2);
+			dlink_type 	= __constant_htons(ETH_P_802_2);
 			datalink 	= p8022_datalink;
 			break;
-
 		case IPX_FRAME_ETHERII:
 			if (dev->type != ARPHRD_IEEE802) {
-				dlink_type 	= htons(ETH_P_IPX);
+				dlink_type 	= __constant_htons(ETH_P_IPX);
 				datalink 	= pEII_datalink;
 				break;
 			} else 
@@ -1114,17 +1109,14 @@
 					"over token-ring is obsolete. Use SNAP "
 					"instead.\n");
 			/* fall through */
-
 		case IPX_FRAME_SNAP:
-			dlink_type 	= htons(ETH_P_SNAP);
+			dlink_type 	= __constant_htons(ETH_P_SNAP);
 			datalink 	= pSNAP_datalink;
 			break;
-
 		case IPX_FRAME_8023:
-			dlink_type 	= htons(ETH_P_802_3);
+			dlink_type 	= __constant_htons(ETH_P_802_3);
 			datalink 	= p8023_datalink;
 			break;
-
 		case IPX_FRAME_NONE:
 		default:
 			err = -EPROTONOSUPPORT;
@@ -1155,7 +1147,7 @@
 		if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000",
 			    IPX_NODE_LEN)) {
 			memset(intrfc->if_node, 0, IPX_NODE_LEN);
-			memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
+			memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len,
 				dev->dev_addr, dev->addr_len);
 		} else
 			memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
@@ -1172,10 +1164,10 @@
 	err = ipxitf_add_local_route(intrfc);
 out_intrfc:
 	ipxitf_put(intrfc);
-	return err;
+	goto out;
 out_dev:
 	dev_put(dev);
-	return err;
+out:	return err;
 }
 
 static int ipxitf_delete(ipx_interface_definition *idef)
@@ -1196,23 +1188,22 @@
 	}
 
 	dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
-	if (!dlink_type) {
-		ret = -EPROTONOSUPPORT;
+	ret = -EPROTONOSUPPORT;
+	if (!dlink_type)
 		goto out;
-	}
 
 	dev = __dev_get_by_name(idef->ipx_device);
-	if (!dev) {
-		ret = -ENODEV;
+	ret = -ENODEV;
+	if (!dev)
 		goto out;
-	}
 
 	intrfc = __ipxitf_find_using_phys(dev, dlink_type);
-	if (intrfc)
-		__ipxitf_put(intrfc);
-	else
-		ret = -EINVAL;
+	ret = -EINVAL;
+	if (!intrfc)
+		goto out;
+	__ipxitf_put(intrfc);
 
+	ret = 0;
 out:	spin_unlock_bh(&ipx_interfaces_lock);
 	return ret;
 }
@@ -1270,7 +1261,7 @@
 static int ipxitf_ioctl(unsigned int cmd, void *arg)
 {
 	struct ifreq ifr;
-	int err = 0, val;
+	int val;
 
 	switch (cmd) {
 		case SIOCSIFADDR: {
@@ -1285,7 +1276,8 @@
 				return -EINVAL;
 
 			f.ipx_network = sipx->sipx_network;
-			memcpy(f.ipx_device,ifr.ifr_name,sizeof(f.ipx_device));
+			memcpy(f.ipx_device, ifr.ifr_name,
+				sizeof(f.ipx_device));
 			memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN);
 			f.ipx_dlink_type = sipx->sipx_type;
 			f.ipx_special = sipx->sipx_special;
@@ -1296,8 +1288,8 @@
 				return ipxitf_create(&f);
 		}
 
-		case SIOCGIFADDR: 
-		{
+		case SIOCGIFADDR: {
+			int err = 0;
 			struct sockaddr_ipx *sipx;
 			ipx_interface *ipxif;
 			struct net_device *dev;
@@ -1344,11 +1336,7 @@
 	return 0;
 }
 
-/**************************************************************************\
-*                                                                          *
-* Routing tables for the IPX socket layer.                                 *
-*                                                                          *
-\**************************************************************************/
+/* Routing tables for the IPX socket layer. */
 
 static inline void ipxrtr_hold(ipx_route *rt)
 {
@@ -1377,7 +1365,8 @@
 
 /* caller must hold a reference to intrfc */
 
-static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char *node)
+static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc,
+				unsigned char *node)
 {
 	ipx_route *rt;
 	int ret;
@@ -1385,7 +1374,7 @@
 	/* Get a route structure; either existing or create */
 	rt = ipxrtr_lookup(network);
 	if (!rt) {
-		rt = kmalloc(sizeof(ipx_route),GFP_ATOMIC);
+		rt = kmalloc(sizeof(ipx_route), GFP_ATOMIC);
 		ret = -EAGAIN;
 		if (!rt)
 			goto out;
@@ -1436,15 +1425,15 @@
 static int ipxrtr_create(ipx_route_definition *rd)
 {
 	ipx_interface *intrfc;
-	int ret;
+	int ret = -ENETUNREACH;
 
 	/* Find the appropriate interface */
 	intrfc = ipxitf_find_using_net(rd->ipx_router_network);
 	if (!intrfc)
-		return -ENETUNREACH;
+		goto out;
 	ret = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
 	ipxitf_put(intrfc);
-	return ret;
+out:	return ret;
 }
 
 static int ipxrtr_delete(long net)
@@ -1481,7 +1470,7 @@
 /* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
 /* This functions should *not* mess with packet contents */
 
-static __u16 ipx_cksum(struct ipxhdr *packet,int length) 
+static __u16 ipx_cksum(struct ipxhdr *packet, int length) 
 {
 	/* 
 	 *	NOTE: sum is a net byte order quantity, which optimizes the 
@@ -1500,7 +1489,7 @@
 		sum += *p++;
 
 	/* Add on the last part word if it exists */
-	if (packet->ipx_pktsize & htons(1))
+	if (packet->ipx_pktsize & __constant_htons(1))
 		sum += ntohs(0xff00) & *p;
 
 	/* Do final fixup */
@@ -1516,7 +1505,8 @@
 /*
  * Route an outgoing frame from a socket.
  */
-static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, struct iovec *iov, int len, int noblock)
+static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
+				struct iovec *iov, int len, int noblock)
 {
 	struct sk_buff *skb;
 	ipx_interface *intrfc;
@@ -1546,15 +1536,15 @@
 	if (!skb)
 		goto out_put;
 
-	skb_reserve(skb,ipx_offset);
+	skb_reserve(skb, ipx_offset);
 	skb->sk = sk;
 
 	/* Fill in IPX header */
 	ipx = (struct ipxhdr *)skb_put(skb, sizeof(struct ipxhdr));
-	ipx->ipx_pktsize= htons(len + sizeof(struct ipxhdr));
+	ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr));
 	IPX_SKB_CB(skb)->ipx_tctrl = 0;
-	ipx->ipx_type 	= usipx->sipx_type;
-	skb->h.raw 	= (void *)skb->nh.ipxh = ipx;
+	ipx->ipx_type 	 = usipx->sipx_type;
+	skb->h.raw 	 = (void *)skb->nh.ipxh = ipx;
 
 	IPX_SKB_CB(skb)->last_hop.index = -1;
 #ifdef CONFIG_IPX_INTERN
@@ -1572,13 +1562,12 @@
 		memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
 	}
 #endif	/* CONFIG_IPX_INTERN */
-
-	ipx->ipx_source.sock 	= sk->protinfo.af_ipx.port;
+	ipx->ipx_source.sock		= sk->protinfo.af_ipx.port;
 	IPX_SKB_CB(skb)->ipx_dest_net	= usipx->sipx_network;
-	memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
-	ipx->ipx_dest.sock	= usipx->sipx_port;
+	memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);
+	ipx->ipx_dest.sock		= usipx->sipx_port;
 
-	err = memcpy_fromiovec(skb_put(skb,len),iov,len);
+	err = memcpy_fromiovec(skb_put(skb, len), iov, len);
 	if (err) {
 		kfree_skb(skb);
 		goto out_put;
@@ -1586,7 +1575,7 @@
 
 	/* Apply checksum. Not allowed on 802.3 links. */
 	if (sk->no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
-		ipx->ipx_checksum=0xFFFF;
+		ipx->ipx_checksum = 0xFFFF;
 	else
 		ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
 
@@ -1612,7 +1601,7 @@
 	}
 
 	ipxitf_hold(r->ir_intrfc);
-	ipxitf_send(r->ir_intrfc, skb, (r->ir_routed) ?
+	ipxitf_send(r->ir_intrfc, skb, r->ir_routed ?
 			r->ir_router_node : ipx->ipx_dest.node);
 	ipxitf_put(r->ir_intrfc);
 	ipxrtr_put(r);
@@ -1626,61 +1615,51 @@
 static int ipxrtr_ioctl(unsigned int cmd, void *arg)
 {
 	struct rtentry rt;	/* Use these to behave like 'other' stacks */
-	struct sockaddr_ipx *sg,*st;
-	int err;
+	struct sockaddr_ipx *sg, *st;
+	int ret = -EFAULT;
 
-	err = copy_from_user(&rt,arg,sizeof(rt));
-	if (err)
-		return -EFAULT;
+	if (copy_from_user(&rt, arg, sizeof(rt)))
+		goto out;
 
 	sg = (struct sockaddr_ipx *)&rt.rt_gateway;
 	st = (struct sockaddr_ipx *)&rt.rt_dst;
 
-	if (!(rt.rt_flags & RTF_GATEWAY))
-		return -EINVAL;	/* Direct routes are fixed */
-	if (sg->sipx_family != AF_IPX)
-		return -EINVAL;
-	if (st->sipx_family != AF_IPX)
-		return -EINVAL;
+	ret = -EINVAL;
+	if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */
+	    sg->sipx_family != AF_IPX ||
+	    st->sipx_family != AF_IPX)
+		goto out;
 
 	switch (cmd) {
 		case SIOCDELRT:
-			return ipxrtr_delete(st->sipx_network);
-
-		case SIOCADDRT:
-		{
+			ret = ipxrtr_delete(st->sipx_network);
+			break;
+		case SIOCADDRT: {
 			struct ipx_route_definition f;
-			f.ipx_network=st->sipx_network;
-			f.ipx_router_network=sg->sipx_network;
+			f.ipx_network		= st->sipx_network;
+			f.ipx_router_network	= sg->sipx_network;
 			memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
-			return ipxrtr_create(&f);
+			ret = ipxrtr_create(&f);
+			break;
 		}
 	}
 
-	return -EINVAL;
+out:	return ret;
 }
 
 static const char *ipx_frame_name(unsigned short frame)
 {
-	switch (ntohs(frame)) {
-		case ETH_P_IPX:
-			return "EtherII";
-
-		case ETH_P_802_2:
-			return "802.2";
-
-		case ETH_P_SNAP:
-			return "SNAP";
-
-		case ETH_P_802_3:
-			return "802.3";
+	char* ret = "None";
 
-		case ETH_P_TR_802_2:
-			return "802.2TR";
-
-		default:
-			return "None";
+	switch (ntohs(frame)) {
+		case ETH_P_IPX:		ret = "EtherII";	break;
+		case ETH_P_802_2:	ret = "802.2";		break;
+		case ETH_P_SNAP:	ret = "SNAP";		break;
+		case ETH_P_802_3:	ret = "802.3";		break;
+		case ETH_P_TR_802_2:	ret = "802.2TR";	break;
 	}
+
+	return ret;
 }
 
 static const char *ipx_device_name(ipx_interface *intrfc)
@@ -1699,27 +1678,28 @@
 
 	/* Theory.. Keep printing in the same place until we pass offset */
 
-	len += sprintf(buffer,"%-11s%-15s%-9s%-11s%s", "Network",
+	len += sprintf(buffer, "%-11s%-15s%-9s%-11s%s", "Network",
 		"Node_Address", "Primary", "Device", "Frame_Type");
 #ifdef IPX_REFCNT_DEBUG
 	len += sprintf(buffer + len, "  refcnt");
 #endif
-	strcat(buffer+len++, "\n");
+	strcat(buffer + len++, "\n");
 	spin_lock_bh(&ipx_interfaces_lock);
 	for (i = ipx_interfaces; i; i = i->if_next) {
-		len += sprintf(buffer+len, "%08lX   ", (long unsigned int)ntohl(i->if_netnum));
-		len += sprintf(buffer+len,"%02X%02X%02X%02X%02X%02X   ",
+		len += sprintf(buffer + len, "%08lX   ",
+				(long unsigned int) ntohl(i->if_netnum));
+		len += sprintf(buffer + len, "%02X%02X%02X%02X%02X%02X   ",
 				i->if_node[0], i->if_node[1], i->if_node[2],
 				i->if_node[3], i->if_node[4], i->if_node[5]);
-		len += sprintf(buffer+len, "%-9s", i == ipx_primary_net ?
+		len += sprintf(buffer + len, "%-9s", i == ipx_primary_net ?
 			"Yes" : "No");
-		len += sprintf(buffer+len, "%-11s", ipx_device_name(i));
-		len += sprintf(buffer+len, "%-9s",
+		len += sprintf(buffer + len, "%-11s", ipx_device_name(i));
+		len += sprintf(buffer + len, "%-9s",
 			ipx_frame_name(i->if_dlink_type));
 #ifdef IPX_REFCNT_DEBUG
-		len += sprintf(buffer+len,"%6d",atomic_read(&i->refcnt));
+		len += sprintf(buffer + len, "%6d", atomic_read(&i->refcnt));
 #endif
-		strcat(buffer+len++, "\n");
+		strcat(buffer + len++, "\n");
 		/* Are we still dumping unwanted data then discard the record */
 		pos = begin + len;
 
@@ -1751,9 +1731,9 @@
 	/* Theory.. Keep printing in the same place until we pass offset */
 
 #ifdef CONFIG_IPX_INTERN
-	len += sprintf(buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+	len += sprintf(buffer, "%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
 #else
-	len += sprintf(buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+	len += sprintf(buffer, "%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
 #endif	/* CONFIG_IPX_INTERN */
 			"Remote_Address", "Tx_Queue", "Rx_Queue",
 			"State", "Uid");
@@ -1764,7 +1744,7 @@
 		spin_lock_bh(&i->if_sklist_lock);
 		for (s = i->if_sklist; s; s = s->next) {
 #ifdef CONFIG_IPX_INTERN
-			len += sprintf(buffer+len,
+			len += sprintf(buffer + len,
 				       "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
                                        (unsigned long) htonl(s->protinfo.af_ipx.intrfc->if_netnum),
 				       s->protinfo.af_ipx.node[0],
@@ -1775,15 +1755,15 @@
 				       s->protinfo.af_ipx.node[5],
 				       htons(s->protinfo.af_ipx.port));
 #else
-			len += sprintf(buffer+len,"%08lX:%04X  ",
-				       (unsigned long)htonl(i->if_netnum),
+			len += sprintf(buffer + len, "%08lX:%04X  ",
+				       (unsigned long) htonl(i->if_netnum),
 				       htons(s->protinfo.af_ipx.port));
 #endif	/* CONFIG_IPX_INTERN */
-
 			if (s->state != TCP_ESTABLISHED)
-				len += sprintf(buffer+len, "%-28s", "Not_Connected");
+				len += sprintf(buffer + len, "%-28s",
+						"Not_Connected");
 			else {
-				len += sprintf(buffer+len,
+				len += sprintf(buffer + len,
 					"%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 					(unsigned long) htonl(s->protinfo.af_ipx.dest_addr.net),
 					s->protinfo.af_ipx.dest_addr.node[0],
@@ -1795,10 +1775,10 @@
 					htons(s->protinfo.af_ipx.dest_addr.sock));
 			}
 
-			len += sprintf(buffer+len,"%08X  %08X  ",
+			len += sprintf(buffer + len, "%08X  %08X  ",
 				atomic_read(&s->wmem_alloc),
 				atomic_read(&s->rmem_alloc));
-			len += sprintf(buffer+len,"%02X     %03d\n",
+			len += sprintf(buffer + len, "%02X     %03d\n",
 				s->state, SOCK_INODE(s->socket)->i_uid);
 
 			pos = begin + len;
@@ -1816,7 +1796,7 @@
 	spin_unlock_bh(&ipx_interfaces_lock);
 
 	/* The data in question runs from begin to begin+len */
-	*start = buffer + (offset-begin);
+	*start = buffer + offset - begin;
 	len -= (offset - begin);
 	if (len > length)
 		len = length;
@@ -1830,19 +1810,21 @@
 	off_t begin = 0, pos = 0;
 	int len = 0;
 
-	len += sprintf(buffer,"%-11s%-13s%s\n",
+	len += sprintf(buffer, "%-11s%-13s%s\n",
 			"Network", "Router_Net", "Router_Node");
 	read_lock_bh(&ipx_routes_lock);
 	for (rt = ipx_routes; rt; rt = rt->ir_next) {
-		len += sprintf(buffer+len,"%08lX   ", (long unsigned int) ntohl(rt->ir_net));
+		len += sprintf(buffer + len, "%08lX   ",
+				(long unsigned int) ntohl(rt->ir_net));
 		if (rt->ir_routed) {
-			len += sprintf(buffer+len,"%08lX     %02X%02X%02X%02X%02X%02X\n",
-				(long unsigned int) ntohl(rt->ir_intrfc->if_netnum),
+			len += sprintf(buffer + len,
+					"%08lX     %02X%02X%02X%02X%02X%02X\n",
+			(long unsigned int) ntohl(rt->ir_intrfc->if_netnum),
 				rt->ir_router_node[0], rt->ir_router_node[1],
 				rt->ir_router_node[2], rt->ir_router_node[3],
 				rt->ir_router_node[4], rt->ir_router_node[5]);
 		} else {
-			len += sprintf(buffer+len, "%-13s%s\n",
+			len += sprintf(buffer + len, "%-13s%s\n",
 					"Directly", "Connected");
 		}
 
@@ -1865,40 +1847,30 @@
 	return len;
 }
 
-/**************************************************************************\
-*                                                                          *
-* Handling for system calls applied via the various interfaces to an       *
-* IPX socket object.                                                       *
-*                                                                          *
-\**************************************************************************/
+/* Handling for system calls applied via the various interfaces to an IPX
+ * socket object. */
 
 static int ipx_setsockopt(struct socket *sock, int level, int optname,
 			  char *optval, int optlen)
 {
 	struct sock *sk = sock->sk;
 	int opt;
+	int ret = -EINVAL;
 
 	if (optlen != sizeof(int))
-		return -EINVAL;
+		goto out;
 
+	ret = -EFAULT;
 	if (get_user(opt, (unsigned int *)optval))
-		return -EFAULT;
-
-	switch (level) {
-		case SOL_IPX:
-			switch (optname) {
-				case IPX_TYPE:
-					sk->protinfo.af_ipx.type = opt;
-					return 0;
+		goto out;
 
-				default:
-					return -ENOPROTOOPT;
-			}
-			break;
+	ret = -ENOPROTOOPT;
+	if (!(level == SOL_IPX && optname == IPX_TYPE))
+		goto out;
 
-		default:
-			return -ENOPROTOOPT;
-	}
+	sk->protinfo.af_ipx.type = opt;
+	ret = 0;
+out:	return ret;
 }
 
 static int ipx_getsockopt(struct socket *sock, int level, int optname,
@@ -1907,49 +1879,41 @@
 	struct sock *sk = sock->sk;
 	int val = 0;
 	int len;
+	int ret = -ENOPROTOOPT;
 
-	switch (level) {
-		case SOL_IPX:
-			switch (optname) {
-				case IPX_TYPE:
-					val = sk->protinfo.af_ipx.type;
-					break;
+	if (!(level == SOL_IPX && optname == IPX_TYPE))
+		goto out;
 
-				default:
-					return -ENOPROTOOPT;
-			}
-			break;
-
-		default:
-			return -ENOPROTOOPT;
-	}
+	val = sk->protinfo.af_ipx.type;
 
+	ret = -EFAULT;
 	if (get_user(len, optlen))
-		return -EFAULT;
+		goto out;
 
 	len = min(len, sizeof(int));
-	
+	ret = -EINVAL;
 	if(len < 0)
-		return -EINVAL;
+		goto out;
 		
-	if (put_user(len, optlen))
-		return -EFAULT;
-
-	if (copy_to_user(optval, &val, len))
-		return -EFAULT;
+	ret = -EFAULT;
+	if (put_user(len, optlen) || copy_to_user(optval, &val, len))
+		goto out;
 
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 static int ipx_create(struct socket *sock, int protocol)
 {
+	int ret = -ESOCKTNOSUPPORT;
 	struct sock *sk;
 
 	switch (sock->type) {
 		case SOCK_DGRAM:
 			sk = sk_alloc(PF_IPX, GFP_KERNEL, 1);
+                	ret = -ENOMEM;
 			if (!sk)
-                		return -ENOMEM;
+				goto out;
                         sock->ops = &ipx_dgram_ops;
                         break;
 
@@ -1958,12 +1922,14 @@
 			 * From this point on SPX sockets are handled
 			 * by af_spx.c and the methods replaced.
 			 */
-			if (spx_family_ops)
-				return spx_family_ops->create(sock,protocol);
+			if (spx_family_ops) {
+				ret = spx_family_ops->create(sock, protocol);
+				goto out;
+			}
 			/* Fall through if SPX is not loaded */
 		case SOCK_STREAM:       /* Allow higher levels to piggyback */
 		default:
-			return -ESOCKTNOSUPPORT;
+			goto out;
 	}
 #ifdef IPX_REFCNT_DEBUG
         atomic_inc(&ipx_sock_nr);
@@ -1975,7 +1941,8 @@
 	sk->no_check 	= 1;		/* Checksum off by default */
 
 	MOD_INC_USE_COUNT;
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 static int ipx_release(struct socket *sock)
@@ -1983,7 +1950,7 @@
 	struct sock *sk = sock->sk;
 
 	if (!sk)
-		return 0;
+		goto out;
 
 	if (!sk->dead)
 		sk->state_change(sk);
@@ -1995,7 +1962,7 @@
 	if (sock->type == SOCK_DGRAM)
 		MOD_DEC_USE_COUNT;
 
-	return 0;
+out:	return 0;
 }
 
 /* caller must hold a reference to intrfc */
@@ -2026,30 +1993,28 @@
 	struct sock *sk = sock->sk;
 	ipx_interface *intrfc;
 	struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
-	int ret;
-
-	if (!sk->zapped)
-		return -EINVAL;
+	int ret = -EINVAL;
 
-	if (addr_len != sizeof(struct sockaddr_ipx))
-		return -EINVAL;
+	if (!sk->zapped || addr_len != sizeof(struct sockaddr_ipx))
+		goto out;
 
 	intrfc = ipxitf_find_using_net(addr->sipx_network);
+	ret = -EADDRNOTAVAIL;
 	if (!intrfc)
-		return -EADDRNOTAVAIL;
+		goto out;
 
 	if (!addr->sipx_port) {
 		addr->sipx_port = ipx_first_free_socketnum(intrfc);
 		ret = -EINVAL;
 		if (!addr->sipx_port)
-			goto out;
+			goto out_put;
 	}
 
 	/* protect IPX system stuff like routing/sap */
 	ret = -EACCES;
 	if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET &&
 	    !capable(CAP_NET_ADMIN))
-		goto out;
+		goto out_put;
 
 	sk->protinfo.af_ipx.port = addr->sipx_port;
 
@@ -2061,8 +2026,8 @@
 		 */
 
 		ret = -EINVAL;
-		if (!memcmp(addr->sipx_node,ipx_broadcast_node,IPX_NODE_LEN))
-			goto out;
+		if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN))
+			goto out_put;
 		if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN))
 			memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
 			       IPX_NODE_LEN);
@@ -2077,7 +2042,7 @@
 			SOCK_DEBUG(sk,
 				"IPX: bind failed because port %X in use.\n",
 				ntohs((int)addr->sipx_port));
-			goto out;
+			goto out_put;
 		}
 	} else {
 		/* Source addresses are easy. It must be our
@@ -2093,7 +2058,7 @@
 			SOCK_DEBUG(sk,
 				"IPX: bind failed because port %X in use.\n",
 				ntohs((int)addr->sipx_port));
-			goto out;
+			goto out_put;
 		}
 	}
 
@@ -2106,7 +2071,7 @@
 	if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
 		SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",
 				ntohs((int)addr->sipx_port));
-		goto out;
+		goto out_put;
 	}
 
 #endif	/* CONFIG_IPX_INTERN */
@@ -2116,8 +2081,9 @@
 	SOCK_DEBUG(sk, "IPX: bound socket 0x%04X.\n", ntohs(addr->sipx_port) );
 
 	ret = 0;
-out:	ipxitf_put(intrfc);
-	return ret;
+out_put:
+	ipxitf_put(intrfc);
+out:	return ret;
 }
 
 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
@@ -2125,46 +2091,48 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ipx *addr;
+	int ret = -EINVAL;
 	ipx_route *rt;
 
 	sk->state	= TCP_CLOSE;
 	sock->state 	= SS_UNCONNECTED;
 
 	if (addr_len != sizeof(*addr))
-		return -EINVAL;
+		goto out;
 	addr = (struct sockaddr_ipx *)uaddr;
 
 	/* put the autobinding in */
 	if (!sk->protinfo.af_ipx.port) {
 		struct sockaddr_ipx uaddr;
-		int ret;
 
 		uaddr.sipx_port		= 0;
 		uaddr.sipx_network 	= 0;
 
 #ifdef CONFIG_IPX_INTERN
-		if (sk->protinfo.af_ipx.intrfc)
-			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);
-		else
-			return -ENETDOWN;		/* Someone zonked the iface */
+		ret = -ENETDOWN;
+		if (!sk->protinfo.af_ipx.intrfc)
+			goto out; /* Someone zonked the iface */
+		memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,
+			IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
 		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
 				sizeof(struct sockaddr_ipx));
 		if (ret)
-			return ret;
+			goto out;
 	}
 
         /* We can either connect to primary network or somewhere
 	 * we can route to */
 	rt = ipxrtr_lookup(addr->sipx_network);
+	ret = -ENETUNREACH;
 	if (!rt && !(!addr->sipx_network && ipx_primary_net))
-		return -ENETUNREACH;
+		goto out;
 
 	sk->protinfo.af_ipx.dest_addr.net  = addr->sipx_network;
 	sk->protinfo.af_ipx.dest_addr.sock = addr->sipx_port;
 	memcpy(sk->protinfo.af_ipx.dest_addr.node,
-		addr->sipx_node,IPX_NODE_LEN);
+		addr->sipx_node, IPX_NODE_LEN);
 	sk->protinfo.af_ipx.type = addr->sipx_type;
 
 	if (sock->type == SOCK_DGRAM) {
@@ -2174,7 +2142,8 @@
 
 	if (rt)
 		ipxrtr_put(rt);
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 
@@ -2184,24 +2153,30 @@
 	ipx_address *addr;
 	struct sockaddr_ipx sipx;
 	struct sock *sk = sock->sk;
+	int ret;
 
 	*uaddr_len = sizeof(struct sockaddr_ipx);
 
 	if (peer) {
+		ret = -ENOTCONN;
 		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 
 		addr = &sk->protinfo.af_ipx.dest_addr;
-		sipx.sipx_network = addr->net;
-		memcpy(sipx.sipx_node,addr->node,IPX_NODE_LEN);
-		sipx.sipx_port = addr->sock;
+		sipx.sipx_network	= addr->net;
+		sipx.sipx_port		= addr->sock;
+		memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN);
 	} else {
 		if (sk->protinfo.af_ipx.intrfc) {
-			sipx.sipx_network=sk->protinfo.af_ipx.intrfc->if_netnum;
+			sipx.sipx_network =
+				sk->protinfo.af_ipx.intrfc->if_netnum;
 #ifdef CONFIG_IPX_INTERN
-			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
+			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node,
+				IPX_NODE_LEN);
 #else
-			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
+			memcpy(sipx.sipx_node,
+				sk->protinfo.af_ipx.intrfc->if_node,
+				IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
 		} else {
@@ -2213,10 +2188,11 @@
 	}
 
 	sipx.sipx_family = AF_IPX;
-	sipx.sipx_type = sk->protinfo.af_ipx.type;
-	memcpy(uaddr,&sipx,sizeof(sipx));
+	sipx.sipx_type	 = sk->protinfo.af_ipx.type;
+	memcpy(uaddr, &sipx, sizeof(sipx));
 
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
@@ -2225,7 +2201,7 @@
 	ipx_interface *intrfc;
 	struct ipxhdr *ipx;
 	u16 ipx_pktsize;
-	int ret;
+	int ret = 0;
 		
 	/* Not ours */	
         if (skb->pkt_type == PACKET_OTHERHOST)
@@ -2234,8 +2210,8 @@
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
 		goto out;
 
-	ipx = skb->nh.ipxh;
-	ipx_pktsize = ntohs(ipx->ipx_pktsize);
+	ipx		= skb->nh.ipxh;
+	ipx_pktsize	= ntohs(ipx->ipx_pktsize);
 	
 	/* Too small or invalid header? */
 	if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)
@@ -2245,8 +2221,8 @@
 	   ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
 		goto drop;
 
-	IPX_SKB_CB(skb)->ipx_tctrl = ipx->ipx_tctrl;
-	IPX_SKB_CB(skb)->ipx_dest_net = ipx->ipx_dest.net;
+	IPX_SKB_CB(skb)->ipx_tctrl	= ipx->ipx_tctrl;
+	IPX_SKB_CB(skb)->ipx_dest_net	= ipx->ipx_dest.net;
 	IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net;
 
 	/* Determine what local ipx endpoint this is */
@@ -2266,9 +2242,9 @@
 
 	ret = ipxitf_rcv(intrfc, skb);
 	ipxitf_put(intrfc);
-	return ret;
+	goto out;
 drop:	kfree_skb(skb);
-out:	return 0;
+out:	return ret;
 }
 
 static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
@@ -2277,58 +2253,58 @@
 	struct sock *sk = sock->sk;
 	struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name;
 	struct sockaddr_ipx local_sipx;
-	int retval;
+	int ret = -EINVAL;
 	int flags = msg->msg_flags;
 
 	/* Socket gets bound below anyway */
 /*	if (sk->zapped)
 		return -EIO; */	/* Socket not bound */
 	if (flags & ~MSG_DONTWAIT)
-		return -EINVAL;
+		goto out;
 
 	if (usipx) {
 		if (!sk->protinfo.af_ipx.port) {
 			struct sockaddr_ipx uaddr;
-			int ret;
 
-			uaddr.sipx_port = 0;
-			uaddr.sipx_network = 0L;
+			uaddr.sipx_port		= 0;
+			uaddr.sipx_network	= 0;
 #ifdef CONFIG_IPX_INTERN
-			if (sk->protinfo.af_ipx.intrfc)
-				memcpy(uaddr.sipx_node,
-					sk->protinfo.af_ipx.intrfc->if_node,
-					IPX_NODE_LEN);
-			else
-				return -ENETDOWN;               /* Someone zonked the iface */
+			ret = -ENETDOWN;
+			if (!sk->protinfo.af_ipx.intrfc)
+				goto out; /* Someone zonked the iface */
+			memcpy(uaddr.sipx_node,
+				sk->protinfo.af_ipx.intrfc->if_node,
+				IPX_NODE_LEN);
 #endif
 			ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
 					sizeof(struct sockaddr_ipx));
 			if (ret)
-				return ret;
+				goto out;
 		}
 
-		if (msg->msg_namelen < sizeof(*usipx))
-			return -EINVAL;
-		if (usipx->sipx_family != AF_IPX)
-			return -EINVAL;
+		ret = -EINVAL;
+		if (msg->msg_namelen < sizeof(*usipx) ||
+		    usipx->sipx_family != AF_IPX)
+			goto out;
 	} else {
+		ret = -ENOTCONN;
 		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 
-		usipx=&local_sipx;
+		usipx = &local_sipx;
 		usipx->sipx_family 	= AF_IPX;
 		usipx->sipx_type 	= sk->protinfo.af_ipx.type;
 		usipx->sipx_port 	= sk->protinfo.af_ipx.dest_addr.sock;
 		usipx->sipx_network 	= sk->protinfo.af_ipx.dest_addr.net;
-		memcpy(usipx->sipx_node,sk->protinfo.af_ipx.dest_addr.node,IPX_NODE_LEN);
+		memcpy(usipx->sipx_node, sk->protinfo.af_ipx.dest_addr.node,
+				IPX_NODE_LEN);
 	}
 
-	retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,
+	ret = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,
 				     flags & MSG_DONTWAIT);
-	if (retval < 0)
-		return retval;
-
-	return len;
+	if (ret >= 0)
+		ret = len;
+out:	return ret;
 }
 
 
@@ -2344,35 +2320,37 @@
 	/* put the autobinding in */
 	if (!sk->protinfo.af_ipx.port) {
 		struct sockaddr_ipx uaddr;
-		int ret;
 
 		uaddr.sipx_port		= 0;
 		uaddr.sipx_network 	= 0;
 
 #ifdef CONFIG_IPX_INTERN
-		if (sk->protinfo.af_ipx.intrfc)
-			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);
-		else
-			return -ENETDOWN;		/* Someone zonked the iface */
+		err = -ENETDOWN;
+		if (!sk->protinfo.af_ipx.intrfc)
+			goto out; /* Someone zonked the iface */
+		memcpy(uaddr.sipx_node,
+			sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
-		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
+		err = ipx_bind(sock, (struct sockaddr *)&uaddr,
 				sizeof(struct sockaddr_ipx));
-		if (ret)
-			return ret;
+		if (err)
+			goto out;
 	}
 	
+	err = -ENOTCONN;
 	if (sk->zapped)
-		return -ENOTCONN;
+		goto out;
 
-	skb = skb_recv_datagram(sk,flags&~MSG_DONTWAIT,flags&MSG_DONTWAIT,&err);
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+					flags & MSG_DONTWAIT, &err);
 	if (!skb)
 		goto out;
 
 	ipx 	= skb->nh.ipxh;
 	copied 	= ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
 	if (copied > size) {
-		copied=size;
+		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
@@ -2387,7 +2365,7 @@
 	if (sipx) {
 		sipx->sipx_family	= AF_IPX;
 		sipx->sipx_port		= ipx->ipx_source.sock;
-		memcpy(sipx->sipx_node,ipx->ipx_source.node,IPX_NODE_LEN);
+		memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);
 		sipx->sipx_network	= IPX_SKB_CB(skb)->ipx_source_net;
 		sipx->sipx_type 	= ipx->ipx_type;
 	}
@@ -2399,7 +2377,7 @@
 }
 
 
-static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
+static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	long amount = 0;
 	struct sock *sk = sock->sk;
@@ -2411,10 +2389,10 @@
 				amount = 0;
 			return put_user(amount, (int *)arg);
 
-		case TIOCINQ:
-		{
+		case TIOCINQ: {
 			struct sk_buff *skb = skb_peek(&sk->receive_queue);
-			/* These two are safe on a single CPU system as only user tasks fiddle here */
+			/* These two are safe on a single CPU system as only
+			 * user tasks fiddle here */
 			if (skb)
 				amount = skb->len - sizeof(struct ipxhdr);
 			return put_user(amount, (int *)arg);
@@ -2424,7 +2402,7 @@
 		case SIOCDELRT:
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
-			return ipxrtr_ioctl(cmd,(void *)arg);
+			return ipxrtr_ioctl(cmd, (void *)arg);
 
 		case SIOCSIFADDR:
 		case SIOCAIPXITFCRT:
@@ -2433,13 +2411,12 @@
 				return -EPERM;
 
 		case SIOCGIFADDR:
-			return ipxitf_ioctl(cmd,(void *)arg);
+			return ipxitf_ioctl(cmd, (void *)arg);
 
 		case SIOCIPXCFGDATA:
 			return ipxcfg_get_config_data((void *)arg);
 
 		case SIOCIPXNCPCONN:
-                {
 			/*
 			 * This socket wants to take care of the NCP connection
 			 * handed to us in arg.
@@ -2448,10 +2425,8 @@
                 		return -EPERM;
 			return get_user(sk->protinfo.af_ipx.ipx_ncp_conn,
 					(const unsigned short *)(arg));
-                }
 
-		case SIOCGSTAMP:
-		{
+		case SIOCGSTAMP: {
 			int ret = -EINVAL;
 			if (sk) {
 				if (!sk->stamp.tv_sec)
@@ -2537,16 +2512,13 @@
 #include <linux/smp_lock.h>
 SOCKOPS_WRAP(ipx_dgram, PF_IPX);
 
-static struct packet_type ipx_8023_packet_type =
-
-{
+static struct packet_type ipx_8023_packet_type = {
 	type:		__constant_htons(ETH_P_802_3),
 	func:		ipx_rcv,
 	data:		(void *) 1,	/* yap, I understand shared skbs :-) */
 };
 
-static struct packet_type ipx_dix_packet_type =
-{
+static struct packet_type ipx_dix_packet_type = {
 	type:		__constant_htons(ETH_P_IPX),
 	func:		ipx_rcv,
 	data:		(void *) 1,	/* yap, I understand shared skbs :-) */
@@ -2565,7 +2537,7 @@
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
 static const char banner[] __initdata =
-	KERN_INFO "NET4: Linux IPX 0.46 for NET4.0\n"
+	KERN_INFO "NET4: Linux IPX 0.47 for NET4.0\n"
 	KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \
 	KERN_INFO "IPX Portions Copyright (c) 2000, 2001 Conectiva, Inc.\n";
 
@@ -2579,11 +2551,11 @@
 	p8023_datalink = make_8023_client();
 	dev_add_pack(&ipx_8023_packet_type);
 
-	p8022_datalink = register_8022_client(ipx_8022_type,ipx_rcv);
+	p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);
 	if (!p8022_datalink)
 		printk(KERN_CRIT "IPX: Unable to register with 802.2\n");
 
-	pSNAP_datalink = register_snap_client(ipx_snap_id,ipx_rcv);
+	pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv);
 	if (!pSNAP_datalink)
 		printk(KERN_CRIT "IPX: Unable to register with SNAP\n");
 
diff -u --recursive --new-file v2.4.4/linux/net/ipx/af_spx.c linux/net/ipx/af_spx.c
--- v2.4.4/linux/net/ipx/af_spx.c	Thu Apr 19 08:38:50 2001
+++ linux/net/ipx/af_spx.c	Wed May 16 10:31:27 2001
@@ -6,7 +6,7 @@
  *		 Revision Date:  February 9, 1993
  *
  *	Developers:
- *      Jay Schulist    <jschlst@turbolinux.com>
+ *      Jay Schulist    <jschlst@samba.org>
  *	Jim Freeman	<jfree@caldera.com>
  *
  *	Changes:
diff -u --recursive --new-file v2.4.4/linux/net/ipx/sysctl_net_ipx.c linux/net/ipx/sysctl_net_ipx.c
--- v2.4.4/linux/net/ipx/sysctl_net_ipx.c	Thu Apr 12 12:16:36 2001
+++ linux/net/ipx/sysctl_net_ipx.c	Wed May 16 10:31:27 2001
@@ -10,10 +10,13 @@
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 
+#ifndef CONFIG_SYSCTL
+#error This file should not be compiled without CONFIG_SYSCTL defined
+#endif
+
 /* From af_ipx.c */
 extern int sysctl_ipx_pprop_broadcasting;
 
-#ifdef CONFIG_SYSCTL
 ctl_table ipx_table[] = {
 	{ NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting",
 	  &sysctl_ipx_pprop_broadcasting, sizeof(int), 0644, NULL,
@@ -42,13 +45,3 @@
 {
 	unregister_sysctl_table(ipx_table_header);
 }
-
-#else
-void ipx_register_sysctl(void)
-{
-}
-
-void ipx_unregister_sysctl(void)
-{
-}
-#endif
diff -u --recursive --new-file v2.4.4/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.4.4/linux/net/irda/af_irda.c	Thu Apr 12 12:11:39 2001
+++ linux/net/irda/af_irda.c	Sat May 19 17:47:55 2001
@@ -2441,5 +2441,7 @@
  
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); 
+#ifdef CONFIG_IRDA_DEBUG
 MODULE_PARM(irda_debug, "1l");
+#endif
 #endif /* MODULE */
diff -u --recursive --new-file v2.4.4/linux/net/irda/irnet/irnet.h linux/net/irda/irnet/irnet.h
--- v2.4.4/linux/net/irda/irnet/irnet.h	Fri Mar  2 11:12:12 2001
+++ linux/net/irda/irnet/irnet.h	Tue May  1 16:05:00 2001
@@ -5,7 +5,7 @@
  *
  * This file contains definitions and declarations global to the IrNET module,
  * all grouped in one place...
- * This file is a private header, so other modules don't want to know
+ * This file is a *private* header, so other modules don't want to know
  * what's in there...
  *
  * Note : as most part of the Linux kernel, this module is available
@@ -52,15 +52,13 @@
  *	o multipoint operation (limited by IrLAP specification)
  *	o information in /proc/net/irda/irnet
  *	o IrNET events on /dev/irnet (for user space daemon)
- *	o IrNET deamon (irnetd) to automatically handle incoming requests
+ *	o IrNET daemon (irnetd) to automatically handle incoming requests
  *	o Windows 2000 compatibility (tested, but need more work)
  * Currently missing :
  *	o Lot's of testing (that's your job)
  *	o Connection retries (may be too hard to do)
  *	o Check pppd persist mode
- *	o User space deamon (to automatically handle incoming requests)
- *	o A registered device number (coming, waiting from an answer) 
- *	o Final integration in Linux-IrDA (up to Dag) 
+ *	o User space daemon (to automatically handle incoming requests)
  *
  * The setup is not currently the most easy, but this should get much
  * better when everything will get integrated...
@@ -159,6 +157,17 @@
  *	o Add IRNET_NOANSWER_FROM event (mostly to help support)
  *	o Release flow control in disconnect_indication
  *	o Block packets while connecting (speed up connections)
+ *
+ * v5 - 11/01/01 - Jean II
+ *	o Init self->max_header_size, just in case...
+ *	o Set up ap->chan.hdrlen, to get zero copy on tx side working.
+ *	o avoid tx->ttp->flow->ppp->tx->... loop, by checking flow state
+ *		Thanks to Christian Gennerat for finding this bug !
+ *	---
+ *	o Declare the proper MTU/MRU that we can support
+ *		(but PPP doesn't read the MTU value :-()
+ *	o Declare hashbin HB_NOLOCK instead of HB_LOCAL to avoid
+ *		disabling and enabling irq twice
  */
 
 /***************************** INCLUDES *****************************/
@@ -375,7 +384,7 @@
   struct irda_device_info *discoveries;	/* Copy of the discovery log */
   int			disco_index;	/* Last read in the discovery log */
   int			disco_number;	/* Size of the discovery log */
-#endif INITIAL_DISCOVERY
+#endif /* INITIAL_DISCOVERY */
 
 } irnet_socket;
 
@@ -450,4 +459,4 @@
 /* Control channel stuff - allocated in irnet_irda.h */
 extern struct irnet_ctrl_channel	irnet_events;
 
-#endif IRNET_H
+#endif /* IRNET_H */
diff -u --recursive --new-file v2.4.4/linux/net/irda/irnet/irnet_irda.c linux/net/irda/irnet/irnet_irda.c
--- v2.4.4/linux/net/irda/irnet/irnet_irda.c	Fri Mar  2 11:12:12 2001
+++ linux/net/irda/irnet/irnet_irda.c	Sat May 19 17:47:55 2001
@@ -380,9 +380,9 @@
   self->ckey = irlmp_register_client(0, NULL, NULL, NULL);
 #ifdef DISCOVERY_NOMASK
   self->mask = 0xffff;		/* For W2k compatibility */
-#else DISCOVERY_NOMASK
+#else /* DISCOVERY_NOMASK */
   self->mask = irlmp_service_to_hint(S_LAN);
-#endif DISCOVERY_NOMASK
+#endif /* DISCOVERY_NOMASK */
   self->tx_flow = FLOW_START;	/* Flow control from IrTTP */
 
   DEXIT(IRDA_SOCK_TRACE, "\n");
@@ -692,7 +692,7 @@
   /* If we want to receive "stream sockets" */
   if(max_sdu_size == 0)
     new->max_data_size = irttp_get_max_seg_size(new->tsap);
-#endif STREAM_COMPAT
+#endif /* STREAM_COMPAT */
 
   /* Clean up the original one to keep it in listen state */
   self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
@@ -708,7 +708,7 @@
    * Also, not doing it give IrDA a chance to finish the setup properly
    * before beeing swamped with packets... */
   ppp_output_wakeup(&new->chan);
-#endif CONNECT_INDIC_KICK
+#endif /* CONNECT_INDIC_KICK */
 
   /* Notify the control channel */
   irnet_post_event(new, IRNET_CONNECT_FROM, new->daddr, self->rname);
@@ -738,7 +738,7 @@
   /* Hum... Is it the right thing to do ? And do we need to send
    * a connect response before ? It looks ok without this... */
   irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
-#endif FAIL_SEND_DISCONNECT
+#endif /* FAIL_SEND_DISCONNECT */
 
   /* Clean up the server to keep it in listen state */
   self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
@@ -788,7 +788,7 @@
 #ifdef ADVERTISE_HINT
   /* Register with IrLMP as a service (advertise our hint bit) */
   irnet_server.skey = irlmp_register_service(hints);
-#endif ADVERTISE_HINT
+#endif /* ADVERTISE_HINT */
 
   /* Register with LM-IAS (so that people can connect to us) */
   irnet_server.ias_obj = irias_new_object(IRNET_SERVICE_NAME, jiffies);
@@ -823,7 +823,7 @@
 #ifdef ADVERTISE_HINT
   /* Unregister with IrLMP */
   irlmp_unregister_service(irnet_server.skey);
-#endif ADVERTISE_HINT
+#endif /* ADVERTISE_HINT */
 
   /* Unregister with LM-IAS */
   if(irnet_server.ias_obj)
@@ -995,7 +995,7 @@
 #ifdef STREAM_COMPAT
   if(max_sdu_size == 0)
     self->max_data_size = irttp_get_max_seg_size(self->tsap);
-#endif STREAM_COMPAT
+#endif /* STREAM_COMPAT */
 
   /* At this point, IrLMP has assigned our source address */
   self->saddr = irttp_get_saddr(self->tsap);
@@ -1012,10 +1012,10 @@
       DEBUG(IRDA_CB_INFO, "Passing connect packet to PPP.\n");
       /* Try to pass it to PPP */
       irnet_data_indication(instance, sap, skb);
-#else PASS_CONNECT_PACKETS
+#else /* PASS_CONNECT_PACKETS */
       DERROR(IRDA_CB_ERROR, "Dropping non empty packet.\n");
       kfree_skb(skb);	/* Note : will be optimised with other kfree... */
-#endif PASS_CONNECT_PACKETS
+#endif /* PASS_CONNECT_PACKETS */
     }
   else
     kfree_skb(skb);
@@ -1039,6 +1039,7 @@
 		      LOCAL_FLOW flow) 
 {
   irnet_socket *	self = (irnet_socket *) instance;
+  LOCAL_FLOW		oldflow = self->tx_flow;
 
   DENTER(IRDA_TCB_TRACE, "(self=0x%X, flow=%d)\n", (unsigned int) self, flow);
 
@@ -1050,7 +1051,11 @@
     {
     case FLOW_START:
       DEBUG(IRDA_CB_INFO, "IrTTP wants us to start again\n");
-      ppp_output_wakeup(&self->chan);
+      /* Check if we really need to wake up PPP */
+      if(oldflow == FLOW_STOP)
+	ppp_output_wakeup(&self->chan);
+      else
+	DEBUG(IRDA_CB_INFO, "But we were already transmitting !!!\n");
       break;
     case FLOW_STOP:
       DEBUG(IRDA_CB_INFO, "IrTTP wants us to slow down\n");
@@ -1076,6 +1081,7 @@
 			LOCK_STATUS lock)
 {
   irnet_socket *	self = (irnet_socket *) instance;
+  LOCAL_FLOW		oldflow = self->tx_flow;
 
   DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
   DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n");
@@ -1157,10 +1163,10 @@
        * WARNING : This need more testing ! */
       irttp_close_tsap(new->tsap);
       /* Note : no return, fall through... */
-#else ALLOW_SIMULT_CONNECT
+#else /* ALLOW_SIMULT_CONNECT */
       irnet_disconnect_server(self, skb);
       return;
-#endif ALLOW_SIMULT_CONNECT
+#endif /* ALLOW_SIMULT_CONNECT */
     }
 
   /* So : at this point, we have a socket, and it is idle. Good ! */
@@ -1173,10 +1179,10 @@
       DEBUG(IRDA_CB_INFO, "Passing connect packet to PPP.\n");
       /* Try to pass it to PPP */
       irnet_data_indication(new, new->tsap, skb);
-#else PASS_CONNECT_PACKETS
+#else /* PASS_CONNECT_PACKETS */
       DERROR(IRDA_CB_ERROR, "Dropping non empty packet.\n");
       kfree_skb(skb);	/* Note : will be optimised with other kfree... */
-#endif PASS_CONNECT_PACKETS
+#endif /* PASS_CONNECT_PACKETS */
     }
   else
     kfree_skb(skb);
@@ -1312,7 +1318,7 @@
 
   DEXIT(IRDA_OCB_TRACE, "\n");
 }
-#endif DISCOVERY_EVENTS
+#endif /* DISCOVERY_EVENTS */
 
 
 /*********************** PROC ENTRY CALLBACKS ***********************/
@@ -1426,7 +1432,7 @@
   memset(&irnet_server, 0, sizeof(struct irnet_root));
 
   /* Setup start of irnet instance list */
-  irnet_server.list = hashbin_new(HB_LOCAL); 
+  irnet_server.list = hashbin_new(HB_NOLOCK); 
   DABORT(irnet_server.list == NULL, -ENOMEM,
 	 MODULE_ERROR, "Can't allocate hashbin!\n");
   /* Init spinlock for instance list */
@@ -1469,7 +1475,7 @@
 #ifdef CONFIG_PROC_FS
   /* Remove our /proc file */
   remove_proc_entry("irnet", proc_irda);
-#endif CONFIG_PROC_FS
+#endif /* CONFIG_PROC_FS */
 
   /* Remove our IrNET server from existence */
   irnet_destroy_server();
diff -u --recursive --new-file v2.4.4/linux/net/irda/irnet/irnet_irda.h linux/net/irda/irnet/irnet_irda.h
--- v2.4.4/linux/net/irda/irnet/irnet_irda.h	Mon Dec 11 13:33:15 2000
+++ linux/net/irda/irnet/irnet_irda.h	Tue May  1 16:05:00 2001
@@ -13,8 +13,9 @@
 #define IRNET_IRDA_H
 
 /***************************** INCLUDES *****************************/
-
 #include <linux/config.h>
+/* Please add other headers in irnet.h */
+
 #include "irnet.h"		/* Module global include */
 
 /************************ CONSTANTS & MACROS ************************/
@@ -149,7 +150,7 @@
 			char **,
 			off_t,
 			int);
-#endif CONFIG_PROC_FS
+#endif /* CONFIG_PROC_FS */
 
 /**************************** VARIABLES ****************************/
 
@@ -164,6 +165,6 @@
 /* The /proc/net/irda directory, defined elsewhere... */
 #ifdef CONFIG_PROC_FS
 extern struct proc_dir_entry *proc_irda;
-#endif CONFIG_PROC_FS
+#endif /* CONFIG_PROC_FS */
 
-#endif IRNET_IRDA_H
+#endif /* IRNET_IRDA_H */
diff -u --recursive --new-file v2.4.4/linux/net/irda/irnet/irnet_ppp.c linux/net/irda/irnet/irnet_ppp.c
--- v2.4.4/linux/net/irda/irnet/irnet_ppp.c	Fri Apr 20 11:54:24 2001
+++ linux/net/irda/irnet/irnet_ppp.c	Tue May  1 16:05:00 2001
@@ -186,7 +186,7 @@
 
   return done_event;
 }
-#endif INITIAL_DISCOVERY
+#endif /* INITIAL_DISCOVERY */
 
 /*------------------------------------------------------------------*/
 /*
@@ -221,7 +221,7 @@
       DEXIT(CTRL_TRACE, "\n");
       return(strlen(event));
     }
-#endif INITIAL_DISCOVERY
+#endif /* INITIAL_DISCOVERY */
 
   /* Put ourselves on the wait queue to be woken up */
   add_wait_queue(&irnet_events.rwait, &wait);
@@ -346,7 +346,7 @@
 #ifdef INITIAL_DISCOVERY
   if(ap->disco_number != -1)
     mask |= POLLIN | POLLRDNORM;
-#endif INITIAL_DISCOVERY
+#endif /* INITIAL_DISCOVERY */
 
   DEXIT(CTRL_TRACE, " - mask=0x%X\n", mask);
   return mask;
@@ -379,7 +379,7 @@
   /* This could (should?) be enforced by the permissions on /dev/irnet. */
   if(!capable(CAP_NET_ADMIN))
     return -EPERM;
-#endif SECURE_DEVIRNET
+#endif /* SECURE_DEVIRNET */
 
   /* Allocate a private structure for this IrNET instance */
   ap = kmalloc(sizeof(*ap), GFP_KERNEL);
@@ -394,8 +394,11 @@
   /* PPP channel setup */
   ap->ppp_open = 0;
   ap->chan.private = ap;
+  ap->chan.ops = &irnet_ppp_ops;
+  ap->chan.mtu = (2048 - TTP_MAX_HEADER - 2 - PPP_HDRLEN);
+  ap->chan.hdrlen = 2 + TTP_MAX_HEADER;		/* for A/C + Max IrDA hdr */
   /* PPP parameters */
-  ap->mru = PPP_MRU;
+  ap->mru = (2048 - TTP_MAX_HEADER - 2 - PPP_HDRLEN);
   ap->xaccm[0] = ~0U;
   ap->xaccm[3] = 0x60000000U;
   ap->raccm = ~0U;
@@ -554,7 +557,7 @@
 #ifdef SECURE_DEVIRNET
   if(!capable(CAP_NET_ADMIN))
     return -EPERM;
-#endif SECURE_DEVIRNET
+#endif /* SECURE_DEVIRNET */
 
   err = -EFAULT;
   switch(cmd)
@@ -566,10 +569,7 @@
       if((val == N_SYNC_PPP) || (val == N_PPP))
 	{
 	  DEBUG(FS_INFO, "Entering PPP discipline.\n");
-	  /* PPP channel setup */
-	  ap->chan.private = ap;
-	  ap->chan.ops = &irnet_ppp_ops;
-	  ap->chan.mtu = PPP_MRU;
+	  /* PPP channel setup (ap->chan in configued in dev_irnet_open())*/
 	  err = ppp_register_channel(&ap->chan);
 	  if(err == 0)
 	    {
@@ -672,7 +672,7 @@
        * we get rid of our own buffers */
 #ifdef FLUSH_TO_PPP
       ppp_output_wakeup(&ap->chan);
-#endif FLUSH_TO_PPP
+#endif /* FLUSH_TO_PPP */
       err = 0;
       break;
 
@@ -758,7 +758,7 @@
   /* prepend address/control fields if necessary */
   if(needaddr)
     {
-      skb_push(skb,2);
+      skb_push(skb, 2);
       skb->data[0] = PPP_ALLSTATIONS;
       skb->data[1] = PPP_UI;
     }
@@ -800,7 +800,7 @@
        * go through interruptible_sleep_on() in irnet_find_lsap_sel()
        * We need to find another way... */
       irda_irnet_connect(self);
-#endif CONNECT_IN_SEND
+#endif /* CONNECT_IN_SEND */
 
       DEBUG(PPP_INFO, "IrTTP not ready ! (%d-0x%X)\n",
 	    self->ttp_open, (unsigned int) self->tsap);
@@ -831,7 +831,7 @@
 	  /* Blocking packet, ppp_generic will retry later */
 	  return 0;
 	}
-#endif BLOCK_WHEN_CONNECT
+#endif /* BLOCK_WHEN_CONNECT */
 
       /* Dropping packet, pppd will retry later */
       dev_kfree_skb(skb);
diff -u --recursive --new-file v2.4.4/linux/net/irda/irnet/irnet_ppp.h linux/net/irda/irnet/irnet_ppp.h
--- v2.4.4/linux/net/irda/irnet/irnet_ppp.h	Mon Dec 11 13:33:14 2000
+++ linux/net/irda/irnet/irnet_ppp.h	Mon Apr 30 16:26:09 2001
@@ -27,8 +27,8 @@
  * Should be defined in <linux/if_ppp.h> */
 #ifndef PPPIOCSLINKNAME
 #define PPPIOCSLINKNAME	_IOW('t', 74, struct ppp_option_data)
-#endif PPPIOCSLINKNAME
-#endif LINKNAME_IOCTL
+#endif /* PPPIOCSLINKNAME */
+#endif /* LINKNAME_IOCTL */
 
 /* PPP hardcore stuff */
 
@@ -127,4 +127,4 @@
   ppp_irnet_ioctl
 };
 
-#endif IRNET_PPP_H
+#endif /* IRNET_PPP_H */
diff -u --recursive --new-file v2.4.4/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.4.4/linux/net/irda/irttp.c	Thu Feb  8 15:14:08 2001
+++ linux/net/irda/irttp.c	Tue May  1 16:05:00 2001
@@ -369,7 +369,7 @@
 	} else {
 		/*
 		 *  Fragment the frame, this function will also queue the
-		 *  fragments, we don't care about the fact the the transmit
+		 *  fragments, we don't care about the fact the transmit
 		 *  queue may be overfilled by all the segments for a little
 		 *  while
 		 */
@@ -454,6 +454,46 @@
 		 */
 		skb->data[0] |= (n & 0x7f);
 		
+		/* Detach from socket.
+		 * The current skb has a reference to the socket that sent
+		 * it (skb->sk). When we pass it to IrLMP, the skb will be
+		 * stored in in IrLAP (self->wx_list). When we are within
+		 * IrLAP, we loose the notion of socket, so we should not
+		 * have a reference to a socket. So, we drop it here.
+		 * 
+		 * Why does it matter ?
+		 * When the skb is freed (kfree_skb), if it is associated
+		 * with a socket, it release buffer space on the socket
+		 * (through sock_wfree() and sock_def_write_space()).
+		 * If the socket no longer exist, we may crash. Hard.
+		 * When we close a socket, we make sure that associated packets
+		 * in IrTTP are freed. However, we have no way to cancel
+		 * the packet that we have passed to IrLAP. So, if a packet
+		 * remains in IrLAP (retry on the link or else) after we
+		 * close the socket, we are dead !
+		 * Jean II */
+		if (skb->sk != NULL) {
+			struct sk_buff *tx_skb;
+
+			/* IrSOCK application, IrOBEX, ... */
+			IRDA_DEBUG(4, __FUNCTION__ "() : Detaching SKB from socket.\n");
+			/* Note : still looking for a more efficient way
+			 * to do that - Jean II */
+
+			/* Get another skb on the same buffer, but without
+			 * a reference to the socket (skb->sk = NULL) */
+			tx_skb = skb_clone(skb, GFP_ATOMIC);
+			if (tx_skb != NULL) {
+				/* Release the skb associated with the
+				 * socket, and use the new skb insted */
+				kfree_skb(skb);
+				skb = tx_skb;
+			}
+		} else {
+			/* IrCOMM over IrTTP, IrLAN, ... */
+			IRDA_DEBUG(4, __FUNCTION__ "() : Got SKB not attached to a socket.\n");
+		}
+
 		irlmp_data_request(self->lsap, skb);
 		self->stats.tx_packets++;
 
diff -u --recursive --new-file v2.4.4/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.4.4/linux/net/irda/qos.c	Thu Feb  8 15:14:08 2001
+++ linux/net/irda/qos.c	Mon Apr 30 16:26:09 2001
@@ -346,7 +346,7 @@
 			WARNING(__FUNCTION__ "(), nothing more we can do!\n");
 		}
 	}
-#endif CONFIG_IRDA_DYNAMIC_WINDOW
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 }
 
 /*
diff -u --recursive --new-file v2.4.4/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.4.4/linux/net/irda/wrapper.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/wrapper.c	Mon Apr 30 16:26:09 2001
@@ -130,7 +130,7 @@
 #ifdef __LITTLE_ENDIAN
 	n += stuff_byte(fcs.bytes[0], tx_buff+n);
 	n += stuff_byte(fcs.bytes[1], tx_buff+n);
-#else ifdef __BIG_ENDIAN
+#else /* ifdef __BIG_ENDIAN */
 	n += stuff_byte(fcs.bytes[1], tx_buff+n);
 	n += stuff_byte(fcs.bytes[0], tx_buff+n);
 #endif
diff -u --recursive --new-file v2.4.4/linux/net/wanrouter/Makefile linux/net/wanrouter/Makefile
--- v2.4.4/linux/net/wanrouter/Makefile	Thu Apr 12 12:11:39 2001
+++ linux/net/wanrouter/Makefile	Sat May 19 17:47:55 2001
@@ -12,9 +12,9 @@
 export-objs := wanmain.o
 
 obj-y :=  wanproc.o wanmain.o
-obj-m := $(O_TARGET) af_wanpipe.o
+obj-m := $(O_TARGET)
+ifneq ($(CONFIG_VENDOR_SANGOMA),n)
+	obj-m += $(O_TARGET)
+endif
 
 include $(TOPDIR)/Rules.make
-
-tar:
-	tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.4.4/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.4.4/linux/net/wanrouter/wanproc.c	Thu Apr 12 12:11:39 2001
+++ linux/net/wanrouter/wanproc.c	Thu May 24 15:01:02 2001
@@ -267,8 +267,10 @@
 		offs = file->f_pos;
 		if (offs < pos) {
 			len = min(pos - offs, count);
-			if(copy_to_user(buf, (page + offs), len))
+			if (copy_to_user(buf, (page + offs), len)) {
+				kfree(page);
 				return -EFAULT;
+			}
 			file->f_pos += len;
 		}
 		else
diff -u --recursive --new-file v2.4.4/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.4.4/linux/scripts/Menuconfig	Sun Oct  8 09:30:40 2000
+++ linux/scripts/Menuconfig	Sat May 19 17:47:55 2001
@@ -347,7 +347,7 @@
 
 	echo -e "
 	function $firstchoice () \
-		{ l_choice '$title' \"$choices\" $current ;}" >>MCradiolists
+		{ l_choice '$title' \"$choices\" \"$current\" ;}" >>MCradiolists
 }
 
 } # END load_functions()
diff -u --recursive --new-file v2.4.4/linux/scripts/checkconfig.pl linux/scripts/checkconfig.pl
--- v2.4.4/linux/scripts/checkconfig.pl	Mon Jan 15 15:31:19 2001
+++ linux/scripts/checkconfig.pl	Sat May 19 17:47:55 2001
@@ -25,6 +25,13 @@
 	$fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next);
 	m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
 
+	# Pick up definitions.
+	if ( m/^\s*#/o )
+	{
+	    $iLinuxConfig      = $. if m/^\s*#\s*include\s*"linux\/config\.h"/o;
+	    $configList{uc $1} = 1  if m/^\s*#\s*include\s*"config\/(\S*)\.h"/o;
+	}
+
 	# Strip strings.
 	$fInString && (s+^.*?"+ +o ? ($fInString = 0) : next);
 	m+"+o && (s+".*?"+ +go, (s+".*$+ +o && ($fInString = 1)));
@@ -52,7 +59,7 @@
 
     # Report superfluous includes.
     if ( $iLinuxConfig && ! $fUseConfig )
-	{ print "$file: $iLinuxConfig: <linux/config.h> not needed.\n"; }
+	{ print "$file: $iLinuxConfig: linux/config.h not needed.\n"; }
 
     close(FILE);
 }
