## Automatically generated incremental diff
## From:   linux-2.4.6-pre8
## To:     linux-2.4.6-pre9
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.6-pre8/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.6-pre8/Documentation/Configure.help	Mon Dec  3 22:50:26 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:50:36 2001
@@ -9457,6 +9457,15 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
+New Tulip bus configuration (EXPERIMENTAL)
+CONFIG_TULIP_MWI
+  This configures your Tulip card specifically for the card and
+  system cache line size type you are using.
+
+  This is experimental code, not yet tested on many boards.
+
+  If unsure, say N.
+
 Digi Intl. RightSwitch support
 CONFIG_DGRS
   This is support for the Digi International RightSwitch series of
@@ -12180,12 +12189,13 @@
 
   If unsure, say N.
 
-System V and Coherent file system support (read only)
+System V, Version 7, Xenix and Coherent filesystem support (read only)
 CONFIG_SYSV_FS
   SCO, Xenix and Coherent are commercial Unix systems for Intel
-  machines. Saying Y here would allow you to read from their floppies
-  and hard disk partitions. If you also want to write to these media,
-  say Y to "SYSV file system write support" below.
+  machines, and Version 7 was used on the DEC PDP-11. Saying Y
+  here would allow you to read from their floppies and hard disk
+  partitions. If you also want to write to these media, say Y to
+  "SYSV file system write support" below.
 
   If you have floppies or hard disk partitions like that, it is likely
   that they contain binaries from those other Unix systems; in order
@@ -12194,7 +12204,9 @@
   Xenix, Wyse, UnixWare, Dell Unix and System V programs under Linux
   and is often needed to run commercial software that's only available
   for those systems. It's available via FTP (user: anonymous) from
-  ftp://tsx-11.mit.edu/pub/linux/BETA ).
+  ftp://tsx-11.mit.edu/pub/linux/BETA ). NOTE: that will work only for
+  binaries from Intel-based systems; PDP ones will have to wait until
+  somebody ports Linux to -11 ;-)
 
   If you only intend to mount files from some other Unix over the
   network using NFS, you don't need the System V file system support
@@ -16127,6 +16139,20 @@
   into the card using a utility which is part of the latest
   isdn4k-utils package. Please read the file
   Documentation/isdn/README.act2000 for more information.
+
+Auvertech TurboPAM support
+CONFIG_ISDN_DRV_TPAM
+  This enables support for the Auvertech TurboPAM ISDN-card.
+  For running this card, additional firmware is necessary, which has
+  to be downloaded into the card using a utility which is distributed
+  separately from the Auvertech's web site: http://www.auvertech.fr.
+
+  Please redirect all support questions to support@auvertech.fr.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called tpam.o.
 
 Hypercope HYSDN cards (Champ, Ergo, Metro) support (module)
 CONFIG_HYSDN
diff -urN linux-2.4.6-pre8/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- linux-2.4.6-pre8/Documentation/DocBook/Makefile	Mon May  7 12:14:56 2001
+++ linux/Documentation/DocBook/Makefile	Mon Dec  3 22:50:36 2001
@@ -1,7 +1,7 @@
 BOOKS	:= wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
 	   kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
 	   kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
-	   deviceiobook.sgml
+	   deviceiobook.sgml procfs-guide.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -9,6 +9,7 @@
 IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig
 EPS-parportbook := $(patsubst %.fig, %.eps, $(IMG-parportbook))
 JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook))
+C-procfs-example = procfs_example.sgml
 
 books:	$(BOOKS)
 
@@ -28,6 +29,15 @@
 %.jpeg: %.fig
 	-fig2dev -Ljpeg $< $@
 
+%.sgml: %.c
+	echo "<programlisting>" > $@
+	expand --tabs=8 < $< | \
+	sed -e "s/&/\\&amp;/g" \
+	    -e "s/</\\&lt;/g" \
+	    -e "s/>/\\&gt;/g" >> $@
+	echo "</programlisting>" >> $@
+
+
 $(TOPDIR)/scripts/docproc:
 	$(MAKE) -C $(TOPDIR)/scripts docproc
 
@@ -67,6 +77,9 @@
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/media/video/videodev.c \
 		<videobook.tmpl >videobook.sgml
 
+procfs-guide.sgml:  procfs-guide.tmpl procfs_example.sgml
+	$(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@
+
 APISOURCES :=	$(TOPDIR)/drivers/media/video/videodev.c \
 		$(TOPDIR)/arch/i386/kernel/irq.c \
 		$(TOPDIR)/arch/i386/kernel/mca.c \
@@ -128,6 +141,7 @@
 	-$(RM) $(BOOKS)
 	-$(RM) $(DVI) $(AUX) $(TEX) $(LOG) $(OUT)
 	-$(RM) $(JPG-parportbook) $(EPS-parportbook)
+	-$(RM) $(C-procfs-example)
 
 mrproper: clean
 	-$(RM) $(PS) $(PDF)
diff -urN linux-2.4.6-pre8/Documentation/DocBook/procfs-guide.tmpl linux/Documentation/DocBook/procfs-guide.tmpl
--- linux-2.4.6-pre8/Documentation/DocBook/procfs-guide.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/procfs-guide.tmpl	Mon Dec  3 22:50:36 2001
@@ -0,0 +1,625 @@
+<!-- -*- sgml -*- -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[
+<!ENTITY procfsexample SYSTEM "procfs_example.sgml">
+]>
+
+<book id="LKProcfsGuide">
+  <bookinfo>
+    <title>Linux Kernel Procfs Guide</title>
+
+    <authorgroup>
+      <author>
+	<firstname>Erik</firstname>
+	<othername>(J.A.K.)</othername>
+	<surname>Mouw</surname>
+	<affiliation>
+	  <orgname>Delft University of Technology</orgname>
+	  <orgdiv>Faculty of Information Technology and Systems</orgdiv>
+	  <address>
+            <email>J.A.K.Mouw@its.tudelft.nl</email>
+            <pob>PO BOX 5031</pob>
+            <postcode>2600 GA</postcode>
+            <city>Delft</city>
+            <country>The Netherlands</country>
+          </address>
+	</affiliation>
+      </author>
+    </authorgroup>
+
+    <revhistory>
+      <revision>
+	<revnumber>1.0&nbsp;</revnumber>
+	<date>May 30, 2001</date>
+	<revremark>Initial revision posted to linux-kernel</revremark>
+      </revision>
+      <revision>
+	<revnumber>1.1&nbsp;</revnumber>
+	<date>June 3, 2001</date>
+	<revremark>Revised after comments from linux-kernel</revremark>
+      </revision>
+    </revhistory>
+
+    <copyright>
+      <year>2001</year>
+      <holder>Erik Mouw</holder>
+    </copyright>
+
+
+    <legalnotice>
+      <para>
+        This documentation is free software; you can redistribute it
+        and/or modify it under the terms of the GNU General Public
+        License as published by the Free Software Foundation; either
+        version 2 of the License, or (at your option) any later
+        version.
+      </para>
+      
+      <para>
+        This documentation is distributed in the hope that it will be
+        useful, but WITHOUT ANY WARRANTY; without even the implied
+        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+        PURPOSE.  See the GNU General Public License for more details.
+      </para>
+      
+      <para>
+        You should have received a copy of the GNU General Public
+        License along with this program; if not, write to the Free
+        Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+        MA 02111-1307 USA
+      </para>
+      
+      <para>
+        For more details see the file COPYING in the source
+        distribution of Linux.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+
+
+
+  <toc>
+  </toc>
+
+
+
+
+  <preface>
+    <title>Preface</title>
+
+    <para>
+      This guide describes the use of the procfs file system from
+      within the Linux kernel. The idea to write this guide came up on
+      the #kernelnewbies IRC channel (see <ulink
+      url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>),
+      when Jeff Garzik explained the use of procfs and forwarded me a
+      message Alexander Viro wrote to the linux-kernel mailing list. I
+      agreed to write it up nicely, so here it is.
+    </para>
+
+    <para>
+      I'd like to thank Jeff Garzik
+      <email>jgarzik@mandrakesoft.com</email> and Alexander Viro
+      <email>viro@math.psu.edu</email> for their input, Tim Waugh
+      <email>twaugh@redhat.com</email> for his <ulink
+      url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
+      and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
+      proofreading.
+    </para>
+
+    <para>
+      This documentation was written while working on the LART
+      computing board (<ulink
+      url="http://www.lart.tudelft.nl/">http://www.lart.tudelft.nl/</ulink>),
+      which is sponsored by the Mobile Multi-media Communications
+      (<ulink
+      url="http://www.mmc.tudelft.nl/">http://www.mmc.tudelft.nl/</ulink>)
+      and Ubiquitous Communications (<ulink
+      url="http://www.ubicom.tudelft.nl/">http://www.ubicom.tudelft.nl/</ulink>)
+      projects.
+    </para>
+
+    <para>
+      Erik
+    </para>
+  </preface>
+
+
+
+
+  <chapter id="intro">
+    <title>Introduction</title>
+
+    <para>
+      The <filename class="directory">/proc</filename> file system
+      (procfs) is a special file system in the linux kernel. It's a
+      virtual file system: it is not associated with a block device
+      but exists only in memory. The files in the procfs are there to
+      allow userland programs access to certain information from the
+      kernel (like process information in <filename
+      class="directory">/proc/[0-9]+/</filename>), but also for debug
+      purposes (like <filename>/proc/ksyms</filename>).
+    </para>
+
+    <para>
+      This guide describes the use of the procfs file system from
+      within the Linux kernel. It starts by introducing all relevant
+      functions to manage the files within the file system. After that
+      it shows how to communicate with userland, and some tips and
+      tricks will be pointed out. Finally a complete example will be
+      shown.
+    </para>
+
+    <para>
+      Note that the files in <filename
+      class="directory">/proc/sys</filename> are sysctl files: they
+      don't belong to procfs and are governed by a completely
+      different API described in the Kernel API book.
+    </para>
+  </chapter>
+
+
+
+
+  <chapter id="managing">
+    <title>Managing procfs entries</title>
+    
+    <para>
+      This chapter describes the functions that various kernel
+      components use to populate the procfs with files, symlinks,
+      device nodes, and directories.
+    </para>
+
+    <para>
+      A minor note before we start: if you want to use any of the
+      procfs functions, be sure to include the correct header file! 
+      This should be one of the first lines in your code:
+    </para>
+
+    <programlisting>
+#include &lt;linux/proc_fs.h&gt;
+    </programlisting>
+
+
+
+
+    <sect1 id="regularfile">
+      <title>Creating a regular file</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        This function creates a regular file with the name
+        <parameter>name</parameter>, file mode
+        <parameter>mode</parameter> in the directory
+        <parameter>parent</parameter>. To create a file in the root of
+        the procfs, use <constant>NULL</constant> as
+        <parameter>parent</parameter> parameter. When successful, the
+        function will return a pointer to the freshly created
+        <structname>struct proc_dir_entry</structname>; otherwise it
+        will return <constant>NULL</constant>. <xref
+        linkend="userland"> describes how to do something useful with
+        regular files.
+      <para>
+
+      <para>
+        Note that it is specifically supported that you can pass a
+        path that spans multiple directories. For example
+        <function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>)
+        will create the <filename class="directory">via0</filename>
+        directory if necessary, with standard
+        <constant>0755</constant> permissions.
+      </para>
+
+    <para>
+      If you only want to be able to read the file, the function
+      <function>create_proc_read_entry</function> described in <xref
+      linkend="convenience"> may be used to create and initialise
+      the procfs entry in one single call.
+    </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a symlink</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry*
+	  <function>proc_symlink</function></funcdef> <paramdef>const
+	  char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry*
+	  <parameter>parent</parameter></paramdef> <paramdef>const
+	  char* <parameter>dest</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        This creates a symlink in the procfs directory
+        <parameter>parent</parameter> that points from
+        <parameter>name</parameter> to
+        <parameter>dest</parameter>. This translates in userland to
+        <literal>ln -s</literal> <parameter>dest</parameter>
+        <parameter>name</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a device</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>proc_mknod</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	  <paramdef>kdev_t <parameter>rdev</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        Creates a device file <parameter>name</parameter> with mode
+        <parameter>mode</parameter> in the procfs directory
+        <parameter>parent</parameter>. The device file will work on
+        the device <parameter>rdev</parameter>, which can be generated
+        by using the <literal>MKDEV</literal> macro from
+        <literal>linux/kdev_t.h</literal>. The
+        <parameter>mode</parameter> parameter
+        <emphasis>must</emphasis> contain <constant>S_IFBLK</constant>
+        or <constant>S_IFCHR</constant> to create a device
+        node. Compare with userland <literal>mknod
+        --mode=</literal><parameter>mode</parameter>
+        <parameter>name</parameter> <parameter>rdev</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a directory</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        Create a directory <parameter>name</parameter> in the procfs
+        directory <parameter>parent</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Removing an entry</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>void <function>remove_proc_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        Removes the entry <parameter>name</parameter> in the directory
+        <parameter>parent</parameter> from the procfs. Entries are
+        removed by their <emphasis>name</emphasis>, not by the
+        <structname>struct proc_dir_entry</structname> returned by the
+        various create functions. Note that this function doesn't
+        recursively remove entries.
+      </para>
+
+      <para>
+        Be sure to free the <structfield>data</structfield> entry from
+        the <structname>struct proc_dir_entry</structname> before
+        <function>remove_proc_entry</function> is called (that is: if
+        there was some <structfield>data</structfield> allocated, of
+        course). See <xref linkend="usingdata"> for more information
+        on using the <structfield>data</structfield> entry.
+      </para>
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="userland">
+    <title>Communicating with userland</title>
+    
+    <para>
+       Instead of reading (or writing) information directly from
+       kernel memory, procfs works with <emphasis>call back
+       functions</emphasis> for files: functions that are called when
+       a specific file is being read or written. Such functions have
+       to be initialised after the procfs file is created by setting
+       the <structfield>read_proc</structfield> and/or
+       <structfield>write_proc</structfield> fields in the
+       <structname>struct proc_dir_entry*</structname> that the
+       function <function>create_proc_entry</function> returned:
+    </para>
+
+    <programlisting>
+struct proc_dir_entry* entry;
+
+entry->read_proc = read_proc_foo;
+entry->write_proc = write_proc_foo;
+    </programlisting>
+
+    <para>
+      If you only want to use a the
+      <structfield>read_proc</structfield>, the function
+      <function>create_proc_read_entry</function> described in <xref
+      linkend="convenience"> may be used to create and initialise the
+      procfs entry in one single call.
+    </para>
+
+
+
+    <sect1>
+      <title>Reading data</title>
+
+      <para>
+        The read function is a call back function that allows userland
+        processes to read data from the kernel. The read function
+        should have the following format:
+      </para>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>int <function>read_func</function></funcdef>
+	  <paramdef>char* <parameter>page</parameter></paramdef>
+	  <paramdef>char** <parameter>start</parameter></paramdef>
+	  <paramdef>off_t <parameter>off</parameter></paramdef>
+	  <paramdef>int <parameter>count</parameter></paramdef>
+	  <paramdef>int* <parameter>eof</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The read function should write its information into the
+        <parameter>page</parameter>. For proper use, the function
+        should start writing at an offset of
+        <parameter>off</parameter> in <parameter>page</parameter> and
+        write at most <parameter>count</parameter> bytes, but because
+        most read functions are quite simple and only return a small
+        amount of information, these two parameters are usually
+        ignored (it breaks pagers like <literal>more</literal> and
+        <literal>less</literal>, but <literal>cat</literal> still
+        works).
+      </para>
+
+      <para>
+        If the <parameter>off</parameter> and
+        <parameter>count</parameter> parameters are properly used,
+        <parameter>eof</parameter> should be used to signal that the
+        end of the file has been reached by writing
+        <literal>1</literal> to the memory location
+        <parameter>eof</parameter> points to.
+      </para>
+
+      <para>
+        The parameter <parameter>start</parameter> doesn't seem to be
+        used anywhere in the kernel. The <parameter>data</parameter>
+        parameter can be used to create a single call back function for
+        several files, see <xref linkend="usingdata">.
+      </para>
+
+      <para>
+        The <function>read_func</function> function must return the
+        number of bytes written into the <parameter>page</parameter>.
+      </para>
+
+      <para>
+        <xref linkend="example"> shows how to use a read call back
+        function.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Writing data</title>
+
+      <para>
+        The write call back function allows a userland process to write
+        data to the kernel, so it has some kind of control over the
+        kernel. The write function should have the following format:
+      </para>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>int <function>write_func</function></funcdef>
+	  <paramdef>struct file* <parameter>file</parameter></paramdef>
+	  <paramdef>const char* <parameter>buffer</parameter></paramdef>
+	  <paramdef>unsigned long <parameter>count</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The write function should read <parameter>count</parameter>
+        bytes at maximum from the <parameter>buffer</parameter>. Note
+        that the <parameter>buffer</parameter> doesn't live in the
+        kernel's memory space, so it should first be copied to kernel
+        space with <function>copy_from_user</function>. The
+        <parameter>file</parameter> parameter is usually
+        ignored. <xref linkend="usingdata"> shows how to use the
+        <parameter>data</parameter> parameter.
+      </para>
+
+      <para>
+        Again, <xref linkend="example"> shows how to use this call back
+        function.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1 id="usingdata">
+      <title>A single call back for many files</title>
+
+      <para>
+         When a large number of almost identical files is used, it's
+         quite inconvenient to use a separate call back function for
+         each file. A better approach is to have a single call back
+         function that distinguishes between the files by using the
+         <structfield>data</structfield> field in <structname>struct
+         proc_dir_entry</structname>. First of all, the
+         <structfield>data</structfield> field has to be initialised:
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+struct my_file_data *file_data;
+
+file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
+entry->data = file_data;
+      </programlisting>
+     
+      <para>
+          The <structfield>data</structfield> field is a <type>void
+          *</type>, so it can be initialised with anything.
+      </para>
+
+      <para>
+        Now that the <structfield>data</structfield> field is set, the
+        <function>read_proc</function> and
+        <function>write_proc</function> can use it to distinguish
+        between files because they get it passed into their
+        <parameter>data</parameter> parameter:
+      </para>
+
+      <programlisting>
+int foo_read_func(char *page, char **start, off_t off,
+                  int count, int *eof, void *data)
+{
+        int len;
+
+        if(data == file_data) {
+                /* special case for this file */
+        } else {
+                /* normal processing */
+        }
+
+        return len;
+}
+      </programlisting>
+
+      <para>
+        Be sure to free the <structfield>data</structfield> data field
+        when removing the procfs entry.
+      </para>
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="tips">
+    <title>Tips and tricks</title>
+
+
+
+
+    <sect1 id="convenience">
+      <title>Convenience functions</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	  <paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        This function creates a regular file in exactly the same way
+        as <function>create_proc_entry</function> from <xref
+        linkend="regularfile"> does, but also allows to set the read
+        function <parameter>read_proc</parameter> in one call. This
+        function can set the <parameter>data</parameter> as well, like
+        explained in <xref linkend="usingdata">.
+      </para>
+    </sect1>
+
+
+
+    <sect1>
+      <title>Modules</title>
+
+      <para>
+        If procfs is being used from within a module, be sure to set
+        the <structfield>owner</structfield> field in the
+        <structname>struct proc_dir_entry</structname> to
+        <constant>THIS_MODULE</constant>.
+      <para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+
+entry->owner = THIS_MODULE;
+      </programlisting>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Mode and ownership</title>
+
+      <para>
+        Sometimes it is useful to change the mode and/or ownership of
+        a procfs entry. Here is an example that shows how to achieve
+        that:
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+
+entry->mode =  S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
+entry->uid = 0;
+entry->gid = 100;
+      </programlisting>
+
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="example">
+    <title>Example</title>
+
+    <!-- be careful with the example code: it shouldn't be wider than
+    approx. 60 columns, or otherwise it won't fit properly on a page
+    -->
+
+&procfsexample;
+
+  </chapter>
+</book>
diff -urN linux-2.4.6-pre8/Documentation/DocBook/procfs_example.c linux/Documentation/DocBook/procfs_example.c
--- linux-2.4.6-pre8/Documentation/DocBook/procfs_example.c	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/procfs_example.c	Mon Dec  3 22:50:36 2001
@@ -0,0 +1,249 @@
+/*
+ * procfs_example.c: an example proc interface
+ *
+ * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This file accompanies the procfs-guide in the Linux kernel
+ * source. Its main use is to demonstrate the concepts and
+ * functions described in the guide.
+ *
+ * This software has been developed while working on the LART
+ * computing board (http://www.lart.tudelft.nl/), which is
+ * sponsored by the Mobile Multi-media Communications
+ * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications 
+ * (http://www.ubicom.tudelft.nl/) projects.
+ *
+ * The author can be reached at:
+ *
+ *  Erik Mouw
+ *  Information and Communication Theory Group
+ *  Faculty of Information Technology and Systems
+ *  Delft University of Technology
+ *  P.O. Box 5031
+ *  2600 GA Delft
+ *  The Netherlands
+ *
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+
+#define MODULE_VERSION "1.0"
+#define MODULE_NAME "procfs_example"
+
+#define FOOBAR_LEN 8
+
+struct fb_data_t {
+	char name[FOOBAR_LEN + 1];
+	char value[FOOBAR_LEN + 1];
+};
+
+
+static struct proc_dir_entry *example_dir, *foo_file,
+	*bar_file, *jiffies_file, *tty_device, *symlink;
+
+
+struct fb_data_t foo_data, bar_data;
+
+
+static int proc_read_jiffies(char *page, char **start,
+			     off_t off, int count,
+			     int *eof, void *data)
+{
+	int len;
+
+	MOD_INC_USE_COUNT;
+	
+	len = sprintf(page, "jiffies = %ld\n",
+                      jiffies);
+
+	MOD_DEC_USE_COUNT;
+
+	return len;
+}
+
+
+static int proc_read_foobar(char *page, char **start,
+			    off_t off, int count, 
+			    int *eof, void *data)
+{
+	int len;
+	struct fb_data_t *fb_data = (struct fb_data_t *)data;
+
+	MOD_INC_USE_COUNT;
+	
+	len = sprintf(page, "%s = '%s'\n", 
+		      fb_data->name, fb_data->value);
+
+	MOD_DEC_USE_COUNT;
+
+	return len;
+}
+
+
+static int proc_write_foobar(struct file *file,
+			     const char *buffer,
+			     unsigned long count, 
+			     void *data)
+{
+	int len;
+	struct fb_data_t *fb_data = (struct fb_data_t *)data;
+
+	MOD_INC_USE_COUNT;
+
+	if(count > FOOBAR_LEN)
+		len = FOOBAR_LEN;
+	else
+		len = count;
+
+	if(copy_from_user(fb_data->value, buffer, len)) {
+		MOD_DEC_USE_COUNT;
+		return -EFAULT;
+	}
+
+	fb_data->value[len] = '\0';
+
+	MOD_DEC_USE_COUNT;
+
+	return len;
+}
+
+
+static int __init init_procfs_example(void)
+{
+	int rv = 0;
+
+	/* create directory */
+	example_dir = proc_mkdir(MODULE_NAME, NULL);
+	if(example_dir == NULL) {
+		rv = -ENOMEM;
+		goto out;
+	}
+	
+	example_dir->owner = THIS_MODULE;
+	
+	/* create jiffies using convenience function */
+	jiffies_file = create_proc_read_entry("jiffies", 
+					      0444, example_dir, 
+					      proc_read_jiffies,
+					      NULL);
+	if(jiffies_file == NULL) {
+		rv  = -ENOMEM;
+		goto no_jiffies;
+	}
+
+	jiffies_file->owner = THIS_MODULE;
+
+	/* create foo and bar files using same callback
+	 * functions 
+	 */
+	foo_file = create_proc_entry("foo", 0644, example_dir);
+	if(foo_file == NULL) {
+		rv = -ENOMEM;
+		goto no_foo;
+	}
+
+	strcpy(foo_data.name, "foo");
+	strcpy(foo_data.value, "foo");
+	foo_file->data = &foo_data;
+	foo_file->read_proc = proc_read_foobar;
+	foo_file->write_proc = proc_write_foobar;
+	foo_file->owner = THIS_MODULE;
+		
+	bar_file = create_proc_entry("bar", 0644, example_dir);
+	if(bar_file == NULL) {
+		rv = -ENOMEM;
+		goto no_bar;
+	}
+
+	strcpy(bar_data.name, "bar");
+	strcpy(bar_data.value, "bar");
+	bar_file->data = &bar_data;
+	bar_file->read_proc = proc_read_foobar;
+	bar_file->write_proc = proc_write_foobar;
+	bar_file->owner = THIS_MODULE;
+		
+	/* create tty device */
+	tty_device = proc_mknod("tty", S_IFCHR | 0666,
+				example_dir, MKDEV(5, 0));
+	if(tty_device == NULL) {
+		rv = -ENOMEM;
+		goto no_tty;
+	}
+	
+	tty_device->owner = THIS_MODULE;
+
+	/* create symlink */
+	symlink = proc_symlink("jiffies_too", example_dir, 
+			       "jiffies");
+	if(symlink == NULL) {
+		rv = -ENOMEM;
+		goto no_symlink;
+	}
+
+	symlink->owner = THIS_MODULE;
+
+	/* everything OK */
+	printk(KERN_INFO "%s %s initialised\n",
+	       MODULE_NAME, MODULE_VERSION);
+	return 0;
+
+no_symlink:
+	remove_proc_entry("tty", example_dir);
+no_tty:
+	remove_proc_entry("bar", example_dir);
+no_bar:
+	remove_proc_entry("foo", example_dir);
+no_foo:
+	remove_proc_entry("jiffies", example_dir);
+no_jiffies:			      
+	remove_proc_entry(MODULE_NAME, NULL);
+out:
+	return rv;
+}
+
+
+static void __exit cleanup_procfs_example(void)
+{
+	remove_proc_entry("jiffies_too", example_dir);
+	remove_proc_entry("tty", example_dir);
+	remove_proc_entry("bar", example_dir);
+	remove_proc_entry("foo", example_dir);
+	remove_proc_entry("jiffies", example_dir);
+	remove_proc_entry(MODULE_NAME, NULL);
+
+	printk(KERN_INFO "%s %s removed\n",
+	       MODULE_NAME, MODULE_VERSION);
+}
+
+
+module_init(init_procfs_example);
+module_exit(cleanup_procfs_example);
+
+MODULE_AUTHOR("Erik Mouw");
+MODULE_DESCRIPTION("procfs examples");
+
+EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.6-pre8/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt
--- linux-2.4.6-pre8/Documentation/fb/matroxfb.txt	Sat Nov 11 18:47:40 2000
+++ linux/Documentation/fb/matroxfb.txt	Mon Dec  3 22:50:36 2001
@@ -173,9 +173,9 @@
 mtrr     - enables write combining on frame buffer. It speeds up video accesses
            much. It is default. You must have MTRR support enabled in kernel
 	   and your CPU must have MTRR (f.e. Pentium II have them).
-sgram    - tells to driver that you have G200 with SGRAM memory. It has no
+sgram    - tells to driver that you have Gxx0 with SGRAM memory. It has no
            effect without `init'.
-sdram    - tells to driver that you have G200 with SDRAM memory.
+sdram    - tells to driver that you have Gxx0 with SDRAM memory.
            It is a default.
 inv24    - change timings parameters for 24bpp modes on Millenium and
            Millenium II. Specify this if you see strange color shadows around
@@ -279,7 +279,7 @@
  + 24bpp does not support correctly XF-FBDev on big-endian architectures.
  + interlaced text mode is not supported; it looks like hardware limitation,
    but I'm not sure.
- + G200 SGRAM/SDRAM is not autodetected.
+ + Gxx0 SGRAM/SDRAM is not autodetected.
  + maybe more...
 And following misfeatures:
  + SVGALib does not restore screen on exit.
@@ -336,7 +336,7 @@
 
 ACCEL, nofastfont
         8x16                 12x22                6x11
-	Millennium I  G200   Millennium I  G200    Millennium I G200
+	Millennium I  G200   Millennium I  G200   Millennium I  G200
 8bpp     7.79         7.24   13.55         7.78   30.00        21.01
 16bpp    9.13         7.78   16.16         7.78   30.00        21.01
 24bpp   14.17        10.72   18.69        10.24   34.99        21.01
@@ -344,7 +344,7 @@
 
 ACCEL, fastfont
         8x16                 12x22                6x11
-	Millennium I  G200    Millennium I G200   Millennium I  G200
+	Millennium I  G200   Millennium I  G200   Millennium I  G200
 8bpp     8.41         6.01    6.54         4.37   16.00        10.51
 16bpp    9.54         9.12    8.76         6.17   17.52        14.01
 24bpp   15.00        12.36   11.67        10.00   22.01        18.32
@@ -355,6 +355,8 @@
 	Millennium I  G200
 TEXT     3.29         1.50
 
+* Yes, it is slower than Millennium I.
+
 
 Dualhead G400
 =============
@@ -376,7 +378,22 @@
  + if you compiled it as module, you must insert i2c-matroxfb, matroxfb_maven
    and matroxfb_crtc2 into kernel.
 
+
+Dualhead G450
+=============
+Driver supports dualhead G450 with some limitations:
+ + secondary head shares videomemory with primary head. It is not problem
+   if you have 32MB of videoram, but if you have only 16MB, you may have
+   to think twice before choosing videomode.
+ + due to hardware limitation, secondary head can use only 16 and 32bpp
+   videomodes.
+ + secondary head is not accelerated.
+ + secondary head always powerups in 640x480@60-32 videomode. You have to use
+   fbset to change this mode.
+ + TV output is not supported
+ + kernel is not fully multihead ready, so some things are impossible to do.
+ + if you compiled it as module, you must insert matroxfb_g450 and matroxfb_crtc2
+   into kernel.
 	
-* Yes, it is slower than Millennium I.
 --
 Petr Vandrovec <vandrove@vc.cvut.cz>
diff -urN linux-2.4.6-pre8/Documentation/networking/TODO linux/Documentation/networking/TODO
--- linux-2.4.6-pre8/Documentation/networking/TODO	Mon Dec  3 22:50:26 2001
+++ linux/Documentation/networking/TODO	Mon Dec  3 22:50:36 2001
@@ -14,3 +14,5 @@
 
 * Add ETHTOOL_GDRVINFO ioctl support to all ethernet drivers.
 
+* dmfe PCI DMA is totally wrong and only works on x86
+
diff -urN linux-2.4.6-pre8/Documentation/networking/sk98lin.txt linux/Documentation/networking/sk98lin.txt
--- linux-2.4.6-pre8/Documentation/networking/sk98lin.txt	Fri Sep 15 14:34:19 2000
+++ linux/Documentation/networking/sk98lin.txt	Mon Dec  3 22:50:36 2001
@@ -1,16 +1,17 @@
-(C)Copyright 1999-2000 SysKonnect.
+(C)Copyright 1999-2001 SysKonnect GmbH.
+All rights reserved
 ===========================================================================
 
-sk98lin.txt created 12-Sept-2000
+sk98lin.txt created 28-May-2001
 
-Readme File for sk98lin.o v3.05
-SK-NET Gigabit Ethernet Adapter SK-98xx Driver for Linux
+Readme File for sk98lin v4.06
+SK-NET Gigabit Ethernet PCI driver for LINUX
 
 This file contains
 (1) OVERVIEW
 (2) REQUIRED FILES
 (3) INSTALLATION
-(4) INCLUSION OF THE ADAPTER AT SYSTEM START
+(4) INCLUSION OF ADAPTER AT SYSTEM START
 (5) DRIVER PARAMETERS
 (6) LARGE FRAME SUPPORT
 (7) TROUBLESHOOTING
@@ -19,13 +20,12 @@
 ===========================================================================
 
 
-
 (1) OVERVIEW
 ============
 
 The sk98lin driver supports the SysKonnect SK-NET Gigabit Ethernet
 Adapter SK-98xx family on Linux 2.2.x and above.
-It has been tested with Linux on Intel/x86, ALPHA and UltraSPARC machines.
+It has been tested with Linux on Intel/x86 machines.
 From v3.02 on, the driver is integrated in the linux kernel source.
 ***
 
@@ -64,8 +64,8 @@
    "make modules_install".
    Reboot your system.
 
-4) Load the module manually by entering:
-       insmod sk98lin.o
+2) Load the module manually by entering:
+       modprobe sk98lin
    If the SysKonnect SK-98xx adapter is installed in your
    computer and you have a /proc filesystem, running the command
    'more /proc/net/dev' should produce an output containing a
@@ -75,7 +75,7 @@
    
    NOTE 1: If you have more than one SysKonnect SK-98xx adapter, the
            adapters will be listed as 'eth0', 'eth1', 'eth2', etc.
-           For each adapter, repeat the steps 5) and 6).
+           For each adapter, repeat the steps 3) and 4).
    NOTE 2: If you have other Ethernet adapters installed,
            your SysKonnect SK-98xx adapter can be mapped to 'eth1' or
 	   'eth2' ...
@@ -84,7 +84,7 @@
 	   for each adapter that is found, containing the
 	   corresponding 'ethX'.
 
-5) Select an IP address and assign it to the respective adapter by
+3) Select an IP address and assign it to the respective adapter by
    entering:
        ifconfig eth0 <ip-address>
    This causes the adapter to connect to the ethernet. The solitary
@@ -99,22 +99,22 @@
    NOTE: If you are in doubt about IP addresses, ask your network
          administrator for assistance.
 
-6) Your adapter should now be fully operational.
+4) Your adapter should now be fully operational.
    Use 'ping <otherstation>' to verify the connection to other
    computers on your network.
-   By entering 'ifconfig', you can check the number of packets sent
-   and received by your adapter and additional some other information
-   regarding the adapter configuration.
+   By viewing /proc/net/sk98lin/[devicename], you can check some 
+   information regarding to the adapter configuration.
+
 
-7) The driver module can be stopped and unloaded using the following
+5) The driver module can be stopped and unloaded using the following
    commands:
        ifconfig eth0 down
        rmmod sk98lin
 ***
 
 
-(4) INCLUSION OF THE ADAPTER AT SYSTEM START
-============================================
+(4) INCLUSION OF ADAPTER AT SYSTEM START
+========================================
 
 Since a large number of different Linux distributions are 
 available, we are unable to describe a general installation procedure
@@ -129,7 +129,7 @@
 =====================
 
 Parameters can be set at the command line while loading the
-module with 'insmod'. The configuration tools of some distributions
+module with 'modprobe'. The configuration tools of some distributions
 can also give parameters to the driver module.
 If you use the kernel module loader, you can set driver parameters
 in the file /etc/modules.conf (or old name: /etc/conf.modules).
@@ -138,12 +138,12 @@
 options sk98lin ...
 
 For "...", use the same syntax as described below for the command
-line parameters of insmod.
+line paramaters of modprobe.
 You either have to reboot your computer or unload and reload
 the driver to activate the new parameters.
 The syntax of the driver parameters is:
 
-insmod sk98lin parameter=value1[,value2[,value3...]]
+modprobe sk98lin parameter=value1[,value2[,value3...]]
 
 value1 is for the first adapter, value2 for the second one etc.
 All Parameters are case sensitive, so write them exactly as
@@ -156,7 +156,7 @@
 	adapter to FULL and on Port A of the second adapter to HALF.
 	You must enter:
 
-	insmod sk98lin.o AutoNeg_A=On,Off DupCap_A=Full,Half
+	modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
 
 NOTE: The number of adapters that can be configured this way is
       limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
@@ -187,7 +187,7 @@
   this port is not "Sense". If autonegotiation is "On", all
   three values are possible. If it is "Off", only "Full" and
   "Half" are allowed.
-  It is useful if your link partner does not support all
+  It is usefull if your link partner does not support all
   possible combinations.
 
 - Flow Control
@@ -234,7 +234,7 @@
 
 - RLMT (Redundant Link Management Technology) Mode
   Parameter:	RlmtMode
-  Values:	CheckLinkState,CheckLocalPort, CheckSeg
+  Values:	CheckLinkState,CheckLocalPort, CheckSeg, DualNet
   Default:	CheckLinkState
 
   RLMT (the driver part that decides which port to use) knows three
@@ -257,6 +257,13 @@
    Ethernet switches installed in your network that have been configured
    to use the Spanning Tree protocol.
 
+-- DualNet - Both ports A and B are used as separate devices at the same
+   time. So if you have a dual port adapter, port A will show up as eth0
+   and port B as eth1. Both ports can be used independend with distinct
+   IP addresses.
+   The preferred port setting is not used. Rlmt is turned off.
+   
+
   NOTE: The modes CheckLocalPort and CheckSeg are meant to operate in
         configurations where a network path between the ports on one
         adapter exists. Especially, they are not designed to work where
@@ -269,7 +276,7 @@
 
 Large frames (also called jumbo frames) are now supported by the
 driver. This can result in a greatly improved throughput if
-transferring large amounts of data.
+transfering large amounts of data.
 To enable large frames, set the MTU (maximum transfer unit)
 of the interface to the value you wish (up to 9000). The command
 for this is:
@@ -285,7 +292,7 @@
 You can switch back to the standard ethernet frame size with:
   ifconfig eth0 mtu 1500
 
-To make this setting persistent, add a script with the 'ifconfig'
+To make this setting persitent, add a script with the 'ifconfig'
 line to the system startup sequence (named something like "S99sk98lin"
 in /etc/rc.d/rc2.d).
 ***
@@ -373,11 +380,27 @@
 (8) HISTORY
 ===========
 
-VERSION 3.05 (In-Kernel version)
+VERSION 4.02 (In-Kernel version)
+New Features:
+- Add Kernel 2.4 changes
+Known limitations:
+- None
+
+VERSION 4.01 (In-Kernel version)
+Problems fixed:
+- Full statistics support for DualNet mode
+Known limitations:
+- None
+
+VERSION 4.00 (In-Kernel version)
 Problems fixed:
-- Failed for multiple adapters in kernel 2.4.0
-New features:
-- New versions of several common modules
+- Memory leak found 
+New Features:
+- Proc filesystem integration
+- DualNet functionality integrated
+- Rlmt networks added
+Known limitations:
+- statistics partially incorrect in DualNet mode
 
 VERSION 3.04 (In-Kernel version)
 Problems fixed:
diff -urN linux-2.4.6-pre8/Makefile linux/Makefile
--- linux-2.4.6-pre8/Makefile	Mon Dec  3 22:50:26 2001
+++ linux/Makefile	Mon Dec  3 22:50:36 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 6
-EXTRAVERSION =-pre8
+EXTRAVERSION =-pre9
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.6-pre8/arch/alpha/boot/bootloader.lds linux/arch/alpha/boot/bootloader.lds
--- linux-2.4.6-pre8/arch/alpha/boot/bootloader.lds	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/boot/bootloader.lds	Mon Dec  3 22:50:36 2001
@@ -6,7 +6,7 @@
   .text : { *(.text) }
   _etext = .;
   PROVIDE (etext = .);
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .data : { *(.data) CONSTRUCTORS }
   .got : { *(.got) }
   .sdata : { *(.sdata) }
diff -urN linux-2.4.6-pre8/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c
--- linux-2.4.6-pre8/arch/alpha/kernel/irq_alpha.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/alpha/kernel/irq_alpha.c	Mon Dec  3 22:50:37 2001
@@ -18,6 +18,8 @@
 unsigned long __irq_attempt[NR_IRQS];
 #endif
 
+extern unsigned long irq_err_count;
+
 /* Hack minimum IPL during interrupt processing for broken hardware.  */
 #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
 int __min_ipl;
diff -urN linux-2.4.6-pre8/arch/alpha/vmlinux.lds.in linux/arch/alpha/vmlinux.lds.in
--- linux-2.4.6-pre8/arch/alpha/vmlinux.lds.in	Mon Jun 26 11:26:56 2000
+++ linux/arch/alpha/vmlinux.lds.in	Mon Dec  3 22:50:37 2001
@@ -53,7 +53,7 @@
   /* Global data */
   _data = .;
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .data : { *(.data) CONSTRUCTORS }
   .got : { *(.got) }
   .sdata : { *(.sdata) }
diff -urN linux-2.4.6-pre8/arch/arm/boot/compressed/vmlinux.lds.in linux/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-2.4.6-pre8/arch/arm/boot/compressed/vmlinux.lds.in	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/vmlinux.lds.in	Mon Dec  3 22:50:37 2001
@@ -24,6 +24,7 @@
     *(.fixup)
     *(.gnu.warning)
     *(.rodata)
+    *(.rodata.*)
     *(.glue_7)
     *(.glue_7t)
     input_data = .;
diff -urN linux-2.4.6-pre8/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in
--- linux-2.4.6-pre8/arch/arm/vmlinux-armo.lds.in	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/vmlinux-armo.lds.in	Mon Dec  3 22:50:37 2001
@@ -47,6 +47,7 @@
 			*(.gnu.warning)
 			*(.text.lock)	/* out-of-line lock text */
 			*(.rodata)
+			*(.rodata.*)
 			*(.glue_7)
 			*(.glue_7t)
 			*(.kstrtab)
diff -urN linux-2.4.6-pre8/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- linux-2.4.6-pre8/arch/arm/vmlinux-armv.lds.in	Wed May 16 15:25:16 2001
+++ linux/arch/arm/vmlinux-armv.lds.in	Mon Dec  3 22:50:37 2001
@@ -42,6 +42,7 @@
 			*(.gnu.warning)
 			*(.text.lock)	/* out-of-line lock text */
 			*(.rodata)
+			*(.rodata.*)
 			*(.glue_7)
 			*(.glue_7t)
 		*(.got)			/* Global offset table		*/
diff -urN linux-2.4.6-pre8/arch/cris/boot/compressed/decompress.ld linux/arch/cris/boot/compressed/decompress.ld
--- linux-2.4.6-pre8/arch/cris/boot/compressed/decompress.ld	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/compressed/decompress.ld	Mon Dec  3 22:50:37 2001
@@ -13,6 +13,7 @@
 		_stext = . ;
 		*(.text)
 		*(.rodata)
+		*(.rodata.*)
 		_etext = . ;
 	} > dram
 	.data :
diff -urN linux-2.4.6-pre8/arch/cris/cris.ld linux/arch/cris/cris.ld
--- linux-2.4.6-pre8/arch/cris/cris.ld	Tue May  1 16:04:56 2001
+++ linux/arch/cris/cris.ld	Mon Dec  3 22:50:37 2001
@@ -24,7 +24,7 @@
 		*(.fixup)
 		*(.text.__*)
 		*(.rodata)
-		*(.rodata.__*)
+		*(.rodata.*)
 	}
 
 	. = ALIGN(4);                /* Exception table */
diff -urN linux-2.4.6-pre8/arch/i386/boot/tools/build.c linux/arch/i386/boot/tools/build.c
--- linux-2.4.6-pre8/arch/i386/boot/tools/build.c	Mon Mar 13 09:35:06 2000
+++ linux/arch/i386/boot/tools/build.c	Mon Dec  3 22:50:37 2001
@@ -154,7 +154,7 @@
 	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
 		die("System is too big. Try using %smodules.",
 			is_big_kernel ? "" : "bzImage or ");
-	if (sys_size > 0xffff)
+	if (sys_size > 0xefff)
 		fprintf(stderr,"warning: kernel is too big for standalone boot "
 		    "from floppy\n");
 	while (sz > 0) {
diff -urN linux-2.4.6-pre8/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.6-pre8/arch/i386/defconfig	Mon Dec  3 22:50:27 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 22:50:37 2001
@@ -374,6 +374,7 @@
 # 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
@@ -384,6 +385,8 @@
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
 # CONFIG_TULIP is not set
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
 # CONFIG_DE4X5 is not set
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
@@ -410,6 +413,7 @@
 # Ethernet (1000 Mbit)
 #
 # CONFIG_ACENIC is not set
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
@@ -538,6 +542,7 @@
 CONFIG_AGP_AMD=y
 CONFIG_AGP_SIS=y
 CONFIG_AGP_ALI=y
+# CONFIG_AGP_SWORKS is not set
 CONFIG_DRM=y
 CONFIG_DRM_TDFX=y
 # CONFIG_DRM_GAMMA is not set
@@ -595,7 +600,6 @@
 # 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
@@ -656,6 +660,7 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
 
diff -urN linux-2.4.6-pre8/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- linux-2.4.6-pre8/arch/i386/kernel/bluesmoke.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/i386/kernel/bluesmoke.c	Mon Dec  3 22:50:37 2001
@@ -233,7 +233,7 @@
 	}
 }
 
-static void __init mcheck_disable(char *str, int *unused)
+static int __init mcheck_disable(char *str)
 {
 	mce_disabled = 1;
 	return 1;
diff -urN linux-2.4.6-pre8/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- linux-2.4.6-pre8/arch/i386/kernel/i386_ksyms.c	Tue May 15 08:46:20 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Dec  3 22:50:37 2001
@@ -90,9 +90,6 @@
 EXPORT_SYMBOL_NOVERS(__get_user_1);
 EXPORT_SYMBOL_NOVERS(__get_user_2);
 EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
 
 EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
diff -urN linux-2.4.6-pre8/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile
--- linux-2.4.6-pre8/arch/i386/lib/Makefile	Wed Apr 25 13:31:03 2001
+++ linux/arch/i386/lib/Makefile	Mon Dec  3 22:50:37 2001
@@ -8,7 +8,7 @@
 L_TARGET = lib.a
 
 obj-y = checksum.o old-checksum.o delay.o \
-	usercopy.o getuser.o putuser.o \
+	usercopy.o getuser.o \
 	memcpy.o strstr.o
 
 obj-$(CONFIG_X86_USE_3DNOW) += mmx.o
diff -urN linux-2.4.6-pre8/arch/i386/lib/putuser.S linux/arch/i386/lib/putuser.S
--- linux-2.4.6-pre8/arch/i386/lib/putuser.S	Mon Jan 12 13:37:26 1998
+++ linux/arch/i386/lib/putuser.S	Wed Dec 31 16:00:00 1969
@@ -1,71 +0,0 @@
-/*
- * __put_user functions.
- *
- * (C) Copyright 1998 Linus Torvalds
- *
- * These functions have a non-standard call interface
- * to make them more efficient.
- */
-
-/*
- * __put_user_X
- *
- * Inputs:	%eax contains the address
- *		%edx contains the value
- *
- * Outputs:	%eax is error code (0 or -EFAULT)
- *		%ecx is corrupted (will contain "current_task").
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-addr_limit = 12
-
-.text
-.align 4
-.globl __put_user_1
-__put_user_1:
-	movl %esp,%ecx
-	andl $0xffffe000,%ecx
-	cmpl addr_limit(%ecx),%eax
-	jae bad_put_user
-1:	movb %dl,(%eax)
-	xorl %eax,%eax
-	ret
-
-.align 4
-.globl __put_user_2
-__put_user_2:
-	addl $1,%eax
-	movl %esp,%ecx
-	jc bad_put_user
-	andl $0xffffe000,%ecx
-	cmpl addr_limit(%ecx),%eax
-	jae bad_put_user
-2:	movw %dx,-1(%eax)
-	xorl %eax,%eax
-	ret
-
-.align 4
-.globl __put_user_4
-__put_user_4:
-	addl $3,%eax
-	movl %esp,%ecx
-	jc bad_put_user
-	andl $0xffffe000,%ecx
-	cmpl addr_limit(%ecx),%eax
-	jae bad_put_user
-3:	movl %edx,-3(%eax)
-	xorl %eax,%eax
-	ret
-
-bad_put_user:
-	movl $-14,%eax
-	ret
-
-.section __ex_table,"a"
-	.long 1b,bad_put_user
-	.long 2b,bad_put_user
-	.long 3b,bad_put_user
-.previous
diff -urN linux-2.4.6-pre8/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- linux-2.4.6-pre8/arch/i386/vmlinux.lds	Wed Jan  3 20:45:26 2001
+++ linux/arch/i386/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -17,7 +17,7 @@
 
   _etext = .;			/* End of text section */
 
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -urN linux-2.4.6-pre8/arch/ia64/boot/bootloader.lds linux/arch/ia64/boot/bootloader.lds
--- linux-2.4.6-pre8/arch/ia64/boot/bootloader.lds	Sun Feb  6 18:42:40 2000
+++ linux/arch/ia64/boot/bootloader.lds	Mon Dec  3 22:50:37 2001
@@ -12,7 +12,7 @@
 
   /* Global data */
   _data = .;
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .data    : { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
   __gp = ALIGN (8) + 0x200000;
   .got           : { *(.got.plt) *(.got) }
diff -urN linux-2.4.6-pre8/arch/ia64/sn/fprom/fprom.lds linux/arch/ia64/sn/fprom/fprom.lds
--- linux-2.4.6-pre8/arch/ia64/sn/fprom/fprom.lds	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/fprom/fprom.lds	Mon Dec  3 22:50:37 2001
@@ -24,7 +24,7 @@
   _data = .;
 
   .rodata : AT(ADDR(.rodata) - 0x0000000000000000 )
-	{ *(.rodata) }
+	{ *(.rodata) *(.rodata.*) }
   .opd : AT(ADDR(.opd) - 0x0000000000000000 )
 	{ *(.opd) }
   .data : AT(ADDR(.data) - 0x0000000000000000 )
diff -urN linux-2.4.6-pre8/arch/ia64/vmlinux.lds.S linux/arch/ia64/vmlinux.lds.S
--- linux-2.4.6-pre8/arch/ia64/vmlinux.lds.S	Thu Apr  5 12:51:47 2001
+++ linux/arch/ia64/vmlinux.lds.S	Mon Dec  3 22:50:37 2001
@@ -83,7 +83,7 @@
   ia64_unw_end = .;
 
   .rodata : AT(ADDR(.rodata) - PAGE_OFFSET)
-	{ *(.rodata) }
+	{ *(.rodata) *(.rodata.*) }
   .kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET)
 	{ *(.kstrtab) }
   .opd : AT(ADDR(.opd) - PAGE_OFFSET)
diff -urN linux-2.4.6-pre8/arch/m68k/vmlinux-sun3.lds linux/arch/m68k/vmlinux-sun3.lds
--- linux-2.4.6-pre8/arch/m68k/vmlinux-sun3.lds	Sat Sep  4 13:06:41 1999
+++ linux/arch/m68k/vmlinux-sun3.lds	Mon Dec  3 22:50:37 2001
@@ -20,6 +20,7 @@
 
   .data : {			/* Data */
 	*(.rodata)
+	*(.rodata.*)
 	*(.data)
 	CONSTRUCTORS
   	. = ALIGN(16);		/* Exception table */
diff -urN linux-2.4.6-pre8/arch/m68k/vmlinux.lds linux/arch/m68k/vmlinux.lds
--- linux-2.4.6-pre8/arch/m68k/vmlinux.lds	Sat Sep  4 13:06:41 1999
+++ linux/arch/m68k/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -12,7 +12,7 @@
 	*(.text.lock)		/* out-of-line lock text */
 	*(.gnu.warning)
 	} = 0x4e75
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -urN linux-2.4.6-pre8/arch/mips/Makefile linux/arch/mips/Makefile
--- linux-2.4.6-pre8/arch/mips/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/Makefile	Mon Dec  3 22:50:37 2001
@@ -17,10 +17,8 @@
 #
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 tool-prefix	= mipsel-linux-
-output-format	= elf32-littlemips
 else
 tool-prefix	= mips-linux-
-output-format	= elf32-bigmips
 endif
 
 ifdef CONFIG_CROSSCOMPILE
@@ -51,9 +49,6 @@
 ifdef CONFIG_CPU_R3000
 GCCFLAGS	+= -mcpu=r3000 -mips1
 endif
-ifdef CONFIG_CPU_R3912
-GCCFLAGS	+= -mcpu=r3000 -mips1
-endif
 ifdef CONFIG_CPU_R6000
 GCCFLAGS	+= -mcpu=r6000 -mips2 -Wa,--trap
 endif
@@ -67,22 +62,19 @@
 GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5432
-GCCFLAGS        += -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS        += -mcpu=r5000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap -mmad
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap -mmad
 endif
 ifdef CONFIG_CPU_RM7000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
-endif
-ifdef CONFIG_CPU_R8000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
 endif
-ifdef CONFIG_CPU_R10000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+ifdef CONFIG_CPU_SB1
+GCCFLAGS	+= -mcpu=sb1 -mips2 -Wa,--trap
 endif
 
 ifdef CONFIG_MIPS_FPU_EMULATOR
@@ -90,14 +82,11 @@
 SUBDIRS		+=arch/mips/math-emu
 endif
 
-#
-# The pipe options is bad for my low-mem machine
-# Uncomment this if you want this.
-#
 GCCFLAGS	+= -pipe
 
 CFLAGS		:= -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS)
 AFLAGS		+= $(GCCFLAGS)
+ASFLAGS		+= $(GCCFLAGS)
 
 #
 # Board-dependent options and extra files
@@ -178,15 +167,6 @@
 endif
 
 #
-# Orion Board
-#
-ifdef CONFIG_ORION
-LIBS          += arch/mips/orion/orionkern.a
-SUBDIRS       += arch/mips/orion
-LINKSCRIPT    = arch/mips/orion/ld.script.orion
-endif
-
-#
 #
 # NEC DDB Vrc-5476
 #
@@ -197,6 +177,17 @@
 endif
 
 #
+#
+# NEC DDB Vrc-5477
+#
+ifdef CONFIG_DDB5477
+SUBDIRS       += arch/mips/ddb5xxx/common arch/mips/ddb5xxx/ddb5477
+LIBS          += arch/mips/ddb5xxx/common/ddb5xxx.o \
+                 arch/mips/ddb5xxx/ddb5477/ddb5477.o
+LOADADDR      += 0x80080000
+endif
+
+#
 # Galileo EV64120 Board
 #
 ifdef CONFIG_MIPS_EV64120
@@ -218,7 +209,9 @@
 # Momentum Ocelot board
 #
 ifdef CONFIG_MOMENCO_OCELOT
-LIBS          += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
+# The Ocelot setup.o must be linked early - it does the ioremap() for the
+# mips_io_port_base.
+CORE_FILES    += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
 SUBDIRS       += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot
 LOADADDR      += 0x80100000
 endif
@@ -227,9 +220,8 @@
 # Philips Nino
 #
 ifdef CONFIG_NINO
-CORE_FILES    += arch/mips/philips/nino/nino.o \
-		 arch/mips/philips/drivers/drivers.o
-SUBDIRS       += arch/mips/philips/nino arch/mips/philips/drivers
+CORE_FILES    += arch/mips/philips/nino/nino.o
+SUBDIRS       += arch/mips/philips/nino
 LOADADDR      += 0x80000000
 endif
 
@@ -252,8 +244,7 @@
 vmlinux: arch/$(ARCH)/ld.script
 
 arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile
-	sed -e 's/@@OUTPUT_FORMAT@@/$(output-format)/' \
-	    -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
+	sed -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
 LINKFLAGS	+= -T arch/$(ARCH)/ld.script
 
 HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
@@ -269,13 +260,6 @@
 balo:  vmlinux
 	$(BAGETBOOT) balo
 
-endif
-
-ifdef CONFIG_ORION
-ORIONBOOT = $(MAKE) -C arch/$(ARCH)/orion
-
-orionboot:
-	$(ORIONBOOT) orionboot
 endif
 
 ifdef CONFIG_MIPS_EV64120
diff -urN linux-2.4.6-pre8/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c
--- linux-2.4.6-pre8/arch/mips/arc/cmdline.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/cmdline.c	Mon Dec  3 22:50:37 2001
@@ -25,10 +25,49 @@
 	"SystemPartition=",
 	"OSLoader=",
 	"OSLoadPartition=",
-	"OSLoadFilename="
+	"OSLoadFilename=",
+	"OSLoadOptions="
 };
 #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
 
+static char *used_arc[][2] = {
+	{ "OSLoadPartition=", "root=" },
+	{ "OSLoadOptions=", "" }
+};
+
+static char * __init move_firmware_args(char* cp)
+{
+	char *s;
+	int actr, i;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	while (actr < prom_argc) {
+		for(i = 0; i < NENTS(used_arc); i++) {
+			int len = strlen(used_arc[i][0]);
+
+			if(!strncmp(prom_argv[actr], used_arc[i][0], len)) {
+			/* Ok, we want it. First append the replacement... */
+				strcat(cp, used_arc[i][1]);
+				cp += strlen(used_arc[i][1]);
+				/* ... and now the argument */
+				s = strstr(prom_argv[actr], "=");
+				if(s) {
+					s++;
+					strcpy(cp, s);
+					cp += strlen(s);
+				}
+				*cp++ = ' ';
+				break;
+			}
+		}
+		actr++;
+	}
+
+	return cp;
+}
+
+
 void __init prom_init_cmdline(void)
 {
 	char *cp;
@@ -37,8 +76,14 @@
 	actr = 1; /* Always ignore argv[0] */
 
 	cp = &(arcs_cmdline[0]);
-	while(actr < prom_argc) {
-		for(i = 0; i < NENTS(ignored); i++) {
+	/* 
+	 * Move ARC variables to the beginning to make sure they can be
+	 * overridden by later arguments.
+	 */
+	cp = move_firmware_args(cp);
+
+	while (actr < prom_argc) {
+		for (i = 0; i < NENTS(ignored); i++) {
 			int len = strlen(ignored[i]);
 
 			if(!strncmp(prom_argv[actr], ignored[i], len))
diff -urN linux-2.4.6-pre8/arch/mips/arc/console.c linux/arch/mips/arc/console.c
--- linux-2.4.6-pre8/arch/mips/arc/console.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/console.c	Mon Dec  3 22:50:37 2001
@@ -15,10 +15,6 @@
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 
-#ifdef CONFIG_ARC_CONSOLE
-#define __init
-#endif
-
 /*
  * IP22 boardcache is not compatible with board caches.  Thus we disable it
  * during romvec action.  Since r4xx0.c is always compiled and linked with your
@@ -29,7 +25,7 @@
  * in some way. You should be careful with them.
  */
 
-void __init prom_putchar(char c)
+void prom_putchar(char c)
 {
 	long cnt;
 	char it = c;
@@ -53,7 +49,7 @@
 
 static char ppbuf[1024];
 
-void __init prom_printf(char *fmt, ...)
+void prom_printf(char *fmt, ...)
 {
 	va_list args;
 	char ch, *bptr;
@@ -71,29 +67,4 @@
 		prom_putchar(ch);
 	}
 	va_end(args);
-}
-
-static void
-arc_console_write(struct console *con, const char *s, unsigned n)
-{
-	prom_printf("%s", s);
-}
-
-static kdev_t 
-arc_console_dev(struct console *c)
-{
-	return MKDEV(TTY_MAJOR, 64 + c->index);
-}
-
-static struct console arc_prom_console = {
-    name:	"prom",
-    write:	arc_console_write,
-    device:	arc_console_dev,
-    flags:	CON_PRINTBUFFER,
-    index:	-1,
-};
-
-__init void arc_setup_console(void)
-{
-	register_console(&arc_prom_console);
 }
diff -urN linux-2.4.6-pre8/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c
--- linux-2.4.6-pre8/arch/mips/arc/identify.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/identify.c	Mon Dec  3 22:50:37 2001
@@ -36,7 +36,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(mach_table); i++) {
+	for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) {
 		if (!strcmp(s, mach_table[i].name))
 			return &mach_table[i];
 	}
diff -urN linux-2.4.6-pre8/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
--- linux-2.4.6-pre8/arch/mips/arc/memory.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/memory.c	Mon Dec  3 22:50:37 2001
@@ -32,7 +32,7 @@
 	"Free/Contig RAM",
 	"Generic Free RAM",
 	"Bad Memory",
-	"Standlong Program Pages",
+	"Standalone Program Pages",
 	"ARCS Temp Storage Area",
 	"ARCS Permanent Storage Area"
 };
diff -urN linux-2.4.6-pre8/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c
--- linux-2.4.6-pre8/arch/mips/arc/misc.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/misc.c	Mon Dec  3 22:50:37 2001
@@ -56,7 +56,7 @@
 	romvec->reboot();
 }
 
-void prom_imode(void)
+void ArcEnterInteractiveMode(void)
 {
 	bc_disable();
 	cli();
diff -urN linux-2.4.6-pre8/arch/mips/baget/ld.script.balo linux/arch/mips/baget/ld.script.balo
--- linux-2.4.6-pre8/arch/mips/baget/ld.script.balo	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/ld.script.balo	Mon Dec  3 22:50:37 2001
@@ -31,6 +31,7 @@
     _ftext = . ;
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -urN linux-2.4.6-pre8/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c
--- linux-2.4.6-pre8/arch/mips/boot/mkboot.c	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/boot/mkboot.c	Mon Dec  3 22:50:37 2001
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 2001 by Ralf Baechle
  *
  * This file is written in plain Kernighan & Ritchie C as it has to run
  * on all crosscompile hosts no matter how braindead.  This code might
@@ -80,7 +80,6 @@
  * Acceptable machine type in e_machine.
  */
 #define EM_MIPS         8               /* MIPS R3000 big-endian */
-#define EM_MIPS_RS4_BE 10               /* MIPS R4000 big-endian */
 
 /*
  * The type of ELF file we accept.
@@ -462,7 +461,7 @@
 		fprintf(stderr, "Input file isn't a executable.\n");
 		exit(1);
 	}
-	if(eh.e_machine != EM_MIPS && eh.e_machine != EM_MIPS_RS4_BE) {
+	if(eh.e_machine != EM_MIPS) {
 		fprintf(stderr, "Input file isn't a MIPS executable.\n");
 		exit(1);
 	}
diff -urN linux-2.4.6-pre8/arch/mips/config.in linux/arch/mips/config.in
--- linux-2.4.6-pre8/arch/mips/config.in	Tue Apr 17 17:19:25 2001
+++ linux/arch/mips/config.in	Mon Dec  3 22:50:37 2001
@@ -2,6 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
+define_bool CONFIG_MIPS y
+define_bool CONFIG_SMP n
+
 mainmenu_name "Linux Kernel Configuration"
 
 mainmenu_option next_comment
@@ -15,18 +18,55 @@
    bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
    bool 'Support for Algorithmics P4032 (EXPERIMENTAL)' CONFIG_ALGOR_P4032
    bool 'Support for BAGET MIPS series (EXPERIMENTAL)' CONFIG_BAGET_MIPS
-   bool 'Support for Cobalt Server' CONFIG_COBALT_MICRO_SERVER
-   if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
-      bool '  Support for 2800' CONFIG_COBALT_28
-   fi
    bool 'Support for DECstations (EXPERIMENTAL)' CONFIG_DECSTATION
    bool 'Support for NEC DDB Vrc-5074 (EXPERIMENTAL)' CONFIG_DDB5074
-   bool 'Support for Galileo Evaluation board or CoSine Orion' CONFIG_ORION
+   bool 'Support for Galileo EV96100 Evaluation board' CONFIG_MIPS_EV96100
+   bool 'Support for Galileo EV64120 Evaluation board' CONFIG_MIPS_EV64120
+   if [ "$CONFIG_MIPS_EV64120" = "y" ]; then
+		  bool 'Enable Second PCI (PCI1)' CONFIG_EVB_PCI1
+      choice 'Galileo Chip Clock' \
+        "75 CONFIG_SYSCLK_75\
+         83.3 CONFIG_SYSCLK_83\
+         100 CONFIG_SYSCLK_100" CONFIG_SYSCLK_83
+   fi
+   bool 'Support for MIPS Atlas board' CONFIG_MIPS_ATLAS
+   bool 'Support for MIPS Malta board' CONFIG_MIPS_MALTA
+   bool 'Support for Philips Nino (EXPERIMENTAL)' CONFIG_NINO
+   if [ "$CONFIG_NINO" = "y" ]; then
+      choice 'Nino Model Number' \
+        "Model-300/301/302/319 CONFIG_NINO_4MB \
+         Model-200/210/312/320/325/350/390 CONFIG_NINO_8MB \
+         Model-500/510 CONFIG_NINO_16MB" CONFIG_NINO_8MB
+   fi
 fi
 bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
+bool 'Support for Momentum Ocelot board' CONFIG_MOMENCO_OCELOT
+bool 'Support for NEC DDB Vrc-5476' CONFIG_DDB5476
+bool 'Support for NEC DDB Vrc-5477' CONFIG_DDB5477
 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
 bool 'Support for SGI IP22' CONFIG_SGI_IP22
 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
+bool 'Support for ITE 8172G board' CONFIG_MIPS_ITE8172
+   if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
+       bool '    Support for older IT8172 (Rev C)' CONFIG_IT8172_REVC
+       bool '    Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD
+       if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
+	   define_bool CONFIG_IT8172_CIR y
+       else
+           bool '    Enable PS2 Keyboard Support ' CONFIG_PC_KEYB
+       fi
+       bool '    Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
+       bool '    Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1
+   fi
+   bool 'Support for Globespan IVR board' CONFIG_MIPS_IVR
+   if [ "$CONFIG_MIPS_IVR" = "y" ]; then
+       bool '    Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD
+       if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
+	   define_bool CONFIG_IT8172_CIR y
+       fi
+       bool '    Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
+   fi
+bool 'Support for Alchemy Semi PB1000 board' CONFIG_MIPS_PB1000
 
 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
@@ -35,54 +75,127 @@
 # Select some configuration options automatically for certain systems.
 #
 unset CONFIG_ARC32
+unset CONFIG_BOARD_SCACHE
+unset CONFIG_HAVE_STD_PC_SERIAL_PORT
+unset CONFIG_I8259
 unset CONFIG_ISA
-unset CONFIG_EISA
 unset CONFIG_PCI
 unset CONFIG_MIPS_JAZZ
+unset CONFIG_SWAP_IO_SPACE
 unset CONFIG_VIDEO_G364
 unset CONFIG_PC_KEYB
 
 define_bool CONFIG_MCA n
 define_bool CONFIG_SBUS n
 
+if [ "$CONFIG_MIPS_EV96100" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_MIPS_GT96100 y
+   define_bool CONFIG_SWAP_IO_SPACE y
+fi
+if [ "$CONFIG_MIPS_EV64120" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_ISA n
+   define_bool CONFIG_MIPS_GT64120 y
+   define_bool CONFIG_OLD_TIME_C y
+fi
+
 if [ "$CONFIG_ALGOR_P4032" = "y" ]; then
    define_bool CONFIG_PCI y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
    define_bool CONFIG_FB y
    define_bool CONFIG_FB_G364 y	
    define_bool CONFIG_MIPS_JAZZ y
    define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
    define_bool CONFIG_MIPS_JAZZ y
    define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
 fi
-if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
-   define_bool CONFIG_COBALT_27 y
-   define_bool CONFIG_COBALT_LCD y
-   define_bool CONFIG_COBALT_SERIAL y
+if [ "$CONFIG_MIPS_ATLAS" = "y" ]; then
    define_bool CONFIG_PCI y
+   define_bool CONFIG_SWAP_IO_SPACE y
+fi
+if [ "$CONFIG_MIPS_MALTA" = "y" ]; then
+   define_bool CONFIG_I8259 y
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y
+   define_bool CONFIG_SWAP_IO_SPACE y
+fi
+if [ "$CONFIG_MOMENCO_OCELOT" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_SYSCLK_100 y
+   define_bool CONFIG_SWAP_IO_SPACE y
+   define_bool CONFIG_NEW_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_SGI_IP22" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_BOARD_SCACHE y
    define_bool CONFIG_PC_KEYB y
    define_bool CONFIG_SGI y
+   define_bool CONFIG_NEW_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_I8259 y
+   define_bool CONFIG_ISA y
+   define_bool CONFIG_PC_KEYB y
    define_bool CONFIG_PCI y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
+fi
+if [ "$CONFIG_DDB5074" = "y"]; then
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
+   define_bool CONFIG_PCI y
    define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y
+   define_bool CONFIG_OLD_TIME_C y
 fi
-if [ "$CONFIG_DDB5074" = "y" ]; then
+if [ "$CONFIG_DDB5476"  = "y" ]; then
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
    define_bool CONFIG_PCI y
+   define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y
+   define_bool CONFIG_NEW_TIME_C y
+fi
+if [ "$CONFIG_DDB5477" = "y" ]; then
+   define_bool CONFIG_CPU_LITTLE_ENDIAN y
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_NEW_TIME_C y
+   define_bool CONFIG_NEW_IRQ y
+fi
+if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_IT8712 y
+   define_bool CONFIG_PC_KEYB y
+fi
+if [ "$CONFIG_MIPS_IVR" = "y" ]; then
+   define_bool CONFIG_PCI y
+fi
+if [ "$CONFIG_MIPS_PB1000" = "y" ]; then
+   define_bool CONFIG_MIPS_AU1000 y
+   define_bool CONFIG_NEW_IRQ y
+fi
+if [ "$CONFIG_NINO" = "y" ]; then
+   define_bool CONFIG_PC_KEYB y
 fi
 
 if [ "$CONFIG_ISA" != "y" ]; then
@@ -95,6 +208,10 @@
 if [ "$CONFIG_PCI" != "y" ]; then
    define_bool CONFIG_PCI n
 fi
+
+if [ "$CONFIG_I8259" != "y" ]; then
+   define_bool CONFIG_I8259 n
+fi
 endmenu
 
 mainmenu_option next_comment
@@ -115,9 +232,12 @@
 	 R4300 CONFIG_CPU_R4300	\
 	 R4x00 CONFIG_CPU_R4X00	\
 	 R5000 CONFIG_CPU_R5000	\
-	 R56x0 CONFIG_CPU_NEVADA \
-	 R8000 CONFIG_CPU_R8000	\
-	 R10000 CONFIG_CPU_R10000" R4x00
+         R5432 CONFIG_CPU_R5432 \
+	 RM7000 CONFIG_CPU_RM7000 \
+	 R52xx CONFIG_CPU_NEVADA \
+	 R10000 CONFIG_CPU_R10000 \
+	 SB1    CONFIG_CPU_SB1    \
+	 MIPS32 CONFIG_CPU_MIPS32" R4x00
 
 bool 'Override CPU Options' CONFIG_CPU_ADVANCED
 
@@ -134,19 +254,23 @@
 	 define_bool CONFIG_CPU_HAS_WB n
       fi
    else
-      define_bool CONFIG_CPU_HAS_LLSC y
-      define_bool CONFIG_CPU_HAS_WB n
+	 define_bool CONFIG_CPU_HAS_LLSC y
+	 define_bool CONFIG_CPU_HAS_WB n
    fi
 fi
 endmenu
 
 mainmenu_option next_comment
 comment 'General setup'
-if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then
+if [ "$CONFIG_DECSTATION" = "y" -o \
+     "$CONFIG_DDB5074" = "y" -o    \
+     "$CONFIG_DDB5476" = "y" -o    \
+     "$CONFIG_NINO" = "y" ]; then
    define_bool CONFIG_CPU_LITTLE_ENDIAN y
 else
    bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
 fi
+bool 'Kernel floating-point emulation' CONFIG_MIPS_FPU_EMULATOR
 
 if [ "$CONFIG_PROC_FS" = "y" ]; then
    define_bool CONFIG_KCORE_ELF y
@@ -158,22 +282,30 @@
    bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD 
 fi
 
+if [ "$CONFIG_ARC32" = "y" ]; then
+   bool 'ARC console support' CONFIG_ARC_CONSOLE
+fi
+
 define_bool CONFIG_BINFMT_AOUT n
 define_bool CONFIG_BINFMT_ELF y
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 bool 'Networking support' CONFIG_NET
 
-if [ "$CONFIG_PCI" = "y" ]; then
-    source drivers/pci/Config.in
+source drivers/pci/Config.in
+
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+   source drivers/pcmcia/Config.in
+else
+   define_bool CONFIG_PCMCIA n
 fi
 
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
-source drivers/parport/Config.in
-
 if [ "$CONFIG_DECSTATION" = "y" ]; then
     bool 'TURBOchannel support' CONFIG_TC
 #    if [ "$CONFIG_TC" = "y" ]; then
@@ -186,14 +318,10 @@
    source drivers/pnp/Config.in
 fi
 
-if [ "$CONFIG_HOTPLUG" = "y" ] ; then
-   source drivers/pcmcia/Config.in
-else
-   define_bool CONFIG_PCMCIA n
-fi
-
 source drivers/mtd/Config.in
 
+source drivers/parport/Config.in
+
 source drivers/block/Config.in
 
 source drivers/md/Config.in
@@ -202,10 +330,7 @@
    source net/Config.in
 fi
 
-if [ "$CONFIG_DECSTATION" != "y" -a \
-     "$CONFIG_SGI_IP22" != "y" ]; then
-   source drivers/telephony/Config.in
-fi
+source drivers/telephony/Config.in
 
 if [ "$CONFIG_SGI_IP22" != "y" -a \
      "$CONFIG_DECSTATION" != "y" ]; then
@@ -236,7 +361,7 @@
 
 if [ "$CONFIG_DECSTATION" != "y" -a \
      "$CONFIG_SGI_IP22" != "y" ]; then
-   source drivers/i2o/Config.in
+   source drivers/message/i2o/Config.in
 fi
 
 if [ "$CONFIG_NET" = "y" ]; then
@@ -245,69 +370,40 @@
 
    bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-
-      if [ "$CONFIG_SGI_IP22" != "y" -a \
-      	   "$CONFIG_DECSTATION" != "y" -a \
-	   "$CONFIG_BAGET_MIPS" != "y" ]; then
-
-	 source drivers/net/Config.in
-
-	 if [ "$CONFIG_ATM" = "y" ]; then
-	    source drivers/atm/Config.in
-	 fi
-      else
-	 tristate 'Dummy net driver support' CONFIG_DUMMY
-	 tristate 'SLIP (serial line) support' CONFIG_SLIP
-	 if [ "$CONFIG_SLIP" != "n" ]; then
-	    bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
-	    bool ' Keepalive and linefill' CONFIG_SLIP_SMART
-	 fi
-	 tristate 'PPP (point-to-point) support' CONFIG_PPP
-	 if [ ! "$CONFIG_PPP" = "n" ]; then
-	    comment 'CCP compressors for PPP are only built as modules.'
-	 fi
-         if [ "$CONFIG_SGI_IP22" = "y" ]; then
-	    bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ
-	 fi
-	 if [ "$CONFIG_DECSTATION" = "y" ]; then
-	    bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE
-	 fi
-	 if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
-	    tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE
-	 fi
+      source drivers/net/Config.in
+      if [ "$CONFIG_ATM" = "y" ]; then
+         source drivers/atm/Config.in
       fi
    fi
    endmenu
 fi
 
-if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then
-   mainmenu_option next_comment
-   comment 'ISDN subsystem'
-
-   if [ "$CONFIG_NET" != "n" ]; then
-      tristate 'ISDN support' CONFIG_ISDN
-      if [ "$CONFIG_ISDN" != "n" ]; then
-	 source drivers/isdn/Config.in
-      fi
-   fi
-   endmenu
+source net/ax25/Config.in
 
-   mainmenu_option next_comment
-   comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+source net/irda/Config.in
 
-   bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
-   if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-      source drivers/cdrom/Config.in
+mainmenu_option next_comment
+comment 'ISDN subsystem'
+if [ "$CONFIG_NET" != "n" ]; then
+   tristate 'ISDN support' CONFIG_ISDN
+   if [ "$CONFIG_ISDN" != "n" ]; then
+      source drivers/isdn/Config.in
    fi
-   endmenu
 fi
+endmenu
 
-if [ "$CONFIG_DECSTATION" != "y" -a \
-     "$CONFIG_SGI_IP22" != "y" ]; then
-   source drivers/char/Config.in
+mainmenu_option next_comment
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
-   source drivers/media/Config.in
+bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
+if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+   source drivers/cdrom/Config.in
 fi
+endmenu
+
+source drivers/char/Config.in
+
+source drivers/media/Config.in
 
 if [ "$CONFIG_DECSTATION" = "y" ]; then
    mainmenu_option next_comment
@@ -332,9 +428,7 @@
 #   if [ "$CONFIG_ACCESSBUS" = "y" ]; then
 #      bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
 #   fi
-   bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC
-
-   define_tristate CONFIG_RTC $CONFIG_MIPS_RTC
+   bool 'Enhanced Real Time Clock Support' CONFIG_RTC
 
    endmenu
 fi
@@ -351,7 +445,10 @@
       else
 	 define_bool CONFIG_FONT_8x16 y
       fi
-      bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE
+   fi
+   bool 'PS/2 mouse support' CONFIG_PSMOUSE
+   if [ "$CONFIG_PSMOUSE" != "n" ]; then
+      define_bool CONFIG_MOUSE y
    fi
    bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
    if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
@@ -364,13 +461,12 @@
 
 if [ "$CONFIG_VT" = "y" ]; then
    mainmenu_option next_comment
-
    comment 'Console drivers'
-      if [ "$CONFIG_DECSTATION" != "y" ]; then
-	 bool 'VGA text console' CONFIG_VGA_CONSOLE
-      fi
-      bool 'Support for frame buffer devices' CONFIG_FB
+   bool 'VGA text console' CONFIG_VGA_CONSOLE
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
       source drivers/video/Config.in
+   fi
    endmenu
 fi
 
@@ -399,8 +495,15 @@
 if [ "$CONFIG_MODULES" = "y" ]; then
    bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE
 fi
-if [ "$CONFIG_SERIAL" = "y" ]; then
+if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_AU1000_UART" = "y" ]; then
   bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
+  dep_bool 'Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_REMOTE_DEBUG
+fi
+if [ "$CONFIG_SERIAL" = "y" ]; then
+  bool 'Low-level debugging' CONFIG_LL_DEBUG
 fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+if [ "$CONFIG_SMP" != "y" ]; then
+   bool 'Run uncached' CONFIG_MIPS_UNCACHED
+fi
 endmenu
diff -urN linux-2.4.6-pre8/arch/mips/dec/boot/ld.ecoff linux/arch/mips/dec/boot/ld.ecoff
--- linux-2.4.6-pre8/arch/mips/dec/boot/ld.ecoff	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/boot/ld.ecoff	Mon Dec  3 22:50:37 2001
@@ -13,7 +13,7 @@
   }
   .rdata :
   {
-    *(.rodata .rdata)
+    *(.rodata .rodata.* .rdata)
   }
   .data :
   {
diff -urN linux-2.4.6-pre8/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile
--- linux-2.4.6-pre8/arch/mips/kernel/Makefile	Tue Jul 11 11:14:42 2000
+++ linux/arch/mips/kernel/Makefile	Mon Dec  3 22:50:37 2001
@@ -6,93 +6,58 @@
 # unless it's something special (ie not a .c file).
 #
 
+.S.s:
+	$(CPP) $(AFLAGS) $< -o $@
 .S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
+	$(CC) $(AFLAGS) -c $< -o $@
+
+EXTRA_AFLAGS = -mips3 -mcpu=r4000
 
 all:	kernel.o head.o init_task.o
-EXTRA_ASFLAGS = -mips3 -mcpu=r4000
+
 O_TARGET := kernel.o
-O_OBJS	:= branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
-	   ioport.o reset.o semaphore.o setup.o syscall.o sysmips.o ipc.o \
-	   scall_o32.o softfp.o unaligned.o
-OX_OBJS := mips_ksyms.o
+
+obj-y				+= branch.o process.o signal.o entry.o \
+				   traps.o ptrace.o vm86.o ioport.o reset.o \
+				   semaphore.o setup.o syscall.o sysmips.o \
+				   ipc.o scall_o32.o unaligned.o
+obj-$(CONFIG_MODULES)		+= mips_ksyms.o
 
 ifdef CONFIG_CPU_R3000
-O_OBJS	+= r2300_misc.o r2300_fpu.o r2300_switch.o
+obj-y	+= r2300_misc.o r2300_fpu.o r2300_switch.o
 else
-O_OBJS	+= r4k_misc.o r4k_switch.o 
+obj-y	+= r4k_misc.o r4k_switch.o 
 ifdef CONFIG_CPU_R6000
-O_OBJS	+= r6000_fpu.o
+obj-y	+= r6000_fpu.o
 else
-O_OBJS	+= r4k_fpu.o
-endif
-endif
-
-ifdef CONFIG_MIPS_FPE_MODULE
-M_OBJS += fpe.o
+obj-y	+= r4k_fpu.o
 endif
-
-#
-# SGIs have very different interrupt/timer hardware.
-#
-ifndef CONFIG_DECSTATION
-  ifndef CONFIG_BAGET_MIPS
-    O_OBJS += time.o
-    ifndef CONFIG_SGI_IP22
-      ifndef CONFIG_ORION
-        OX_OBJS += irq.o
-      endif
-    endif
-  endif
 endif
 
-#
-# Do we want to be able to execute IRIX elf binaries?
-#
-ifdef CONFIG_BINFMT_IRIX
-O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o irixinv.o
+obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_MIPS_FPE_MODULE)	+= fpe.o
+ifndef CONFIG_MIPS_FPU_EMULATOR
+  obj-y				+= softfp.o
 endif
 
-#
-# Kernel debugging
-#
-ifdef CONFIG_REMOTE_DEBUG
-O_OBJS += gdb-low.o gdb-stub.o 
-endif
+# Old style irq support, going to die in 2.5.
+export-objs			+= old-irq.o
+obj-$(CONFIG_NEW_IRQ)		+= irq.o
+obj-$(CONFIG_ROTTEN_IRQ)	+= old-irq.o
 
-#
-# Depending from some other kernel option
-#
-ifdef CONFIG_PROC_FS
-O_OBJS += proc.o
-endif
+# transition from old time.c to new time.c
+# some boards uses old-time.c, some use time.c, and some use their own ones
+export-objs			+= old-time.o time.o
+obj-$(CONFIG_OLD_TIME_C)	+= old-time.o
+obj-$(CONFIG_NEW_TIME_C)	+= time.o
 
-#
-# Since we add the same object files to O_OBJS for different configurations.
-# O_OBJS might contain duplicate files.  We correct this by filtering out
-# duplicate files.  Just to avoid users having to know about all the
-# compatibility stuff between various boards and boards.
-#
-O_OBJS := $(sort $(O_OBJS))
+obj-$(CONFIG_BINFMT_IRIX)	+= irixelf.o irixioctl.o irixsig.o sysirix.o \
+				   irixinv.o
+obj-$(CONFIG_REMOTE_DEBUG)	+= gdb-low.o gdb-stub.o 
+obj-$(CONFIG_PCI)		+= pci-dma.o
+obj-$(CONFIG_PROC_FS)		+= proc.o
 
 entry.o: entry.S
-
 head.o: head.S
-
-#r4k_switch.o: r4k_switch.S
-#
-#r4k_misc.o: r4k_misc.S
-#
-#r4k_fpu.o: r4k_fpu.S
-#
-#r2300_switch.o: r2300_switch.S
-#
-#r2300_misc.o: r2300_misc.S
-#
-#r2300_fpu.o: r2300_fpu.S
-#
-#r6000_fpu.o: r6000_fpu.S
-
-clean:
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.6-pre8/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S
--- linux-2.4.6-pre8/arch/mips/kernel/entry.S	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/kernel/entry.S	Mon Dec  3 22:50:37 2001
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/sys.h>
 
+#include <asm/addrspace.h>
 #include <asm/asm.h>
 #include <asm/current.h>
 #include <asm/errno.h>
@@ -43,11 +44,16 @@
 EXPORT(ret_from_sys_call)
 EXPORT(ret_from_irq)
 		.type	ret_from_irq,@function
-		lw	t0, irq_stat		# softirq_active
-		lw	t1, irq_stat+4		# softirq_mask.  unused delay slot
+		la	t1, irq_stat		# softirq_active
+#ifdef CONFIG_SMP
+		lw	t0, TASK_PROCESSOR($28)
+		sll	t0, t0, 5
+		addu	t1, t0
+#endif
+		lw	t0, 0(t1)		# softirq_active
+		lw	t1, 4(t1)		# softirq_mask.  unused delay slot
 		and	t0, t1
 		bnez	t0, handle_softirq
-
 
 9:		lw	t0,PT_STATUS(sp)	# returning to kernel mode?
 		lw	t2, TASK_NEED_RESCHED($28)
diff -urN linux-2.4.6-pre8/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c
--- linux-2.4.6-pre8/arch/mips/kernel/gdb-stub.c	Sun Oct  1 20:35:15 2000
+++ linux/arch/mips/kernel/gdb-stub.c	Mon Dec  3 22:50:37 2001
@@ -64,6 +64,61 @@
  * Host:                  Reply:
  * $m0,10#2a               +$00010203040506070809101112131415#42
  *
+ * 
+ *  ==============
+ *  MORE EXAMPLES:
+ *  ==============
+ *
+ *  For reference -- the following are the steps that one
+ *  company took (RidgeRun Inc) to get remote gdb debugging
+ *  going. In this scenario the host machine was a PC and the
+ *  target platform was a Galileo EVB64120A MIPS evaluation
+ *  board.
+ *   
+ *  Step 1:
+ *  First download gdb-5.0.tar.gz from the internet.
+ *  and then build/install the package.
+ * 
+ *  Example:
+ *    $ tar zxf gdb-5.0.tar.gz
+ *    $ cd gdb-5.0
+ *    $ ./configure --target=mips-linux-elf
+ *    $ make
+ *    $ install
+ *    $ which mips-linux-elf-gdb
+ *    /usr/local/bin/mips-linux-elf-gdb
+ * 
+ *  Step 2:
+ *  Configure linux for remote debugging and build it.
+ * 
+ *  Example:
+ *    $ cd ~/linux
+ *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
+ *    $ make dep; make vmlinux
+ * 
+ *  Step 3:
+ *  Download the kernel to the remote target and start
+ *  the kernel running. It will promptly halt and wait 
+ *  for the host gdb session to connect. It does this
+ *  since the "Kernel Hacking" option has defined 
+ *  CONFIG_REMOTE_DEBUG which in turn enables your calls
+ *  to:
+ *     set_debug_traps();
+ *     breakpoint();
+ * 
+ *  Step 4:
+ *  Start the gdb session on the host.
+ * 
+ *  Example:
+ *    $ mips-linux-elf-gdb vmlinux
+ *    (gdb) set remotebaud 115200
+ *    (gdb) target remote /dev/ttyS1
+ *    ...at this point you are connected to 
+ *       the remote target and can use gdb
+ *       in the normal fasion. Setting 
+ *       breakpoints, single stepping,
+ *       printing variables, etc.
+ *
  */
 
 #include <linux/string.h>
@@ -71,6 +126,8 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
 
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
@@ -315,13 +372,10 @@
  * signals, which are primarily what GDB understands.  It also indicates
  * which hardware traps we need to commandeer when initializing the stub.
  */
-static struct hard_trap_info
-{
+static struct hard_trap_info {
 	unsigned char tt;		/* Trap type code for MIPS R3xxx and R4xxx */
 	unsigned char signo;		/* Signal that we map this trap into */
 } hard_trap_info[] = {
-	{ 4, SIGBUS },			/* address error (load) */
-	{ 5, SIGBUS },			/* address error (store) */
 	{ 6, SIGBUS },			/* instruction bus error */
 	{ 7, SIGBUS },			/* data bus error */
 	{ 9, SIGTRAP },			/* break */
@@ -350,6 +404,7 @@
 	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
 		set_except_vector(ht->tt, trap_low);
   
+	putDebugChar('+'); /* 'hello world' */
 	/*
 	 * In case GDB is started before us, ack any packets
 	 * (presumably "$?#xx") sitting there.
@@ -373,7 +428,7 @@
  */
 extern void fltr_set_mem_err(void)
 {
-  /* FIXME: Needs to be written... */
+	/* FIXME: Needs to be written... */
 }
 
 /*
@@ -401,8 +456,7 @@
 
 	*intValue = 0;
 
-	while (**ptr)
-	{
+	while (**ptr) {
 		hexValue = hex(**ptr);
 		if (hexValue < 0)
 			break;
@@ -904,3 +958,47 @@
 			lw	$9,0($8)
 	");
 }
+
+#ifdef CONFIG_GDB_CONSOLE
+
+void gdb_puts(const char *str)
+{
+	int l = strlen(str);
+	char outbuf[18];
+
+	outbuf[0]='O';
+
+	while(l) {
+		int i = (l>8)?8:l;
+		mem2hex((char *)str, &outbuf[1], i, 0);
+		outbuf[(i*2)+1]=0;
+		putpacket(outbuf); 
+		str += i;
+		l -= i;
+	}
+}
+
+static kdev_t gdb_console_dev(struct console *con)
+{
+	return MKDEV(1, 3); /* /dev/null */
+}
+
+static void gdb_console_write(struct console *con, const char *s, unsigned n)
+{
+	gdb_puts(s);
+}
+
+static struct console gdb_console = {
+	name:	"gdb",
+	write:	gdb_console_write,
+	device:	gdb_console_dev,
+	flags:	CON_PRINTBUFFER,
+	index:	-1
+};
+
+__init void register_gdb_console(void)
+{
+	register_console(&gdb_console);
+}
+     
+#endif
diff -urN linux-2.4.6-pre8/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S
--- linux-2.4.6-pre8/arch/mips/kernel/head.S	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/kernel/head.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,4 @@
-/* $Id: head.S,v 1.18 2000/03/03 22:17:07 kevink Exp $
- *
+/*
  * arch/mips/kernel/head.S
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -15,6 +14,14 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  *
  * Head.S contains the MIPS exception handler and startup code.
+ *
+ **************************************************************************
+ *  9 Nov, 2000.
+ *  Added Cache Error exception handler and SBDDP EJTAG debug exception.
+ *
+ *  Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ **************************************************************************
  */
 #include <linux/config.h>
 #include <linux/threads.h>
@@ -52,9 +59,19 @@
 	.set	noat
 	LEAF(except_vec0_r4000)
 	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, current_pgd
+	srl	k1, 23
+	sll	k1, 2
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else 
+	lw	k1, current_pgd			# get pgd pointer
+#endif	
 	mfc0	k0, CP0_BADVADDR		# Get faulting address
 	srl	k0, k0, 22			# get pgd only bits
-	lw	k1, current_pgd			# get pgd pointer
+
 	sll	k0, k0, 2
 	addu	k1, k1, k0			# add in pgd offset
 	mfc0	k0, CP0_CONTEXT			# get context reg
@@ -69,8 +86,8 @@
 	srl	k1, k1, 6			# convert to entrylo1
 	mtc0	k1, CP0_ENTRYLO1		# load it
 	b	1f
-	 tlbwr					# write random tlb entry
-1:	
+	tlbwr					# write random tlb entry
+1:
 	nop
 	eret					# return from trap
 	END(except_vec0_r4000)
@@ -308,12 +325,26 @@
 
 	/* Cache Error */
 	LEAF(except_vec2_generic)
-	/* Famous last words: unreached */
-	mfc0	a1,CP0_ERROREPC
-	PRINT("Cache error exception: c0_errorepc == %08x\n")
-1:
-	j	1b
-	 nop
+	.set	noat
+	.set    mips0
+	/*
+	 * This is a very bad place to be.  Our cache error
+	 * detection has triggered.  If we have write-back data
+	 * in the cache, we may not be able to recover.  As a
+	 * first-order desperate measure, turn off KSEG0 cacheing.
+	 */
+	mfc0	k0,CP0_CONFIG
+	li	k1,~CONF_CM_CMASK
+	and	k0,k0,k1
+	ori	k0,k0,CONF_CM_UNCACHED
+	mtc0	k0,CP0_CONFIG
+	/* Give it a few cycles to sink in... */
+	nop
+	nop
+	nop
+
+	j	cache_parity_error
+	nop
 	END(except_vec2_generic)
 
 	/* General exception vector R4000 version. */
@@ -338,6 +369,7 @@
  * c0_badvaddr because after return from this exception handler the load /
  * store will be re-executed.
  */
+	.set    mips3
 handle_vced:
 	mfc0	k0, CP0_BADVADDR
  li k1, -4
@@ -393,6 +425,38 @@
 	 nop
 	END(except_vec4)
 
+	/*
+	 * SBDDP EJTAG debug exception handler.
+	 * The EJTAG debug exception entry point is 0xbfc00480, which
+	 * normally is in the boot PROM, so the boot PROM must do a
+	 * unconditional jump to this vector.
+	 */	
+	NESTED(except_vec_ejtag_debug, 0, sp)
+	j	ejtag_debug_handler
+	 nop
+	END(except_vec_ejtag_debug)
+
+	/*
+	 * EJTAG debug exception handler.
+	 */
+	NESTED(ejtag_debug_handler, PT_SIZE, sp)
+	.set	noat
+	.set	noreorder
+	SAVE_ALL
+	PRINT("SDBBP EJTAG debug exception - not handled yet, just ignored!\n");
+	mfc0	k0, $23         # Get EJTAG Debug register.
+	mfc0    k1, $24         # Get DEPC register.
+	bgez	k0, 1f
+	 addiu	k1, k1, 4	# SBDDP inst. in delay slot.
+	addiu	k1, k1, 4
+1:	mtc0	k1, $24
+	RESTORE_ALL
+	.word	0x4200001f      # deret, return EJTAG debug exception.
+	 nop
+	.set	at
+	END(ejtag_debug_handler)
+
+		
 /*
  * Kernel entry point
  */
@@ -407,9 +471,9 @@
 	 */
 	la	$28, init_task_union
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
-	sw	t0, kernelsp
 	subu	sp, t0, 4*SZREG
 
+	sw	t0, kernelsp
 	/* The firmware/bootloader passes argc/argp/envp
 	 * to us as arguments.  But clear bss first because
 	 * the romvec and other important info is stored there
@@ -427,6 +491,30 @@
 	 nop
 	END(kernel_entry)
 
+
+#ifdef CONFIG_SMP
+
+/*
+ * SMP slave cpus entry point.  Board specific code
+ * for bootstrap calls this function after setting up
+ * the stack and gp registers. 
+ */
+	LEAF(smp_bootstrap)
+	.set push
+	.set noreorder
+	mtc0	zero, CP0_WIRED
+	CLI
+	mfc0	t0, CP0_STATUS
+	li	t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); 
+	and	t0, t1
+	or	t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR);
+	addiu	a0, zero, 0
+	jal	start_secondary
+         mtc0	t0, CP0_STATUS
+	.set pop
+	END(smp_bootstrap)
+#endif
+	
 /*
  * This buffer is reserved for the use of the cache error handler.
  */
@@ -434,12 +522,19 @@
 		EXPORT(cache_error_buffer)
 		.fill	32*4,1,0
 
+#ifndef CONFIG_SMP
 EXPORT(kernelsp)
 		PTR	0
 EXPORT(current_pgd)
-		PTR	0
+		PTR     0
+#else
+		/* There's almost certainly a better way to do this with the macros...*/
+		.globl kernelsp
+		.comm  kernelsp,     NR_CPUS * 8, 8
+		.globl current_pgd
+		.comm	current_pgd, NR_CPUS * 8, 8
+#endif
 		.text
-
 		.org	0x1000
 EXPORT(swapper_pg_dir)
 
diff -urN linux-2.4.6-pre8/arch/mips/kernel/i8259.c linux/arch/mips/kernel/i8259.c
--- linux-2.4.6-pre8/arch/mips/kernel/i8259.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/i8259.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,308 @@
+/*
+ * 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.
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+
+void enable_8259A_irq(unsigned int irq);
+void disable_8259A_irq(unsigned int irq);
+
+/*
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ * plus some generic x86 specific things if generic specifics makes
+ * any sense at all.
+ * this file should become arch/i386/kernel/irq.c when the old irq.c
+ * moves to arch independent land
+ */
+
+spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
+
+static void end_8259A_irq (unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_8259A_irq(irq);
+}
+
+#define shutdown_8259A_irq	disable_8259A_irq
+
+void mask_and_ack_8259A(unsigned int);
+
+static unsigned int startup_8259A_irq(unsigned int irq)
+{ 
+	enable_8259A_irq(irq);
+
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type i8259A_irq_type = {
+	"XT-PIC",
+	startup_8259A_irq,
+	shutdown_8259A_irq,
+	enable_8259A_irq,
+	disable_8259A_irq,
+	mask_and_ack_8259A,
+	end_8259A_irq,
+	NULL
+};
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) 	(((unsigned char *)&(y))[x])
+#define cached_21	(__byte(0,cached_irq_mask))
+#define cached_A1	(__byte(1,cached_irq_mask))
+
+void disable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	cached_irq_mask |= mask;
+	if (irq & 8)
+		outb(cached_A1,0xA1);
+	else
+		outb(cached_21,0x21);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+void enable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	cached_irq_mask &= mask;
+	if (irq & 8)
+		outb(cached_A1,0xA1);
+	else
+		outb(cached_21,0x21);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+int i8259A_irq_pending(unsigned int irq)
+{
+	unsigned int mask = 1 << irq;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	if (irq < 8)
+		ret = inb(0x20) & mask;
+	else
+		ret = inb(0xA0) & (mask >> 8);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+
+	return ret;
+}
+
+void make_8259A_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &i8259A_irq_type;
+	enable_irq(irq);
+}
+
+/*
+ * This function assumes to be called rarely. Switching between
+ * 8259A registers is slow.
+ * This has to be protected by the irq controller spinlock
+ * before being called.
+ */
+static inline int i8259A_irq_real(unsigned int irq)
+{
+	int value;
+	int irqmask = 1 << irq;
+
+	if (irq < 8) {
+		outb(0x0B,0x20);		/* ISR register */
+		value = inb(0x20) & irqmask;
+		outb(0x0A,0x20);		/* back to the IRR register */
+		return value;
+	}
+	outb(0x0B,0xA0);		/* ISR register */
+	value = inb(0xA0) & (irqmask >> 8);
+	outb(0x0A,0xA0);		/* back to the IRR register */
+	return value;
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+void mask_and_ack_8259A(unsigned int irq)
+{
+	unsigned int irqmask = 1 << irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	/*
+	 * Lightweight spurious IRQ detection. We do not want to overdo
+	 * spurious IRQ handling - it's usually a sign of hardware problems, so
+	 * we only do the checks we can do without slowing down good hardware
+	 * nnecesserily.
+	 *
+	 * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting
+	 * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A.
+	 * Thus we can check spurious 8259A IRQs without doing the quite slow
+	 * i8259A_irq_real() call for every IRQ.  This does not cover 100% of
+	 * spurious interrupts, but should be enough to warn the user that
+	 * there is something bad going on ...
+	 */
+	if (cached_irq_mask & irqmask)
+		goto spurious_8259A_irq;
+	cached_irq_mask |= irqmask;
+
+handle_real_irq:
+	if (irq & 8) {
+		inb(0xA1);		/* DUMMY - (do we need this?) */
+		outb(cached_A1,0xA1);
+		outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
+		outb(0x62,0x20);	/* 'Specific EOI' to master-IRQ2 */
+	} else {
+		inb(0x21);		/* DUMMY - (do we need this?) */
+		outb(cached_21,0x21);
+		outb(0x60+irq,0x20);	/* 'Specific EOI' to master */
+	}
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+	return;
+
+spurious_8259A_irq:
+	/*
+	 * this is the slow path - should happen rarely.
+	 */
+	if (i8259A_irq_real(irq))
+		/*
+		 * oops, the IRQ _is_ in service according to the
+		 * 8259A - not spurious, go handle it.
+		 */
+		goto handle_real_irq;
+
+	{
+		static int spurious_irq_mask = 0;
+		/*
+		 * At this point we can be sure the IRQ is spurious,
+		 * lets ACK and report it. [once per IRQ]
+		 */
+		if (!(spurious_irq_mask & irqmask)) {
+			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+			spurious_irq_mask |= irqmask;
+		}
+		irq_err_count++;
+		/*
+		 * Theoretically we do not have to handle this IRQ,
+		 * but in Linux this does not cause problems and is
+		 * simpler for us.
+		 */
+		goto handle_real_irq;
+	}
+}
+
+void __init init_8259A(int auto_eoi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+
+	outb(0xff, 0x21);	/* mask all of 8259A-1 */
+	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
+
+	/*
+	 * outb_p - this has to work on a wide range of PC hardware.
+	 */
+	outb_p(0x11, 0x20);	/* ICW1: select 8259A-1 init */
+	outb_p(0x20 + 0, 0x21);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+	outb_p(0x04, 0x21);	/* 8259A-1 (the master) has a slave on IR2 */
+	if (auto_eoi)
+		outb_p(0x03, 0x21);	/* master does Auto EOI */
+	else
+		outb_p(0x01, 0x21);	/* master expects normal EOI */
+
+	outb_p(0x11, 0xA0);	/* ICW1: select 8259A-2 init */
+	outb_p(0x20 + 8, 0xA1);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+	outb_p(0x02, 0xA1);	/* 8259A-2 is a slave on master's IR2 */
+	outb_p(0x01, 0xA1);	/* (slave's support for AEOI in flat mode
+				    is to be investigated) */
+
+	if (auto_eoi)
+		/*
+		 * in AEOI mode we just have to mask the interrupt
+		 * when acking.
+		 */
+		i8259A_irq_type.ack = disable_8259A_irq;
+	else
+		i8259A_irq_type.ack = mask_and_ack_8259A;
+
+	udelay(100);		/* wait for 8259A to initialize */
+
+	outb(cached_21, 0x21);	/* restore master IRQ mask */
+	outb(cached_A1, 0xA1);	/* restore slave IRQ mask */
+
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+asmlinkage void i8259_do_irq(int irq, struct pt_regs regs)
+{
+	panic("i8259_do_irq: I want to be implemented");
+}
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+	no_action, 0, 0, "cascade", NULL, NULL
+};
+
+static struct resource pic1_io_resource = {
+	"pic1", 0x20, 0x3f, IORESOURCE_BUSY
+};
+
+static struct resource pic2_io_resource = {
+	"pic2", 0xa0, 0xbf, IORESOURCE_BUSY
+};
+
+/*
+ * On systems with i8259-style interrupt controllers we assume for
+ * driver compatibility reasons interrupts 0 - 15 to be the i8295
+ * interrupts even if the hardware uses a different interrupt numbering.
+ */
+void __init init_i8259_irqs (void)
+{
+	int i;
+
+	request_resource(&ioport_resource, &pic1_io_resource);
+	request_resource(&ioport_resource, &pic2_io_resource);
+	setup_irq(2, &irq2);
+
+	init_8259A(0);
+
+	for (i = 0; i < 16; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &i8259A_irq_type;
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- linux-2.4.6-pre8/arch/mips/kernel/irixsig.c	Wed Jan 24 15:21:10 2001
+++ linux/arch/mips/kernel/irixsig.c	Mon Dec  3 22:50:37 2001
@@ -714,7 +714,7 @@
 					SET_LINKS(p);
 					notify_parent(p, SIGCHLD);
 				} else
-					release(p);
+					release_task(p);
 				goto end_waitsys;
 			default:
 				continue;
diff -urN linux-2.4.6-pre8/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- linux-2.4.6-pre8/arch/mips/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/kernel/irq.c	Mon Dec  3 22:50:37 2001
@@ -8,289 +8,367 @@
  * Copyright (C) 1992 Linus Torvalds
  * Copyright (C) 1994 - 2000 Ralf Baechle
  */
-#include <linux/config.h>
-#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
 #include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
 #include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
+#include <linux/kernel_stat.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
 #include <asm/system.h>
-#include <asm/sni.h>
-#include <asm/nile4.h>
 
 /*
- * Linux has a controller-independent x86 interrupt architecture.
- * every controller has a 'controller-template', that is used
- * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the apropriate
- * controller. Thus drivers need not be aware of the
- * interrupt-controller.
- *
- * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
- * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
- * (IO-APICs assumed to be messaging to Pentium local-APICs)
- *
- * the code is designed to be easily extended with new/different
- * interrupt controllers, without having to do assembly magic.
+ * Controller mappings for all interrupt sources:
  */
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
+	{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
 
 /*
- * This contains the irq mask for both 8259A irq controllers, it's an
- * int so we can deal with the third PIC in some systems like the RM300.
- * (XXX This is broken for big endian.)
+ * Special irq handlers.
  */
-static unsigned int cached_irq_mask = 0xffff;
-
-#define __byte(x,y) (((unsigned char *)&(y))[x])
-#define __word(x,y) (((unsigned short *)&(y))[x])
-#define __long(x,y) (((unsigned int *)&(y))[x])
 
-#define cached_21       (__byte(0,cached_irq_mask))
-#define cached_A1       (__byte(1,cached_irq_mask))
-
-unsigned long spurious_count = 0;
+void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
 
 /*
- * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
- * PCI devices.  Other onboard hardware needs specific routines.
+ * Generic no controller code
  */
-static inline void mask_irq(unsigned int irq)
-{
-	cached_irq_mask |= 1 << irq;
-	if (irq & 8) {
-		outb(cached_A1, 0xa1);
-	} else {
-		outb(cached_21, 0x21);
-	}
-}
 
-static inline void unmask_irq(unsigned int irq)
-{
-	cached_irq_mask &= ~(1 << irq);
-	if (irq & 8) {
-		outb(cached_A1, 0xa1);
-	} else {
-		outb(cached_21, 0x21);
-	}
-}
-
-void i8259_disable_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	save_and_cli(flags);
-	mask_irq(irq_nr);
-	restore_flags(flags);
-}
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+	/*
+	 * 'what should we do if we get a hw irq event on an illegal vector'.
+	 * each architecture has to answer this themselves, it doesnt deserve
+	 * a generic callback i think.
+	 */
+	printk("unexpected interrupt %d\n", irq);
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none	disable_none
+#define end_none	enable_none
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	startup_none,
+	shutdown_none,
+	enable_none,
+	disable_none,
+	ack_none,
+	end_none
+};
 
-void i8259_enable_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-	save_and_cli(flags);
-	unmask_irq(irq_nr);
-	restore_flags(flags);
-}
+volatile unsigned long irq_err_count, spurious_count;
 
-static struct irqaction *irq_action[NR_IRQS] = {
-	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, 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, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
+/*
+ * Generic, controller-independent functions:
+ */
 
 int get_irq_list(char *buf)
 {
-	int i, len = 0;
 	struct irqaction * action;
+	char *p = buf;
+	int i;
+
+	p += sprintf(p, "           ");
+	for (i=0; i < 1 /*smp_num_cpus*/; i++)
+		p += sprintf(p, "CPU%d       ", i);
+	*p++ = '\n';
 
-	for (i = 0 ; i < 32 ; i++) {
-		action = irq_action[i];
+	for (i = 0 ; i < NR_IRQS ; i++) {
+		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
-			i, kstat.irqs[0][i],
-			(action->flags & SA_INTERRUPT) ? '+' : ' ',
-			action->name);
-		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
-				(action->flags & SA_INTERRUPT) ? " +" : "",
-				action->name);
-		}
-		len += sprintf(buf+len, "\n");
+		p += sprintf(p, "%3d: ",i);
+		p += sprintf(p, "%10u ", kstat_irqs(i));
+		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+		p += sprintf(p, "  %s", action->name);
+
+		for (action=action->next; action; action = action->next)
+			p += sprintf(p, ", %s", action->name);
+		*p++ = '\n';
 	}
-	return len;
-}
-
-static inline void i8259_mask_and_ack_irq(int irq)
-{
-	cached_irq_mask |= 1 << irq;
-
-	if (irq & 8) {
-		inb(0xa1);
-		outb(cached_A1, 0xa1);
-		outb(0x62, 0x20);		/* Specific EOI to cascade */
-                outb(0x20, 0xa0);
-        } else {
-		inb(0x21);
-		outb(cached_21, 0x21);
-		outb(0x20, 0x20);
-        }
+	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
+	return p - buf;
 }
 
-asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
+/*
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
+ */
+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
-	struct irqaction *action;
-	int do_random, cpu;
-
-	cpu = smp_processor_id();
-	irq_enter(cpu);
+	int status;
+	int cpu = smp_processor_id();
 
-	if (irq >= 16)
-		goto out;
+	irq_enter(cpu, irq);
 
-	i8259_mask_and_ack_irq(irq);
-
-	kstat.irqs[cpu][irq]++;
-
-	action = *(irq + irq_action);
-	if (!action)
-		goto out;
+	status = 1;	/* Force the "do bottom halves" bit */
 
 	if (!(action->flags & SA_INTERRUPT))
 		__sti();
-	action = *(irq + irq_action);
-	do_random = 0;
-       	do {
-		do_random |= action->flags;
+
+	do {
+		status |= action->flags;
 		action->handler(irq, action->dev_id, regs);
 		action = action->next;
-       	} while (action);
-	if (do_random & SA_SAMPLE_RANDOM)
+	} while (action);
+	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
 	__cli();
-	unmask_irq (irq);
 
-out:
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
+
+	return status;
 }
 
 /*
- * do_IRQ handles IRQ's that have been installed without the
- * SA_INTERRUPT flag: it uses the full signal-handling return
- * and runs with other interrupts enabled. All relatively slow
- * IRQ's should use this format: notably the keyboard/timer
- * routines.
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock. 
+ */
+ 
+/**
+ *	disable_irq_nosync - disable an irq without waiting
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line. Disables of an interrupt
+ *	stack. Unlike disable_irq(), this function does not ensure existing
+ *	instances of the IRQ handler have completed before returning.
+ *
+ *	This function may be called from IRQ context.
  */
-asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+ 
+void inline disable_irq_nosync(unsigned int irq)
 {
-	struct irqaction *action;
-	int do_random, cpu;
-
-	cpu = smp_processor_id();
-	irq_enter(cpu);
-	kstat.irqs[cpu][irq]++;
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
 
-	action = *(irq + irq_action);
-	if (action) {
-		if (!(action->flags & SA_INTERRUPT))
-			__sti();
-		action = *(irq + irq_action);
-		do_random = 0;
-        	do {
-			do_random |= action->flags;
-			action->handler(irq, action->dev_id, regs);
-			action = action->next;
-        	} while (action);
-		if (do_random & SA_SAMPLE_RANDOM)
-			add_interrupt_randomness(irq);
-		__cli();
+	spin_lock_irqsave(&desc->lock, flags);
+	if (!desc->depth++) {
+		desc->status |= IRQ_DISABLED;
+		desc->handler->disable(irq);
 	}
-	irq_exit(cpu);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
 
-	if (softirq_active(cpu)&softirq_mask(cpu))
-		do_softirq();
+/**
+ *	disable_irq - disable an irq and wait for completion
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line. Disables of an interrupt
+ *	stack. That is for two disables you need two enables. This
+ *	function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+ 
+void disable_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
 
-	/* unmasking and bottom half handling is done magically for us. */
+	if (!local_irq_count(smp_processor_id())) {
+		do {
+			barrier();
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+	}
 }
 
-int i8259_setup_irq(int irq, struct irqaction * new)
+/**
+ *	enable_irq - enable interrupt handling on an irq
+ *	@irq: Interrupt to enable
+ *
+ *	Re-enables the processing of interrupts on this IRQ line
+ *	providing no disable_irq calls are now in effect.
+ *
+ *	This function may be called from IRQ context.
+ */
+ 
+void enable_irq(unsigned int irq)
 {
-	int shared = 0;
-	struct irqaction *old, **p;
+	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	p = irq_action + irq;
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ))
-			return -EBUSY;
+	spin_lock_irqsave(&desc->lock, flags);
+	switch (desc->depth) {
+	case 1: {
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+		desc->status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			desc->status = status | IRQ_REPLAY;
+			hw_resend_irq(desc->handler,irq);
+		}
+		desc->handler->enable(irq);
+		/* fall-through */
+	}
+	default:
+		desc->depth--;
+		break;
+	case 0:
+		printk("enable_irq(%u) unbalanced from %p\n", irq,
+		       __builtin_return_address(0));
+	}
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
 
-		/* Can't share interrupts unless both are same type */
-		if ((old->flags ^ new->flags) & SA_INTERRUPT)
-			return -EBUSY;
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
+{
+	/* 
+	 * We ack quickly, we don't want the irq controller
+	 * thinking we're snobs just because some other CPU has
+	 * disabled global interrupts (we have already done the
+	 * INT_ACK cycles, it's too late to try to pretend to the
+	 * controller that we aren't taking the interrupt).
+	 *
+	 * 0 return value means that this irq is already being
+	 * handled by some other CPU. (or is disabled)
+	 */
+	int cpu = smp_processor_id();
+	irq_desc_t *desc = irq_desc + irq;
+	struct irqaction * action;
+	unsigned int status;
 
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
+	kstat.irqs[cpu][irq]++;
+	spin_lock(&desc->lock);
+	desc->handler->ack(irq);
+	/*
+	   REPLAY is when Linux resends an IRQ that was dropped earlier
+	   WAITING is used by probe to mark irqs that are being tested
+	   */
+	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+	status |= IRQ_PENDING; /* we _want_ to handle it */
+
+	/*
+	 * If the IRQ is disabled for whatever reason, we cannot
+	 * use the action we have.
+	 */
+	action = NULL;
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		action = desc->action;
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
+	desc->status = status;
 
-	if (new->flags & SA_SAMPLE_RANDOM)
-		rand_initialize_irq(irq);
-
-	save_and_cli(flags);
-	*p = new;
+	/*
+	 * If there is no IRQ handler or it was disabled, exit early.
+	   Since we set PENDING, if another processor is handling
+	   a different instance of this same irq, the other processor
+	   will take care of it.
+	 */
+	if (!action)
+		goto out;
 
-	if (!shared) {
-		if (is_i8259_irq(irq))
-		    unmask_irq(irq);
-#if CONFIG_DDB5074 /* This has no business here  */
-		else
-		    nile4_enable_irq(irq_to_nile4(irq));
-#endif
+	/*
+	 * Edge triggered interrupts need to remember
+	 * pending events.
+	 * This applies to any hw interrupts that allow a second
+	 * instance of the same irq to arrive while we are in do_IRQ
+	 * or in the handler. But the code here only handles the _second_
+	 * instance of the irq, not the third or fourth. So it is mostly
+	 * useful for irq hardware that does not mask cleanly in an
+	 * SMP environment.
+	 */
+	for (;;) {
+		spin_unlock(&desc->lock);
+		handle_IRQ_event(irq, regs, action);
+		spin_lock(&desc->lock);
+		
+		if (!(desc->status & IRQ_PENDING))
+			break;
+		desc->status &= ~IRQ_PENDING;
 	}
-	restore_flags(flags);
-	return 0;
+	desc->status &= ~IRQ_INPROGRESS;
+out:
+	/*
+	 * The ->end() handler has to deal with interrupts which got
+	 * disabled while the handler was running.
+	 */
+	desc->handler->end(irq);
+	spin_unlock(&desc->lock);
+
+	if (softirq_active(cpu) & softirq_mask(cpu))
+		do_softirq();
+	return 1;
 }
 
-/*
- * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
- * non i8259 devices.  They will have to be replaced by architecture
- * specific variants.  For now we still use this as broken as it is because
- * it used to work ...
+/**
+ *	request_irq - allocate an interrupt line
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs
+ *	@irqflags: Interrupt type flags
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A cookie passed back to the handler function
+ *
+ *	This call allocates interrupt resources and enables the
+ *	interrupt line and IRQ handling. From the point this
+ *	call is made your handler function may be invoked. Since
+ *	your handler function must clear any interrupt the board 
+ *	raises, you must take care both to initialise your hardware
+ *	and to set up the interrupt handler in the right order.
+ *
+ *	Dev_id must be globally unique. Normally the address of the
+ *	device data structure is used as the cookie. Since the handler
+ *	receives this value it makes sense to use it.
+ *
+ *	If your interrupt is shared you must pass a non NULL dev_id
+ *	as this is required when freeing the interrupt.
+ *
+ *	Flags:
+ *
+ *	SA_SHIRQ		Interrupt is shared
+ *
+ *	SA_INTERRUPT		Disable local interrupts while processing
+ *
+ *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
+ *
  */
+ 
 int request_irq(unsigned int irq, 
 		void (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, const char * devname, void *dev_id)
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
 {
 	int retval;
 	struct irqaction * action;
 
-	if (irq >= 32)
+#if 1
+	/*
+	 * Sanity-check: shared interrupts should REALLY pass in
+	 * a real dev-ID, otherwise we'll have trouble later trying
+	 * to figure out which interrupt is which (messes up the
+	 * interrupt freeing logic etc).
+	 */
+	if (irqflags & SA_SHIRQ) {
+		if (!dev_id)
+			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+	}
+#endif
+
+	if (irq >= NR_IRQS)
 		return -EINVAL;
 	if (!handler)
 		return -EINVAL;
 
-	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = (struct irqaction *)
+			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action)
 		return -ENOMEM;
 
@@ -301,107 +379,329 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
-	retval = i8259_setup_irq(irq, action);
-
+	retval = setup_irq(irq, action);
 	if (retval)
 		kfree(action);
 	return retval;
 }
-		
+
+/**
+ *	free_irq - free an interrupt
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Remove an interrupt handler. The handler is removed and if the
+ *	interrupt line is no longer in use by any driver it is disabled.
+ *	On a shared IRQ the caller must ensure the interrupt is disabled
+ *	on the card it drives before calling this function. The function
+ *	does not return until any executing interrupts for this IRQ
+ *	have completed.
+ *
+ *	This function may be called from interrupt context. 
+ *
+ *	Bugs: Attempting to free an irq in a handler for the same irq hangs
+ *	      the machine.
+ */
+ 
 void free_irq(unsigned int irq, void *dev_id)
 {
-	struct irqaction * action, **p;
+	irq_desc_t *desc;
+	struct irqaction **p;
 	unsigned long flags;
 
-	if (irq > 31) {
-		printk("Trying to free IRQ%d\n",irq);
+	if (irq >= NR_IRQS)
 		return;
-	}
-	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
-		if (action->dev_id != dev_id)
-			continue;
 
-		/* Found it - now free it */
-		save_and_cli(flags);
-		*p = action->next;
-		if (!irq[irq_action])
-			mask_irq(irq);
-		restore_flags(flags);
-		kfree(action);
+	desc = irq_desc + irq;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	for (;;) {
+		struct irqaction * action = *p;
+		if (action) {
+			struct irqaction **pp = p;
+			p = &action->next;
+			if (action->dev_id != dev_id)
+				continue;
+
+			/* Found it - now remove it from the list of entries */
+			*pp = action->next;
+			if (!desc->action) {
+				desc->status |= IRQ_DISABLED;
+				desc->handler->shutdown(irq);
+			}
+			spin_unlock_irqrestore(&desc->lock,flags);
+
+#ifdef CONFIG_SMP
+			/* Wait to make sure it's not being used on another CPU */
+			while (desc->status & IRQ_INPROGRESS)
+				barrier();
+#endif
+			kfree(action);
+			return;
+		}
+		printk("Trying to free free IRQ%d\n",irq);
+		spin_unlock_irqrestore(&desc->lock,flags);
 		return;
 	}
-	printk("Trying to free free IRQ%d\n",irq);
 }
 
-unsigned long probe_irq_on (void)
+/*
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
+ */
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ *	probe_irq_on	- begin an interrupt autodetect
+ *
+ *	Commence probing for an interrupt. The interrupts are scanned
+ *	and a mask of potential interrupt lines is returned.
+ *
+ */
+ 
+unsigned long probe_irq_on(void)
 {
-	unsigned int i, irqs = 0;
+	unsigned int i;
+	irq_desc_t *desc;
+	unsigned long val;
 	unsigned long delay;
 
-	/* first, enable any unassigned (E)ISA irqs */
-	for (i = 15; i > 0; i--) {
-		if (!irq_action[i]) {
-			i8259_enable_irq(i);
-			irqs |= (1 << i);
+	down(&probe_sem);
+	/* 
+	 * something may have generated an irq long ago and we want to
+	 * flush such a longstanding irq before considering it as spurious. 
+	 */
+	for (i = NR_IRQS-1; i > 0; i--)  {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!irq_desc[i].action) 
+			irq_desc[i].handler->startup(i);
+		spin_unlock_irq(&desc->lock);
+	}
+
+	/* Wait for longstanding interrupts to trigger. */
+	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+		/* about 20ms delay */ synchronize_irq();
+
+	/*
+	 * enable any unassigned irqs
+	 * (we must startup again here because if a longstanding irq
+	 * happened in the previous stage, it may have masked itself)
+	 */
+	for (i = NR_IRQS-1; i > 0; i--) {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!desc->action) {
+			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+			if (desc->handler->startup(i))
+				desc->status |= IRQ_PENDING;
 		}
+		spin_unlock_irq(&desc->lock);
 	}
 
-	/* wait for spurious interrupts to mask themselves out again */
-	for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
-		/* about 100ms delay */;
+	/*
+	 * Wait for spurious interrupts to trigger
+	 */
+	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+		/* about 100ms delay */ synchronize_irq();
+
+	/*
+	 * Now filter out any obviously spurious interrupts
+	 */
+	val = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			/* It triggered already - consider it spurious. */
+			if (!(status & IRQ_WAITING)) {
+				desc->status = status & ~IRQ_AUTODETECT;
+				desc->handler->shutdown(i);
+			} else
+				if (i < 32)
+					val |= 1 << i;
+		}
+		spin_unlock_irq(&desc->lock);
+	}
 
-	/* now filter out any obviously spurious interrupts */
-	return irqs & ~cached_irq_mask;
+	return val;
 }
 
-int probe_irq_off (unsigned long irqs)
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+ 
+/**
+ *	probe_irq_mask - scan a bitmap of interrupt lines
+ *	@val:	mask of interrupts to consider
+ *
+ *	Scan the ISA bus interrupt lines and return a bitmap of
+ *	active interrupts. The interrupt probe logic state is then
+ *	returned to its previous value.
+ *
+ *	Note: we need to scan all the irq's even though we will
+ *	only return ISA irq numbers - just so that we reset them
+ *	all to a known state.
+ */
+unsigned int probe_irq_mask(unsigned long val)
 {
-	unsigned int i;
+	int i;
+	unsigned int mask;
 
-#ifdef DEBUG
-	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
-#endif
-	irqs &= cached_irq_mask;
-	if (!irqs)
-		return 0;
-	i = ffz(~irqs);
-	if (irqs != (irqs & (1 << i)))
-		i = -i;
-	return i;
+	mask = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (i < 16 && !(status & IRQ_WAITING))
+				mask |= 1 << i;
+
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+	up(&probe_sem);
+
+	return mask & val;
 }
 
-int (*irq_cannonicalize)(int irq);
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source).
+ */
 
-static int i8259_irq_cannonicalize(int irq)
+/**
+ *	probe_irq_off	- end an interrupt autodetect
+ *	@val: mask of potential interrupts (unused)
+ *
+ *	Scans the unused interrupt lines and returns the line which
+ *	appears to have triggered the interrupt. If no interrupt was
+ *	found then zero is returned. If more than one interrupt is
+ *	found then minus the first candidate is returned to indicate
+ *	their is doubt.
+ *
+ *	The interrupt probe logic state is returned to its previous
+ *	value.
+ *
+ *	BUGS: When used in a module (which arguably shouldnt happen)
+ *	nothing prevents two IRQ probe callers from overlapping. The
+ *	results of this are non-optimal.
+ */
+ 
+int probe_irq_off(unsigned long val)
 {
-	return ((irq == 2) ? 9 : irq);
+	int i, irq_found, nr_irqs;
+
+	nr_irqs = 0;
+	irq_found = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING)) {
+				if (!nr_irqs)
+					irq_found = i;
+				nr_irqs++;
+			}
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+	up(&probe_sem);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
+	return irq_found;
 }
 
-void __init i8259_init(void)
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
 {
-	/* Init master interrupt controller */
-	outb(0x11, 0x20); /* Start init sequence */
-	outb(0x00, 0x21); /* Vector base */
-	outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
-	outb(0x01, 0x21); /* Select 8086 mode */
-	outb(0xff, 0x21); /* Mask all */
-        
-	/* Init slave interrupt controller */
-	outb(0x11, 0xa0); /* Start init sequence */
-	outb(0x08, 0xa1); /* Vector base */
-	outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
-	outb(0x01, 0xa1); /* Select 8086 mode */
-	outb(0xff, 0xa1); /* Mask all */
+	int shared = 0;
+	unsigned long flags;
+	struct irqaction *old, **p;
+	irq_desc_t *desc = irq_desc + irq;
+
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
 
-	outb(cached_A1, 0xa1);
-	outb(cached_21, 0x21);
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&desc->lock,flags);
+			return -EBUSY;
+		}
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	*p = new;
+
+	if (!shared) {
+		desc->depth = 0;
+		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
+		desc->handler->startup(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock,flags);
+
+	/* register_irq_proc(irq); */
+	return 0;
 }
 
-void __init init_IRQ(void)
+void __init init_generic_irq(void)
 {
-	irq_cannonicalize = i8259_irq_cannonicalize;
-	/* i8259_init(); */
-	irq_setup();
-}
+	int i;
 
-EXPORT_SYMBOL(irq_cannonicalize);
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].status  = IRQ_DISABLED;
+		irq_desc[i].action  = NULL;
+		irq_desc[i].depth   = 1;
+		irq_desc[i].handler = &no_irq_type;
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c
--- linux-2.4.6-pre8/arch/mips/kernel/mips_ksyms.c	Fri Mar  2 11:15:47 2001
+++ linux/arch/mips/kernel/mips_ksyms.c	Mon Dec  3 22:50:37 2001
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -94,9 +94,10 @@
 /*
  * Semaphore stuff
  */
-EXPORT_SYMBOL(__down_read);
-EXPORT_SYMBOL(__down_write);
-EXPORT_SYMBOL(__rwsem_wake);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
 
 /*
  * Base address of ports for Intel style I/O.
diff -urN linux-2.4.6-pre8/arch/mips/kernel/old-irq.c linux/arch/mips/kernel/old-irq.c
--- linux-2.4.6-pre8/arch/mips/kernel/old-irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/old-irq.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2001 Ralf Baechle
+ *
+ * Old rotten IRQ code.  To be killed as soon as everybody had converted or
+ * in 2.5.0, whatever comes first.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/nile4.h>
+
+/*
+ * The board specific setup routine sets irq_setup to point to a board
+ * specific setup routine.
+ */
+void (*irq_setup)(void);
+
+/*
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers, it's an
+ * int so we can deal with the third PIC in some systems like the RM300.
+ * (XXX This is broken for big endian.)
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) (((unsigned char *)&(y))[x])
+#define __word(x,y) (((unsigned short *)&(y))[x])
+#define __long(x,y) (((unsigned int *)&(y))[x])
+
+#define cached_21       (__byte(0,cached_irq_mask))
+#define cached_A1       (__byte(1,cached_irq_mask))
+
+unsigned long spurious_count = 0;
+
+/*
+ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
+ * PCI devices.  Other onboard hardware needs specific routines.
+ */
+static inline void mask_irq(unsigned int irq)
+{
+	cached_irq_mask |= 1 << irq;
+	if (irq & 8) {
+		outb(cached_A1, 0xa1);
+	} else {
+		outb(cached_21, 0x21);
+	}
+}
+
+static inline void unmask_irq(unsigned int irq)
+{
+	cached_irq_mask &= ~(1 << irq);
+	if (irq & 8) {
+		outb(cached_A1, 0xa1);
+	} else {
+		outb(cached_21, 0x21);
+	}
+}
+
+void i8259_disable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	mask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+void i8259_enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	save_and_cli(flags);
+	unmask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+static struct irqaction *irq_action[NR_IRQS] = {
+	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, 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, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	struct irqaction * action;
+
+	for (i = 0 ; i < 32 ; i++) {
+		action = irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			i, kstat.irqs[0][i],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, "\n");
+	}
+	return len;
+}
+
+static inline void i8259_mask_and_ack_irq(int irq)
+{
+	cached_irq_mask |= 1 << irq;
+
+	if (irq & 8) {
+		inb(0xa1);
+		outb(cached_A1, 0xa1);
+		outb(0x62, 0x20);		/* Specific EOI to cascade */
+                outb(0x20, 0xa0);
+        } else {
+		inb(0x21);
+		outb(cached_21, 0x21);
+		outb(0x20, 0x20);
+        }
+}
+
+asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+	cpu = smp_processor_id();
+	irq_enter(cpu, irq);
+
+	if (irq >= 16)
+		goto out;
+
+	i8259_mask_and_ack_irq(irq);
+
+	kstat.irqs[cpu][irq]++;
+
+	action = *(irq + irq_action);
+	if (!action)
+		goto out;
+
+	if (!(action->flags & SA_INTERRUPT))
+		__sti();
+	action = *(irq + irq_action);
+	do_random = 0;
+       	do {
+		do_random |= action->flags;
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+       	} while (action);
+	if (do_random & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	__cli();
+	unmask_irq (irq);
+
+out:
+	irq_exit(cpu, irq);
+}
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts enabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
+ */
+asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+	cpu = smp_processor_id();
+	irq_enter(cpu, irq);
+	kstat.irqs[cpu][irq]++;
+
+	action = *(irq + irq_action);
+	if (action) {
+		if (!(action->flags & SA_INTERRUPT))
+			__sti();
+		action = *(irq + irq_action);
+		do_random = 0;
+        	do {
+			do_random |= action->flags;
+			action->handler(irq, action->dev_id, regs);
+			action = action->next;
+        	} while (action);
+		if (do_random & SA_SAMPLE_RANDOM)
+			add_interrupt_randomness(irq);
+		__cli();
+	}
+	irq_exit(cpu, irq);
+
+	if (softirq_active(cpu)&softirq_mask(cpu))
+		do_softirq();
+
+	/* unmasking and bottom half handling is done magically for us. */
+}
+
+int i8259_setup_irq(int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	p = irq_action + irq;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	save_and_cli(flags);
+	*p = new;
+
+	if (!shared) {
+		if (is_i8259_irq(irq))
+		    unmask_irq(irq);
+#if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476))
+		else
+		    nile4_enable_irq(irq_to_nile4(irq));
+#endif
+	}
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
+ * non i8259 devices.  They will have to be replaced by architecture
+ * specific variants.  For now we still use this as broken as it is because
+ * it used to work ...
+ */
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, const char * devname, void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+	if (irq >= 32)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = i8259_setup_irq(irq, action);
+
+	if (retval)
+		kfree(action);
+	return retval;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction * action, **p;
+	unsigned long flags;
+
+	if (irq > 31) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		save_and_cli(flags);
+		*p = action->next;
+		if (!irq[irq_action])
+			mask_irq(irq);
+		restore_flags(flags);
+		kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n",irq);
+}
+
+unsigned long probe_irq_on (void)
+{
+	unsigned int i, irqs = 0;
+	unsigned long delay;
+
+	/* first, enable any unassigned (E)ISA irqs */
+	for (i = 15; i > 0; i--) {
+		if (!irq_action[i]) {
+			i8259_enable_irq(i);
+			irqs |= (1 << i);
+		}
+	}
+
+	/* wait for spurious interrupts to mask themselves out again */
+	for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
+		/* about 100ms delay */;
+
+	/* now filter out any obviously spurious interrupts */
+	return irqs & ~cached_irq_mask;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+	unsigned int i;
+
+#ifdef DEBUG
+	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
+#endif
+	irqs &= cached_irq_mask;
+	if (!irqs)
+		return 0;
+	i = ffz(~irqs);
+	if (irqs != (irqs & (1 << i)))
+		i = -i;
+	return i;
+}
+
+void __init i8259_init(void)
+{
+	/* Init master interrupt controller */
+	outb(0x11, 0x20); /* Start init sequence */
+	outb(0x00, 0x21); /* Vector base */
+	outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+	outb(0x01, 0x21); /* Select 8086 mode */
+	outb(0xff, 0x21); /* Mask all */
+        
+	/* Init slave interrupt controller */
+	outb(0x11, 0xa0); /* Start init sequence */
+	outb(0x08, 0xa1); /* Vector base */
+	outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
+	outb(0x01, 0xa1); /* Select 8086 mode */
+	outb(0xff, 0xa1); /* Mask all */
+
+	outb(cached_A1, 0xa1);
+	outb(cached_21, 0x21);
+}
+
+void __init init_IRQ(void)
+{
+	/* i8259_init(); */
+	irq_setup();
+}
diff -urN linux-2.4.6-pre8/arch/mips/kernel/old-time.c linux/arch/mips/kernel/old-time.c
--- linux-2.4.6-pre8/arch/mips/kernel/old-time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/old-time.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ * Copyright (C) 1996 - 2000  Ralf Baechle
+ *
+ * This file contains the time handling details for PC-style clocks as
+ * found in some MIPS systems.
+ */
+/**************************************************************************
+ *  9 Nov, 2000.
+ *  Changed init_cycle_counter() routine, use the mips_cpu structure.
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ddb5074.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern volatile unsigned long wall_jiffies;
+unsigned long r4k_interval;
+extern rwlock_t xtime_lock;
+
+/*
+ * Change this if you have some constant time drift
+ */
+/* This is the value for the PC-style PICs. */
+/* #define USECS_PER_JIFFY (1000020/HZ) */
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi, timerlo;
+
+/*
+ * On MIPS only R4000 and better have a cycle counter.
+ *
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res, tmp;
+
+	/* Last jiffy when do_fast_gettimeoffset() was called. */
+	static unsigned long last_jiffies;
+	unsigned long quotient;
+
+	/*
+	 * Cached "1/(clocks per usec)*2^32" value.
+	 * It has to be recalculated once each jiffy.
+	 */
+	static unsigned long cached_quotient;
+
+	tmp = jiffies;
+
+	quotient = cached_quotient;
+
+	if (tmp && last_jiffies != tmp) {
+		last_jiffies = tmp;
+		__asm__(".set\tnoreorder\n\t"
+			".set\tnoat\n\t"
+			".set\tmips3\n\t"
+			"lwu\t%0,%2\n\t"
+			"dsll32\t$1,%1,0\n\t"
+			"or\t$1,$1,%0\n\t"
+			"ddivu\t$0,$1,%3\n\t"
+			"mflo\t$1\n\t"
+			"dsll32\t%0,%4,0\n\t"
+			"nop\n\t"
+			"ddivu\t$0,%0,$1\n\t"
+			"mflo\t%0\n\t"
+			".set\tmips0\n\t"
+			".set\tat\n\t"
+			".set\treorder"
+			:"=&r" (quotient)
+			:"r" (timerhi),
+			 "m" (timerlo),
+			 "r" (tmp),
+			 "r" (USECS_PER_JIFFY)
+			:"$1");
+		cached_quotient = quotient;
+	}
+
+	/* Get last timer tick in absolute kernel time */
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* .. relative to previous jiffy (32 bits is enough) */
+	count -= timerlo;
+
+	__asm__("multu\t%1,%2\n\t"
+		"mfhi\t%0"
+		:"=r" (res)
+		:"r" (count),
+		 "r" (quotient));
+
+	/*
+ 	 * Due to possible jiffies inconsistencies, we need to check 
+	 * the result so that we'll get a timer that is monotonic.
+	 */
+	if (res >= USECS_PER_JIFFY)
+		res = USECS_PER_JIFFY-1;
+
+	return res;
+}
+
+/* This function must be called with interrupts disabled 
+ * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
+ * 
+ * However, the pc-audio speaker driver changes the divisor so that
+ * it gets interrupted rather more often - it loads 64 into the
+ * counter rather than 11932! This has an adverse impact on
+ * do_gettimeoffset() -- it stops working! What is also not
+ * good is that the interval that our timer function gets called
+ * is no longer 10.0002 ms, but 9.9767 ms. To get around this
+ * would require using a different timing source. Maybe someone
+ * could use the RTC - I know that this can interrupt at frequencies
+ * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
+ * it so that at startup, the timer code in sched.c would select
+ * using either the RTC or the 8253 timer. The decision would be
+ * based on whether there was any other device around that needed
+ * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
+ * and then do some jiggery to have a version of do_timer that 
+ * advanced the clock by 1/1024 s. Every time that reached over 1/100
+ * of a second, then do all the old code. If the time was kept correct
+ * then do_gettimeoffset could just return 0 - there is no low order
+ * divider that can be accessed.
+ *
+ * Ideally, you would be able to use the RTC for the speaker driver,
+ * but it appears that the speaker driver really needs interrupt more
+ * often than every 120 us or so.
+ *
+ * Anyway, this needs more thought....		pjsg (1993-08-28)
+ * 
+ * If you are really that interested, you should be reading
+ * comp.protocols.time.ntp!
+ */
+
+#define TICK_SIZE tick
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+	int count;
+
+	static int count_p = LATCH;    /* for the first call after boot */
+	static unsigned long jiffies_p;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
+
+	/* timer count may underflow right here */
+	outb_p(0x00, 0x43);	/* latch the count ASAP */
+
+	count = inb_p(0x40);	/* read the latched count */
+
+	/*
+	 * We do this guaranteed double memory access instead of a _p 
+	 * postfix in the previous port access. Wheee, hackady hack
+	 */
+	jiffies_t = jiffies;
+
+	count |= inb_p(0x40) << 8;
+
+	/*
+	 * avoiding timer inconsistencies (they are rare, but they happen)...
+	 * there are two kinds of problems that must be avoided here:
+	 *  1. the timer counter underflows
+	 *  2. hardware problem with the timer, not giving us continuous time,
+	 *     the counter does small "jumps" upwards on some Pentium systems,
+	 *     (see c't 95/10 page 335 for Neptun bug.)
+	 */
+
+	if( jiffies_t == jiffies_p ) {
+		if( count > count_p ) {
+			/* the nutcase */
+
+			outb_p(0x0A, 0x20);
+
+			/* assumption about timer being IRQ1 */
+			if (inb(0x20) & 0x01) {
+				/*
+				 * We cannot detect lost timer interrupts ... 
+				 * well, that's why we call them lost, don't we? :)
+				 * [hmm, on the Pentium and Alpha we can ... sort of]
+				 */
+				count -= LATCH;
+			} else {
+				printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+			}
+		}
+	} else
+		jiffies_p = jiffies_t;
+
+	count_p = count;
+
+	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = (count + LATCH/2) / LATCH;
+
+	return count;
+}
+
+static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+
+	read_lock_irqsave (&xtime_lock, flags);
+	*tv = xtime;
+	tv->tv_usec += do_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+	 * is nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (jiffies - wall_jiffies)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	read_unlock_irqrestore (&xtime_lock, flags);
+
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	write_lock_irq (&xtime_lock);
+
+	/* This is revolting. We need to set the xtime.tv_usec
+	 * correctly. However, the value in this location is
+	 * is value at the last tick.
+	 * Discover what correction gettimeofday
+	 * would have done, and then undo it!
+	 */
+	tv->tv_usec -= do_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+
+	write_unlock_irq (&xtime_lock);
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+ 		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static void inline
+timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+#ifdef CONFIG_DDB5074
+	static unsigned cnt, period, dist;
+
+	if (cnt == 0 || cnt == dist)
+	    ddb5074_led_d2(1);
+	else if (cnt == 7 || cnt == dist+7)
+	    ddb5074_led_d2(0);
+	
+	if (++cnt > period) {
+	    cnt = 0;
+	    /* The hyperbolic function below modifies the heartbeat period
+	     * length in dependency of the current (5min) load. It goes
+	     * through the points f(0)=126, f(1)=86, f(5)=51,
+	     * f(inf)->30. */
+	     period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+	     dist = period / 4;
+	}
+#endif
+	if(!user_mode(regs)) {
+		if (prof_buffer && current->pid) {
+			extern int _stext;
+			unsigned long pc = regs->cp0_epc;
+
+			pc -= (unsigned long) &_stext;
+			pc >>= prof_shift;
+			/*
+			 * Dont ignore out-of-bounds pc values silently,
+			 * put them into the last histogram slot, so if
+			 * present, they will show up as a sharp peak.
+			 */
+			if (pc > prof_len-1)
+				pc = prof_len-1;
+			atomic_inc((atomic_t *)&prof_buffer[pc]);
+		}
+	}
+	do_timer(regs);
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	read_lock (&xtime_lock); 
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
+	  if (set_rtc_mmss(xtime.tv_sec) == 0)
+	    last_rtc_update = xtime.tv_sec;
+	  else
+	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+	}
+	/* As we return to user mode fire off the other CPU schedulers.. this is 
+	   basically because we don't yet share IRQ's around. This message is
+	   rigged to be safe on the 386 - basically it's a hack, so don't look
+	   closely for now.. */
+	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
+	read_unlock (&xtime_lock); 
+}
+
+static inline void 
+r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	unsigned int count;
+
+	/*
+	 * The cycle counter is only 32 bit which is good for about
+	 * a minute at current count rates of upto 150MHz or so.
+	 */
+	count = read_32bit_cp0_register(CP0_COUNT);
+	timerhi += (count < timerlo);	/* Wrap around */
+	timerlo = count;
+
+#ifdef CONFIG_SGI_IP22
+	/* Since we don't get anything but r4k timer interrupts, we need to
+	 * set this up so that we'll get one next time. Fortunately since we
+	 * have timerhi/timerlo, we don't care so much if we miss one. So
+	 * we need only ask for the next in r4k_interval counts. On other
+	 * archs we have a real timer, so we don't want this.
+	 */
+	write_32bit_cp0_register (CP0_COMPARE, 
+				  (unsigned long) (count + r4k_interval));
+        kstat.irqs[0][irq]++;
+#endif
+
+	timer_interrupt(irq, dev_id, regs);
+
+	if (!jiffies)
+	{
+		/*
+		 * If jiffies has overflowed in this timer_interrupt we must
+		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
+		 * quotient calc still valid. -arca
+		 */
+		timerhi = timerlo = 0;
+	}
+}
+
+void indy_r4k_timer_interrupt (struct pt_regs *regs)
+{
+	static const int INDY_R4K_TIMER_IRQ = 7;
+	r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs);
+}
+
+struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0,
+                                  "timer", NULL, NULL};
+
+
+void (*board_time_init)(struct irqaction *irq);
+
+void __init time_init(void)
+{
+	unsigned int epoch = 0, year, mon, day, hour, min, sec;
+	int i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+
+	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c so
+	   no stupid things will happen to timekeeping.  Who knows, maybe Ultrix
+  	   also uses 1952 as epoch ...  */
+	if (year > 10 && year < 44) {
+		epoch = 1980;
+	} else if (year < 96) {
+		epoch = 1952;
+	}
+	year += epoch;
+
+	write_lock_irq (&xtime_lock);
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_usec = 0;
+	write_unlock_irq (&xtime_lock);
+
+	if (mips_cpu.options & MIPS_CPU_COUNTER) {
+		write_32bit_cp0_register(CP0_COUNT, 0);
+		do_gettimeoffset = do_fast_gettimeoffset;
+		irq0.handler = r4k_timer_interrupt;
+	}
+
+	board_time_init(&irq0);
+}
diff -urN linux-2.4.6-pre8/arch/mips/kernel/pci-dma.c linux/arch/mips/kernel/pci-dma.c
--- linux-2.4.6-pre8/arch/mips/kernel/pci-dma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/pci-dma.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,41 @@
+/*
+ * 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) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000  Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t * dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		dma_cache_wback_inv((unsigned long) ret, size);
+		*dma_handle = virt_to_bus(ret);
+		ret = KSEG1ADDR(ret);
+	}
+
+	return ret;
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long) KSEG0ADDR(vaddr), get_order(size));
+}
diff -urN linux-2.4.6-pre8/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c
--- linux-2.4.6-pre8/arch/mips/kernel/proc.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/proc.c	Mon Dec  3 22:50:37 2001
@@ -7,12 +7,16 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/watch.h>
 
 unsigned long unaligned_instructions;
 unsigned int vced_count, vcei_count;
+#if !defined(CONFIG_CPU_HAS_LLSC)
+unsigned long ll_ops, sc_ops;
+#endif
 
 /*
  * BUFFER is PAGE_SIZE bytes long.
@@ -35,32 +39,37 @@
 	const char *mach_cobalt_names[] = GROUP_COBALT_NAMES;
 	const char *mach_nec_ddb_names[] = GROUP_NEC_DDB_NAMES;
 	const char *mach_baget_names[] = GROUP_BAGET_NAMES;
+	const char *mach_cosine_names[] = GROUP_COSINE_NAMES;
+	const char *mach_galileo_names[] = GROUP_GALILEO_NAMES;
+	const char *mach_momenco_names[] = GROUP_MOMENCO_NAMES;
+ 	const char *mach_ite_names[] = GROUP_ITE_NAMES;
+	const char *mach_philips_names[] = GROUP_PHILIPS_NAMES;
+ 	const char *mach_globespan_names[] = GROUP_GLOBESPAN_NAMES;
+	const char *mach_sibyte_names[] = GROUP_SIBYTE_NAMES;
+	const char *mach_toshiba_names[] = GROUP_TOSHIBA_NAMES;
+	const char *mach_alchemy_names[] = GROUP_ALCHEMY_NAMES;
 	const char **mach_group_to_name[] = { mach_unknown_names,
-	                                      mach_jazz_names,
-	                                      mach_dec_names,
-	                                      mach_arc_names,
-	                                      mach_sni_rm_names,
-	                                      mach_acn_names,
-	                                      mach_sgi_names,
-					      mach_cobalt_names,
-					      mach_nec_ddb_names,
-					      mach_baget_names };
+		mach_jazz_names, mach_dec_names, mach_arc_names,
+		mach_sni_rm_names, mach_acn_names, mach_sgi_names,
+		mach_cobalt_names, mach_nec_ddb_names, mach_baget_names,
+		mach_cosine_names, mach_galileo_names, mach_momenco_names, 
+		mach_ite_names, mach_philips_names, mach_globespan_names,
+		mach_sibyte_names, mach_toshiba_names, mach_alchemy_names};
 	unsigned int version = read_32bit_cp0_register(CP0_PRID);
 	int len;
 
 	len = sprintf(buffer, "cpu\t\t\t: MIPS\n");
 	len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n",
-	               cpu_name[mips_cputype <= CPU_LAST ?
-	                        mips_cputype :
-	                        CPU_UNKNOWN],
-	               (version >> 4) & 0x0f,
-	               version & 0x0f);
+	               cpu_name[mips_cpu.cputype <= CPU_LAST ?
+	                        mips_cpu.cputype : CPU_UNKNOWN],
+	               (version >> 4) & 0x0f, version & 0x0f);
 	len += sprintf(buffer + len, "system type\t\t: %s %s\n",
 		       mach_group_names[mips_machgroup],
 		       mach_group_to_name[mips_machgroup][mips_machtype]);
 	len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n",
-		       (loops_per_sec + 2500) / 500000,
-	               ((loops_per_sec + 2500) / 5000) % 100);
+		       loops_per_jiffy/(500000/HZ),
+		       (loops_per_jiffy/(5000/HZ)) % 100);
+
 #if defined (__MIPSEB__)
 	len += sprintf(buffer + len, "byteorder\t\t: big endian\n");
 #endif
@@ -72,17 +81,23 @@
 	len += sprintf(buffer + len, "wait instruction\t: %s\n",
 	               cpu_wait ? "yes" : "no");
 	len += sprintf(buffer + len, "microsecond timers\t: %s\n",
-	               cyclecounter_available ? "yes" : "no");
+	               (mips_cpu.options & MIPS_CPU_COUNTER) ? "yes" : "no");
 	len += sprintf(buffer + len, "extra interrupt vector\t: %s\n",
 	               dedicated_iv_available ? "yes" : "no");
 	len += sprintf(buffer + len, "hardware watchpoint\t: %s\n",
 	               watch_available ? "yes" : "no");
 
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
-	        vce_available ? "%d" : "not available");
+	        (mips_cpu.options & MIPS_CPU_VCE) ? "%d" : "not available");
 	len += sprintf(buffer + len, fmt, 'D', vced_count);
 	len += sprintf(buffer + len, fmt, 'I', vcei_count);
 
+#if !defined(CONFIG_CPU_HAS_LLSC)
+	len += sprintf(buffer + len, "ll emulations\t\t: %lu\n",
+		       ll_ops);
+	len += sprintf(buffer + len, "sc emulations\t\t: %lu\n",
+		       sc_ops);
+#endif
 	return len;
 }
 
diff -urN linux-2.4.6-pre8/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- linux-2.4.6-pre8/arch/mips/kernel/process.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/process.c	Mon Dec  3 22:50:37 2001
@@ -162,21 +162,21 @@
 	long retval;
 
 	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"move\t$6,$sp\n\t"
-		"move\t$4,%5\n\t"
-		"li\t$2,%1\n\t"
-		"syscall\n\t"
-		"beq\t$6,$sp,1f\n\t"
-		"subu\t$sp,32\n\t"	/* delay slot */
-		"jalr\t%4\n\t"
-		"move\t$4,%3\n\t"	/* delay slot */
-		"move\t$4,$2\n\t"
-		"li\t$2,%2\n\t"
-		"syscall\n"
-		"1:\taddiu\t$sp,32\n\t"
-		"move\t%0,$2\n\t"
-		".set\treorder"
+		".set noreorder               \n"
+		"    move    $6,$sp           \n"
+		"    move    $4,%5            \n"
+		"    li      $2,%1            \n"
+		"    syscall                  \n"
+		"    beq     $6,$sp,1f        \n"
+		"    subu    $sp,32           \n"	/* delay slot */
+		"    jalr    %4               \n"
+		"    move    $4,%3            \n"	/* delay slot */
+		"    move    $4,$2            \n"
+		"    li      $2,%2            \n"
+		"    syscall                  \n"
+		"1:  addiu   $sp,32           \n"
+		"    move    %0,$2            \n"
+		".set reorder"
 		:"=r" (retval)
 		:"i" (__NR_clone), "i" (__NR_exit),
 		 "r" (arg), "r" (fn),
@@ -199,27 +199,47 @@
 #define first_sched	((unsigned long) scheduling_functions_start_here)
 #define last_sched	((unsigned long) scheduling_functions_end_here)
 
+/* get_wchan - a maintenance nightmare ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
-	unsigned long schedule_frame;
-	unsigned long pc;
+	unsigned long frame, pc;
 
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
 	pc = thread_saved_pc(&p->thread);
-	if (pc == (unsigned long) interruptible_sleep_on
-	    || pc == (unsigned long) sleep_on) {
-		schedule_frame = ((unsigned long *)p->thread.reg30)[9];
-		return ((unsigned long *)schedule_frame)[15];
-	}
-	if (pc == (unsigned long) interruptible_sleep_on_timeout
-	    || pc == (unsigned long) sleep_on_timeout) {
-		schedule_frame = ((unsigned long *)p->thread.reg30)[9];
-		return ((unsigned long *)schedule_frame)[16];
+	if (pc < first_sched || pc >= last_sched) {
+		return pc;
 	}
+
+	if (pc >= (unsigned long) sleep_on_timeout)
+		goto schedule_timeout_caller;
+	if (pc >= (unsigned long) sleep_on)
+		goto schedule_caller;
+	if (pc >= (unsigned long) interruptible_sleep_on_timeout)
+		goto schedule_timeout_caller;
+	if (pc >= (unsigned long)interruptible_sleep_on)
+		goto schedule_caller;
+	goto schedule_timeout_caller;
+
+schedule_caller:
+	frame = ((unsigned long *)p->thread.reg30)[9];
+	pc    = ((unsigned long *)frame)[11];
+	return pc;
+
+schedule_timeout_caller:
+	/* Must be schedule_timeout ...  */
+	pc    = ((unsigned long *)p->thread.reg30)[10];
+	frame = ((unsigned long *)p->thread.reg30)[9];
+
+	/* The schedule_timeout frame ...  */
+	pc    = ((unsigned long *)frame)[14];
+	frame = ((unsigned long *)frame)[13];
+
 	if (pc >= first_sched && pc < last_sched) {
-		printk(KERN_DEBUG "Bug in %s\n", __FUNCTION__);
+		/* schedule_timeout called by interruptible_sleep_on_timeout */
+		pc    = ((unsigned long *)frame)[11];
+		frame = ((unsigned long *)frame)[10];
 	}
 
 	return pc;
diff -urN linux-2.4.6-pre8/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- linux-2.4.6-pre8/arch/mips/kernel/ptrace.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/ptrace.c	Mon Dec  3 22:50:37 2001
@@ -207,7 +207,7 @@
 
 	case PTRACE_POKEUSR: {
 		struct pt_regs *regs;
-		int res = 0;
+		res = 0;
 		regs = (struct pt_regs *) ((unsigned long) child +
 		       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
 
@@ -289,7 +289,7 @@
 	 */
 	case PTRACE_KILL:
 		res = 0;
-		if (child->state != TASK_ZOMBIE)	/* already dead */
+		if (child->state == TASK_ZOMBIE)	/* already dead */
 			break;
 		child->exit_code = SIGKILL;
 		wake_up_process(child);
@@ -299,7 +299,7 @@
 		res = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
+		child->ptrace = 0;
 		child->exit_code = data;
 		write_lock_irq(&tasklist_lock);
 		REMOVE_LINKS(child);
@@ -310,6 +310,14 @@
 		res = 0;
 		break;
 
+	case PTRACE_SETOPTIONS:
+		if (data & PTRACE_O_TRACESYSGOOD)
+			child->ptrace |= PT_TRACESYSGOOD;
+		else
+			child->ptrace &= ~PT_TRACESYSGOOD;
+		res = 0;
+		break;
+
 	default:
 		res = -EIO;
 		goto out;
@@ -326,7 +334,10 @@
 	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
 			!= (PT_PTRACED|PT_TRACESYS))
 		return;
-	current->exit_code = SIGTRAP;
+	/* The 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
+	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+	                                ? 0x80 : 0);
 	current->state = TASK_STOPPED;
 	notify_parent(current, SIGCHLD);
 	schedule();
diff -urN linux-2.4.6-pre8/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S
--- linux-2.4.6-pre8/arch/mips/kernel/r2300_fpu.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r2300_fpu.S	Mon Dec  3 22:50:37 2001
@@ -117,6 +117,7 @@
 	jr	ra
 	 ctc1	t0,fcr31
 	END(_restore_fp_context)
+	.set	reorder
 
 	.type	fault@function
 	.ent	fault
diff -urN linux-2.4.6-pre8/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
--- linux-2.4.6-pre8/arch/mips/kernel/r2300_switch.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r2300_switch.S	Mon Dec  3 22:50:37 2001
@@ -34,6 +34,9 @@
  *                     task_struct *next)
  */
 LEAF(resume)
+#ifndef CONFIG_CPU_HAS_LLSC
+	sw      zero, ll_bit
+#endif
 	mfc0	t1, CP0_STATUS
 	sw	t1, THREAD_STATUS(a0)
 	CPU_SAVE_NONSCRATCH(a0)
diff -urN linux-2.4.6-pre8/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S
--- linux-2.4.6-pre8/arch/mips/kernel/r4k_fpu.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r4k_fpu.S	Mon Dec  3 22:50:37 2001
@@ -93,6 +93,7 @@
 	jr	ra
 	 ctc1	t0,fcr31
 	END(_restore_fp_context)
+	.set	reorder
 
 	.type	fault@function
 	.ent	fault
diff -urN linux-2.4.6-pre8/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S
--- linux-2.4.6-pre8/arch/mips/kernel/r4k_misc.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r4k_misc.S	Mon Dec  3 22:50:37 2001
@@ -35,10 +35,25 @@
 	 * in register PTE, a ptr into the table in which
 	 * the pte belongs is in PTR.
 	 */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, current_pgd;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);          
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, current_pgd;
+#endif
+	
+	
 #define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
 	mfc0	pte, CP0_BADVADDR; \
 	srl	pte, pte, 22; \
-	lw	ptr, current_pgd; \
 	sll	pte, pte, 2; \
 	addu	ptr, ptr, pte; \
 	mfc0	pte, CP0_BADVADDR; \
diff -urN linux-2.4.6-pre8/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S
--- linux-2.4.6-pre8/arch/mips/kernel/r4k_switch.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r4k_switch.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,4 @@
-/* $Id: r4k_switch.S,v 1.9 1999/08/18 23:37:44 ralf Exp $
- *
+/*
  * 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.
@@ -38,6 +37,9 @@
 	.set	noreorder
 	.align	5
 	LEAF(resume)
+#ifndef CONFIG_CPU_HAS_LLSC
+	sw      zero, ll_bit
+#endif
 	mfc0	t1, CP0_STATUS
 	sw	t1, THREAD_STATUS(a0)
 	CPU_SAVE_NONSCRATCH(a0)
@@ -50,7 +52,16 @@
 	move	$28, a1
 	CPU_RESTORE_NONSCRATCH($28)
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
+#ifdef CONFIG_SMP	 
+	mfc0	a3, CP0_CONTEXT
+	la	t1, kernelsp
+	srl	a3, 23
+	sll	a3, 2
+	addu	t1, a3, t1
+	sw	t0, (t1)	
+#else
 	sw	t0, kernelsp
+#endif 
 	mfc0	t1, CP0_STATUS		/* Do we really need this? */
 	li	a3, 0xff00
 	and	t1, a3
diff -urN linux-2.4.6-pre8/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S
--- linux-2.4.6-pre8/arch/mips/kernel/scall_o32.S	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/kernel/scall_o32.S	Mon Dec  3 22:50:37 2001
@@ -65,8 +65,14 @@
 1:	sw	v0, PT_R2(sp)		# result
 
 EXPORT(o32_ret_from_sys_call)
-	lw	t0, irq_stat		# softirq_active
-	lw	t1, irq_stat+4		# softirq_mask.  unused delay slot
+	la	t1, irq_stat		# softirq_active
+#ifdef CONFIG_SMP
+	lw	t0, TASK_PROCESSOR($28)
+        sll	t0, t0, 5
+	addu	t1, t0
+#endif
+	lw	t0, 0(t1)		# softirq_active
+	lw	t1, 4(t1)		# softirq_mask.  unused delay slot
 	and	t0, t1
 	bnez	t0, o32_handle_softirq
 
diff -urN linux-2.4.6-pre8/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- linux-2.4.6-pre8/arch/mips/kernel/setup.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/setup.c	Mon Dec  3 22:50:37 2001
@@ -26,13 +26,9 @@
 #include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/bootmem.h>
-#ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
-#endif
 #include <linux/ide.h>
-#ifdef CONFIG_RTC
 #include <linux/timex.h>
-#endif
 
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
@@ -45,7 +41,8 @@
 #include <asm/sgialib.h>
 #endif
 
-struct mips_cpuinfo boot_cpu_data = { NULL, NULL, 0 };
+
+struct mips_cpuinfo boot_cpu_data = { 0, NULL, NULL, 0 };
 
 /*
  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
@@ -57,11 +54,6 @@
 void (*cpu_wait)(void) = NULL;
 
 /*
- * Do we have a cyclecounter available?
- */
-char cyclecounter_available;
-
-/*
  * There are several bus types available for MIPS machines.  "RISC PC"
  * type machines have ISA, EISA, VLB or PCI available, DECstations
  * have Turbochannel or Q-Bus, SGI has GIO, there are lots of VME
@@ -72,16 +64,16 @@
 
 struct screen_info screen_info;
 
-#ifdef CONFIG_BLK_DEV_FD
 extern struct fd_ops no_fd_ops;
 struct fd_ops *fd_ops;
-#endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 extern struct ide_ops no_ide_ops;
 struct ide_ops *ide_ops;
 #endif
 
+extern void * __rd_start, * __rd_end;
+
 extern struct rtc_ops no_rtc_ops;
 struct rtc_ops *rtc_ops;
 
@@ -95,23 +87,17 @@
  *
  * These are initialized so they are in the .data section
  */
-unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
-unsigned long mips_cputype = CPU_UNKNOWN;
 unsigned long mips_machtype = MACH_UNKNOWN;
 unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
 
+struct boot_mem_map boot_mem_map;
+
 unsigned char aux_device_present;
-extern int _end;
+extern char _ftext, _etext, _fdata, _edata, _end;
 
-static char command_line[CL_SIZE] = { 0, };
-       char saved_command_line[CL_SIZE];
-extern char arcs_cmdline[CL_SIZE];
-
-/*
- * The board specific setup routine sets irq_setup to point to a board
- * specific setup routine.
- */
-void (*irq_setup)(void);
+static char command_line[COMMAND_LINE_SIZE];
+       char saved_command_line[COMMAND_LINE_SIZE];
+extern char arcs_cmdline[COMMAND_LINE_SIZE];
 
 /*
  * mips_io_port_base is the begin of the address space to which x86 style
@@ -129,7 +115,10 @@
 extern void SetUpBootInfo(void);
 extern void loadmmu(void);
 extern asmlinkage void start_kernel(void);
-extern int prom_init(int, char **, char **, int *);
+extern void prom_init(int, char **, char **, int *);
+
+static struct resource code_resource = { "Kernel code" };
+static struct resource data_resource = { "Kernel data" };
 
 /*
  * Probe whether cpu has config register by trying to play with
@@ -143,9 +132,9 @@
 	unsigned long size1, size2; 
 	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
 
-	size1 = r3k_cache_size(ST0_DE);
+	size1 = r3k_cache_size(ST0_ISC);
 	write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC);
-	size2 = r3k_cache_size(ST0_DE);
+	size2 = r3k_cache_size(ST0_ISC);
 	write_32bit_cp0_register(CP0_CONF, cfg);
 	return size1 != size2;
 #else
@@ -165,152 +154,230 @@
 
 static inline void cpu_probe(void)
 {
+
+#ifdef CONFIG_CPU_MIPS32
 	unsigned long config1;
+#endif
 
 	mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID);
-	switch (mips_cpu.processor_id & 0xff00) {
-	case PRID_IMP_R2000:
-		mips_cpu.cputype = CPU_R2000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
-		mips_cpu.tlbsize = 64;
-		break;
-	case PRID_IMP_R3000:
-		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
-			if (cpu_has_confreg())
-				mips_cpu.cputype = CPU_R3081E;
+	switch (mips_cpu.processor_id & 0xff0000) {
+	case PRID_COMP_LEGACY:
+		switch (mips_cpu.processor_id & 0xff00) {
+		case PRID_IMP_R2000:
+			mips_cpu.cputype = CPU_R2000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_I;
+			mips_cpu.options = MIPS_CPU_TLB;
+			mips_cpu.tlbsize = 64;
+			break;
+		case PRID_IMP_R3000:
+			if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
+				if (cpu_has_confreg())
+					mips_cpu.cputype = CPU_R3081E;
+				else
+					mips_cpu.cputype = CPU_R3000A;
 			else
-				mips_cpu.cputype = CPU_R3000A;
-		else
-			 mips_cpu.cputype = CPU_R3000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
-		mips_cpu.tlbsize = 64;
-		break;
-	case PRID_IMP_R4000:
-		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
-			mips_cpu.cputype = CPU_R4400SC;
-		else
-			mips_cpu.cputype = CPU_R4000SC;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-		                   MIPS_CPU_WATCH | MIPS_CPU_VCE;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_R4600:
-		mips_cpu.cputype = CPU_R4600;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 48;
-		break;
+				mips_cpu.cputype = CPU_R3000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_I;
+			mips_cpu.options = MIPS_CPU_TLB;
+			mips_cpu.tlbsize = 64;
+			break;
+		case PRID_IMP_R4000:
+			if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
+				mips_cpu.cputype = CPU_R4400SC;
+			else
+				mips_cpu.cputype = CPU_R4000SC;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+				           MIPS_CPU_WATCH | MIPS_CPU_VCE;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R4600:
+			mips_cpu.cputype = CPU_R4600;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+			mips_cpu.tlbsize = 48;
+			break;
 /*
  * This processor doesn't have an MMU, so it's not "real easy" to
  * run Linux on it. It is left purely for documentation.
- *
-	case PRID_IMP_R4650:
-		mips_cpu.cputype = CPU_R4650;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 48;
-		break;
- */
-	case PRID_IMP_R3912:
-		mips_cpu.cputype = CPU_R3912;
-		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
-		mips_cpu.tlbsize = 32;
-		break;
-	case PRID_IMP_R4700:
-		mips_cpu.cputype = CPU_R4700;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_R5000:
-		mips_cpu.cputype = CPU_R5000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_R5432:
-	        mips_cpu.cputype = CPU_R5432;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_NEVADA:
-		mips_cpu.cputype = CPU_NEVADA;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 
-		                   MIPS_CPU_DIVEC;
-		mips_cpu.tlbsize = 48;
-		mips_cpu.icache.ways = 2;
-		mips_cpu.dcache.ways = 2;
-		break;
-	case PRID_IMP_R6000:
-		mips_cpu.cputype = CPU_R6000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_II;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 32;
-		break;
-	case PRID_IMP_R6000A:
-		mips_cpu.cputype = CPU_R6000A;
-		mips_cpu.isa_level = MIPS_CPU_ISA_II;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 32;
-		break;
-	case PRID_IMP_RM7000:
-		mips_cpu.cputype = CPU_RM7000;
-	        mips_cpu.isa_level = MIPS_CPU_ISA_IV;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		break;
-	case PRID_IMP_R8000:
-		mips_cpu.cputype = CPU_R8000;
-	        mips_cpu.isa_level = MIPS_CPU_ISA_IV;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-		                   MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 384;      /* has wierd TLB: 3-way x 128 */
-		break;
-	case PRID_IMP_R10000:
-		mips_cpu.cputype = CPU_R10000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-		                   MIPS_CPU_FPU | MIPS_CPU_32FPR | 
-		                   MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
-		mips_cpu.tlbsize = 64;
+ *		case PRID_IMP_R4650:
+	 		mips_cpu.cputype = CPU_R4650;
+		 	mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+		        mips_cpu.tlbsize = 48;
+			break;
+*/
+		case PRID_IMP_TX39:
+			mips_cpu.isa_level = MIPS_CPU_ISA_I;
+			mips_cpu.options = MIPS_CPU_TLB;
+
+			switch (mips_cpu.processor_id & 0xff) {
+			case PRID_REV_TX3912:
+				mips_cpu.cputype = CPU_TX3912;
+				mips_cpu.tlbsize = 32;
+				break;
+			case PRID_REV_TX3922:
+				mips_cpu.cputype = CPU_TX3922;
+				mips_cpu.tlbsize = 64;
+				break;
+			case PRID_REV_TX3927:
+				mips_cpu.cputype = CPU_TX3927;
+				mips_cpu.tlbsize = 64;
+				break;
+			default:
+				mips_cpu.cputype = CPU_UNKNOWN;
+				break;
+			}
+			break;
+		case PRID_IMP_R4700:
+			mips_cpu.cputype = CPU_R4700;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R5000:
+			mips_cpu.cputype = CPU_R5000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R5432:
+			mips_cpu.cputype = CPU_R5432;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_NEVADA:
+			mips_cpu.cputype = CPU_NEVADA;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+				           MIPS_CPU_DIVEC;
+			mips_cpu.tlbsize = 48;
+			mips_cpu.icache.ways = 2;
+			mips_cpu.dcache.ways = 2;
+			break;
+		case PRID_IMP_R6000:
+			mips_cpu.cputype = CPU_R6000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_II;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+			mips_cpu.tlbsize = 32;
+			break;
+		case PRID_IMP_R6000A:
+			mips_cpu.cputype = CPU_R6000A;
+			mips_cpu.isa_level = MIPS_CPU_ISA_II;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+			mips_cpu.tlbsize = 32;
+			break;
+		case PRID_IMP_RM7000:
+			mips_cpu.cputype = CPU_RM7000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			break;
+		case PRID_IMP_R8000:
+			mips_cpu.cputype = CPU_R8000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+				           MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 384;      /* has wierd TLB: 3-way x 128 */
+			break;
+		case PRID_IMP_R10000:
+			mips_cpu.cputype = CPU_R10000;
+			mips_cpu.cputype = MIPS_CPU_ISA_IV;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+				           MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
+			mips_cpu.tlbsize = 64;
+			break;
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}
 		break;
 #ifdef CONFIG_CPU_MIPS32
-	case PRID_IMP_4KC:
-		mips_cpu.cputype = CPU_4KC;
-		mips_cpu.isa_level = MIPS_CPU_ISA_M32;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-		                   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
-		                   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
-		config1 = read_mips32_cp0_config1();
-		if (config1 & (1 << 3))
-		        mips_cpu.options |= MIPS_CPU_WATCH;
-		if (config1 & (1 << 2))
-		        mips_cpu.options |= MIPS_CPU_MIPS16;
-		if (config1 & 1)
-		        mips_cpu.options |= MIPS_CPU_FPU;
-		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
-		break;
-	case PRID_IMP_5KC:
-		mips_cpu.cputype = CPU_5KC;
-		mips_cpu.isa_level = MIPS_CPU_ISA_M64;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-		                   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
-		                   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
-		config1 = read_mips32_cp0_config1();
-		if (config1 & (1 << 3))
-		        mips_cpu.options |= MIPS_CPU_WATCH;
-		if (config1 & (1 << 2))
-		        mips_cpu.options |= MIPS_CPU_MIPS16;
-		if (config1 & 1)
-		        mips_cpu.options |= MIPS_CPU_FPU;
-		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+	case PRID_COMP_MIPS:
+		switch (mips_cpu.processor_id & 0xff00) {
+		case PRID_IMP_4KC:
+			mips_cpu.cputype = CPU_4KC;
+			goto cpu_4kc;
+		case PRID_IMP_4KEC:
+			mips_cpu.cputype = CPU_4KEC;
+			goto cpu_4kc;
+		case PRID_IMP_4KSC:
+			mips_cpu.cputype = CPU_4KSC;
+cpu_4kc:
+			/* Why do we set all these options by default, THEN query them?? */
+			mips_cpu.cputype = MIPS_CPU_ISA_M32;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+				           MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+			config1 = read_mips32_cp0_config1();
+			if (config1 & (1 << 3))
+				mips_cpu.options |= MIPS_CPU_WATCH;
+			if (config1 & (1 << 2))
+				mips_cpu.options |= MIPS_CPU_MIPS16;
+			if (config1 & 1)
+				mips_cpu.options |= MIPS_CPU_FPU;
+			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+			break;
+		case PRID_IMP_5KC:
+			mips_cpu.cputype = CPU_5KC;
+			mips_cpu.cputype = MIPS_CPU_ISA_M64;
+			/* See comment above about querying options */
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+				           MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+			config1 = read_mips32_cp0_config1();
+			if (config1 & (1 << 3))
+				mips_cpu.options |= MIPS_CPU_WATCH;
+			if (config1 & (1 << 2))
+				mips_cpu.options |= MIPS_CPU_MIPS16;
+			if (config1 & 1)
+				mips_cpu.options |= MIPS_CPU_FPU;
+			break;
+			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}		
 		break;
 #endif
+	case PRID_COMP_ALCHEMY:
+		switch (mips_cpu.processor_id & 0xff00) {
+#ifdef CONFIG_CPU_MIPS32
+		case PRID_IMP_AU1000:
+			mips_cpu.cputype = CPU_AU1000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_M32;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+					   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+					   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+			config1 = read_mips32_cp0_config1();
+			if (config1 & (1 << 3))
+				mips_cpu.options |= MIPS_CPU_WATCH;
+			if (config1 & (1 << 2))
+				mips_cpu.options |= MIPS_CPU_MIPS16;
+			if (config1 & 1)
+				mips_cpu.options |= MIPS_CPU_FPU;
+			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+			break;
+#endif
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}
+		break;
+	case PRID_COMP_SIBYTE:
+		switch (mips_cpu.processor_id & 0xff00) {
+		case PRID_IMP_SB1:
+			mips_cpu.cputype = CPU_SB1;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | MIPS_CPU_FPU |
+		      	           MIPS_CPU_VCE;
+			break;
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}
+		break;
 	default:
 		mips_cpu.cputype = CPU_UNKNOWN;
 	}
@@ -329,9 +396,6 @@
 #ifdef CONFIG_SGI_IP22
 	sgi_sysinit();
 #endif
-#ifdef CONFIG_COBALT_MICRO_SERVER
-	SetUpBootInfo();
-#endif
 
 	/*
 	 * Determine the mmu/cache attached to this machine,
@@ -349,25 +413,116 @@
 	start_kernel();
 }
 
-static void __init default_irq_setup(void)
+void __init add_memory_region(unsigned long start, unsigned long size,
+			      long type)
 {
-	panic("Unknown machtype in init_IRQ");
+	int x = boot_mem_map.nr_map;
+
+	if (x == BOOT_MEM_MAP_MAX) {
+		printk("Ooops! Too many entries in the memory map!\n");
+		return;
+	}
+
+	boot_mem_map.map[x].addr = start;
+	boot_mem_map.map[x].size = size;
+	boot_mem_map.map[x].type = type;
+	boot_mem_map.nr_map++;
+}
+
+static void __init print_memory_map(void)
+{
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		printk(" memory: %08lx @ %08lx ",
+			boot_mem_map.map[i].size, boot_mem_map.map[i].addr);
+		switch (boot_mem_map.map[i].type) {
+		case BOOT_MEM_RAM:
+			printk("(usable)\n");
+			break;
+		case BOOT_MEM_ROM_DATA:
+			printk("(ROM data)\n");
+			break;
+		case BOOT_MEM_RESERVED:
+			printk("(reserved)\n");
+			break;
+		default:
+			printk("type %lu\n", boot_mem_map.map[i].type);
+			break;
+		}
+	}
+}
+
+static inline void parse_mem_cmdline(void)
+{
+	char c = ' ', *to = command_line, *from = saved_command_line;
+	unsigned long start_at, mem_size;
+	int len = 0;
+	int usermem = 0;
+
+	printk("Determined physical RAM map:\n");
+	print_memory_map();
+
+	for (;;) {
+		/*
+		 * "mem=XXX[kKmM]" defines a memory region from
+		 * 0 to <XXX>, overriding the determined size.
+		 * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
+		 * <YYY> to <YYY>+<XXX>, overriding the determined size.
+		 */
+		if (c == ' ' && !memcmp(from, "mem=", 4)) {
+			if (to != command_line)
+				to--;
+			/*
+			 * If a user specifies memory size, we
+			 * blow away any automatically generated
+			 * size.
+			 */
+			if (usermem == 0) {
+				boot_mem_map.nr_map = 0;
+				usermem = 1;
+			}
+			mem_size = memparse(from + 4, &from);
+			if (*from == '@')
+				start_at = memparse(from + 1, &from);
+			else
+				start_at = 0;
+			add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
+		}
+		c = *(from++);
+		if (!c)
+			break;
+		if (COMMAND_LINE_SIZE <= ++len)
+			break;
+		*(to++) = c;
+	}
+	*to = '\0';
+
+	if (usermem) {
+		printk("User-defined physical RAM map:\n");
+		print_memory_map();
+	}
 }
 
 void __init setup_arch(char **cmdline_p)
 {
+	void atlas_setup(void);
 	void baget_setup(void);
-	void cobalt_setup(void);
+	void ddb_setup(void);
 	void decstation_setup(void);
 	void deskstation_setup(void);
 	void jazz_setup(void);
 	void sni_rm200_pci_setup(void);
 	void sgi_setup(void);
-	void ddb_setup(void);
-	void orion_setup(void);
+        void ev96100_setup(void);
+	void malta_setup(void);
+	void momenco_ocelot_setup(void);
+	void nino_setup(void);
 
-	/* Save defaults for configuration-dependent routines.  */
-	irq_setup = default_irq_setup;
+	unsigned long bootmap_size;
+	unsigned long start_pfn, max_pfn, first_usable_pfn;
+
+	int i;
 
 #ifdef CONFIG_BLK_DEV_FD
 	fd_ops = &no_fd_ops;
@@ -390,21 +545,31 @@
 		baget_setup();
 		break;
 #endif
-#ifdef CONFIG_COBALT_MICRO_SERVER
-	case MACH_GROUP_COBALT:
-		cobalt_setup();
-		break;
-#endif
 #ifdef CONFIG_DECSTATION
 	case MACH_GROUP_DEC:
 		decstation_setup();
 		break;
 #endif
+#ifdef CONFIG_MIPS_ATLAS
+	case MACH_GROUP_UNKNOWN:
+		atlas_setup();
+		break;
+#endif
 #ifdef CONFIG_MIPS_JAZZ
 	case MACH_GROUP_JAZZ:
 		jazz_setup();
 		break;
 #endif
+#ifdef CONFIG_MIPS_MALTA
+	case MACH_GROUP_UNKNOWN:
+		malta_setup();
+		break;
+#endif
+#ifdef CONFIG_MOMENCO_OCELOT
+	case MACH_GROUP_MOMENCO:
+		momenco_ocelot_setup();
+		break;
+#endif
 #ifdef CONFIG_SGI_IP22
 	/* As of now this is only IP22.  */
 	case MACH_GROUP_SGI:
@@ -421,42 +586,193 @@
 		ddb_setup();
 		break;
 #endif
-#ifdef CONFIG_ORION
-	case MACH_GROUP_ORION:
-		orion_setup();
+#ifdef CONFIG_DDB5476
+       case MACH_GROUP_NEC_DDB:
+               ddb_setup();
+               break;
+#endif
+#ifdef CONFIG_DDB5477
+       case MACH_GROUP_NEC_DDB:
+               ddb_setup();
+               break;
+#endif
+#ifdef CONFIG_MIPS_EV96100
+	case MACH_GROUP_GALILEO:
+		ev96100_setup();
+		break;
+#endif
+#ifdef CONFIG_MIPS_EV64120
+	case MACH_GROUP_GALILEO:
+		ev64120_setup();
+		break;
+#endif
+#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172)
+	case  MACH_GROUP_ITE:
+	case  MACH_GROUP_GLOBESPAN:
+		it8172_setup();
+		break;
+#endif  
+#ifdef CONFIG_NINO
+	case MACH_GROUP_PHILIPS:
+		nino_setup();
+		break;
+#endif
+#ifdef CONFIG_MIPS_PB1000
+	case MACH_GROUP_ALCHEMY:
+		au1000_setup();
 		break;
 #endif
 	default:
 		panic("Unsupported architecture");
 	}
 
-        strncpy (command_line, arcs_cmdline, CL_SIZE);
-	memcpy(saved_command_line, command_line, CL_SIZE);
-	saved_command_line[CL_SIZE-1] = '\0';
-
+	strncpy(command_line, arcs_cmdline, sizeof command_line);
+	command_line[sizeof command_line - 1] = 0;
+	strcpy(saved_command_line, command_line);
 	*cmdline_p = command_line;
 
+	parse_mem_cmdline();
+
+#define PFN_UP(x)	(((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
+
+	/*
+	 * Partially used pages are not usable - thus
+	 * we are rounding upwards.
+	 */
+	start_pfn = PFN_UP(__pa(&_end));
+
+	/* Find the highest page frame number we have available.  */
+	max_pfn = 0;
+	first_usable_pfn = -1UL;
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		unsigned long start, end;
+
+		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+			continue;
+
+		start = PFN_UP(boot_mem_map.map[i].addr);
+		end = PFN_DOWN(boot_mem_map.map[i].addr
+		      + boot_mem_map.map[i].size);
+
+		if (start >= end)
+			continue;
+		if (end > max_pfn)
+			max_pfn = end;
+		if (start < first_usable_pfn) {
+			if (start > start_pfn) {
+				first_usable_pfn = start;
+			} else if (end > start_pfn) {
+				first_usable_pfn = start_pfn;
+			}
+		}
+	}
+	
+	/* Initialize the boot-time allocator.  */
+	bootmap_size = init_bootmem(first_usable_pfn, max_pfn);
+
+	/*
+	 * Register fully available low RAM pages with the bootmem allocator.
+	 */
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		unsigned long curr_pfn, last_pfn, size;
+
+		/*
+		 * Reserve usable memory.
+		 */
+		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+			continue;
+
+		/*
+		 * We are rounding up the start address of usable memory:
+		 */
+		curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
+		if (curr_pfn >= max_pfn)
+			continue;
+		if (curr_pfn < start_pfn)
+			curr_pfn = start_pfn;
+
+		/*
+		 * ... and at the end of the usable range downwards:
+		 */
+		last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
+				    + boot_mem_map.map[i].size);
+
+		if (last_pfn > max_pfn)
+			last_pfn = max_pfn;
+
+		/*
+		 * ... finally, did all the rounding and playing
+		 * around just make the area go away?
+		 */
+		if (last_pfn <= curr_pfn)
+			continue;
+
+		size = last_pfn - curr_pfn;
+		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+	}
+
+	/* Reserve the bootmap memory.  */
+	reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
+
 #ifdef CONFIG_BLK_DEV_INITRD
-#error "Fixme, I'm broken."
-	tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
-	if (tmp < (unsigned long)&_end)
-		tmp += PAGE_SIZE;
-	initrd_header = (unsigned long *)tmp;
-	if (initrd_header[0] == 0x494E5244) {
-		initrd_start = (unsigned long)&initrd_header[2];
-		initrd_end = initrd_start + initrd_header[1];
-		initrd_below_start_ok = 1;
-		if (initrd_end > memory_end) {
+	/* Board specific code should have set up initrd_start and initrd_end */
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	initrd_start = (unsigned long)&__rd_start;
+	initrd_end = (unsigned long)&__rd_end;
+	initrd_below_start_ok = 1;
+	if (initrd_start) {
+		unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); 
+		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%08lx)\ndisabling initrd\n",
-			       initrd_end,memory_end);
-			initrd_start = 0;
-		} else
-			*memory_start_p = initrd_end;
+			       "(0x%lx > 0x%p)\ndisabling initrd\n",
+			       initrd_end,
+			       phys_to_virt(PFN_PHYS(max_low_pfn)));
+			initrd_start = initrd_end = 0;
+		} 
 	}
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD  */
 
 	paging_init();
+
+	code_resource.start = virt_to_bus(&_ftext);
+	code_resource.end = virt_to_bus(&_etext) - 1;
+	data_resource.start = virt_to_bus(&_fdata);
+	data_resource.end = virt_to_bus(&_edata) - 1;
+
+	/*
+	 * Request address space for all standard RAM.
+	 */
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		struct resource *res;
+
+		res = alloc_bootmem(sizeof(struct resource));
+		switch (boot_mem_map.map[i].type) {
+		case BOOT_MEM_RAM:
+		case BOOT_MEM_ROM_DATA:
+			res->name = "System RAM";
+			break;
+		case BOOT_MEM_RESERVED:
+		default:
+			res->name = "reserved";
+		}
+		res->start = boot_mem_map.map[i].addr;
+		res->end = res->start + boot_mem_map.map[i].size - 1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+		request_resource(&iomem_resource, res);
+
+		/*
+		 *  We dont't know which RAM region contains kernel data,
+		 *  so we try it repeatedly and let the resource manager
+		 *  test it.
+		 */
+		request_resource(res, &code_resource);
+		request_resource(res, &data_resource);
+	}
 }
 
 void r3081_wait(void) 
diff -urN linux-2.4.6-pre8/arch/mips/kernel/smp.c linux/arch/mips/kernel/smp.c
--- linux-2.4.6-pre8/arch/mips/kernel/smp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/smp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,402 @@
+/*
+ *
+ *  arch/mips/kernel/smp.c
+ *
+ *  Copyright (C) 2000 Sibyte
+ * 
+ *  Written by Justin Carlson (carlson@sibyte.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This 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/config.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <asm/mmu_context.h>
+#include <asm/delay.h>
+#include <asm/smp.h>
+
+/*
+ * This was written with the BRCM12500 MP SOC in mind, but tries to
+ * be generic.  It's modelled on the mips64 smp.c code, which is
+ * derived from Sparc, I'm guessing, which is derived from...
+ * 
+ * It's probably horribly designed for very large ccNUMA systems
+ * as it doesn't take any node clustering into account.  
+*/
+
+
+/* Ze Big Kernel Lock! */
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+int smp_threads_ready;  /* Not used */
+int smp_num_cpus;    
+int global_irq_holder = NO_PROC_ID;
+spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
+struct mips_cpuinfo cpu_data[NR_CPUS];
+
+struct smp_fn_call_struct smp_fn_call = 
+{ SPIN_LOCK_UNLOCKED, ATOMIC_INIT(0), NULL, NULL};
+
+static atomic_t cpus_booted = ATOMIC_INIT(0);
+
+
+/* These are defined by the board-specific code. */
+
+/* Cause the function described by smp_fn_call 
+   to be executed on the passed cpu.  When the function
+   has finished, increment the finished field of
+   smp_fn_call. */
+
+void core_call_function(int cpu);
+
+/*
+ * Clear all undefined state in the cpu, set up sp and gp to the passed
+ * values, and kick the cpu into smp_bootstrap(); 
+ */
+void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp);
+
+/*
+ *  After we've done initial boot, this function is called to allow the
+ *  board code to clean up state, if needed 
+ */
+
+void prom_init_secondary(void);
+
+
+void cpu_idle(void);
+
+/* Do whatever setup needs to be done for SMP at the board level.  Return
+   the number of cpus in the system, including this one */
+int prom_setup_smp(void);
+
+int start_secondary(void *unused)
+{
+	prom_init_secondary();
+	write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
+	current_pgd[smp_processor_id()] = init_mm.pgd;
+	printk("Slave cpu booted successfully\n");
+	atomic_inc(&cpus_booted);
+	cpu_idle();
+	return 0;
+}
+
+void __init smp_boot_cpus(void)
+{
+	int i;
+
+	smp_num_cpus = prom_setup_smp();
+	init_new_context(current, &init_mm);
+	current->processor = 0;
+	atomic_set(&cpus_booted, 1);  /* Master CPU is already booted... */
+	init_idle();
+	for (i = 1; i < smp_num_cpus; i++) {
+		struct task_struct *p;
+		struct pt_regs regs;
+		printk("Starting CPU %d... ", i);
+
+		/* Spawn a new process normally.  Grab a pointer to
+		   its task struct so we can mess with it */
+		do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+		p = init_task.prev_task;
+
+		/* Schedule the first task manually */
+		p->processor = i;
+		p->has_cpu = 1;
+
+		/* Attach to the address space of init_task. */
+		atomic_inc(&init_mm.mm_count);
+		p->active_mm = &init_mm;
+		init_tasks[i] = p;
+
+		del_from_runqueue(p);
+		unhash_process(p);
+
+		prom_boot_secondary(i,
+				    (unsigned long)p + KERNEL_STACK_SIZE - 32,
+				    (unsigned long)p);
+
+#if 0
+
+		/* This is copied from the ip-27 code in the mips64 tree */
+
+		struct task_struct *p;
+
+		/*
+		 * The following code is purely to make sure
+		 * Linux can schedule processes on this slave.
+		 */
+		kernel_thread(0, NULL, CLONE_PID);
+		p = init_task.prev_task;
+		sprintf(p->comm, "%s%d", "Idle", i);
+		init_tasks[i] = p;
+		p->processor = i;
+		p->has_cpu = 1; /* we schedule the first task manually */
+		del_from_runqueue(p);
+		unhash_process(p);
+		/* Attach to the address space of init_task. */
+		atomic_inc(&init_mm.mm_count);
+		p->active_mm = &init_mm;
+		prom_boot_secondary(i, 
+				    (unsigned long)p + KERNEL_STACK_SIZE - 32,
+				    (unsigned long)p);
+#endif
+	}
+
+	/* Wait for everyone to come up */
+	while (atomic_read(&cpus_booted) != smp_num_cpus);
+}
+
+void __init smp_commence(void)
+{
+	/* Not sure what to do here yet */
+}
+
+static void reschedule_this_cpu(void *dummy)
+{
+	current->need_resched = 1;
+}
+
+void FASTCALL(smp_send_reschedule(int cpu))
+{
+	smp_call_function(reschedule_this_cpu, NULL, 0, 0);
+}
+
+
+/*
+ * The caller of this wants the passed function to run on every cpu.  If wait
+ * is set, wait until all cpus have finished the function before returning.
+ * The lock is here to protect the call structure.
+ */
+int smp_call_function (void (*func) (void *info), void *info, int retry, 
+								int wait)
+{
+	int cpus = smp_num_cpus - 1;
+	int i;
+
+	if (smp_num_cpus < 2) {
+		return 0;
+	}
+
+	spin_lock_bh(&smp_fn_call.lock);
+
+	atomic_set(&smp_fn_call.finished, 0);
+	smp_fn_call.fn = func;
+	smp_fn_call.data = info;
+
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (i != smp_processor_id()) {
+			/* Call the board specific routine */
+			core_call_function(i);
+		}
+	}
+
+	if (wait) {
+		while(atomic_read(&smp_fn_call.finished) != cpus) {}
+	}
+
+	spin_unlock_bh(&smp_fn_call.lock);
+	return 0;
+}
+
+void synchronize_irq(void)
+{
+	panic("synchronize_irq");
+}
+
+static void stop_this_cpu(void *dummy)
+{
+	printk("Cpu stopping\n");
+	for (;;);
+}
+
+void smp_send_stop(void)
+{
+	smp_call_function(stop_this_cpu, NULL, 1, 0);
+	smp_num_cpus = 1;
+}
+
+/* Not really SMP stuff ... */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return 0;
+}
+
+
+/*
+ * Most of this code is take from the mips64 tree (ip27-irq.c).  It's virtually
+ * identical to the i386 implentation in arh/i386/irq.c, with translations for
+ * the interrupt enable bit
+ */
+
+#define MAXCOUNT 		100000000
+#define SYNC_OTHER_CORES(x)	udelay(x+1)
+
+static inline void wait_on_irq(int cpu)
+{
+	int count = MAXCOUNT;
+
+	for (;;) {
+
+		/*
+		 * Wait until all interrupts are gone. Wait
+		 * for bottom half handlers unless we're
+		 * already executing in one..
+		 */
+		if (!irqs_running())
+			if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
+				break;
+
+		/* Duh, we have to loop. Release the lock to avoid deadlocks */
+		spin_unlock(&global_irq_lock);
+
+		for (;;) {
+			if (!--count) {
+				printk("Count spun out.  Huh?\n");
+				count = ~0;
+			}
+			__sti();
+			SYNC_OTHER_CORES(cpu);
+			__cli();
+			if (irqs_running())
+				continue;
+			if (spin_is_locked(&global_irq_lock))
+				continue;
+			if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
+				continue;
+			if (spin_trylock(&global_irq_lock))
+				break;
+		}
+	}
+}
+
+
+static inline void get_irqlock(int cpu)
+{
+	if (!spin_trylock(&global_irq_lock)) {
+		/* do we already hold the lock? */
+		if ((unsigned char) cpu == global_irq_holder)
+			return;
+		/* Uhhuh.. Somebody else got it. Wait.. */
+		spin_lock(&global_irq_lock);
+	}
+	/*
+	 * We also to make sure that nobody else is running
+	 * in an interrupt context.
+	 */
+	wait_on_irq(cpu);
+
+	/*
+	 * Ok, finally..
+	 */
+	global_irq_holder = cpu;
+}
+
+
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
+void __global_cli(void)
+{
+	unsigned int flags;
+
+	__save_flags(flags);
+	if (flags & ST0_IE) {
+		int cpu = smp_processor_id();
+		__cli();
+		if (!local_irq_count(cpu))
+			get_irqlock(cpu);
+	}
+}
+
+void __global_sti(void)
+{
+	int cpu = smp_processor_id();
+
+	if (!local_irq_count(cpu))
+		release_irqlock(cpu);
+	__sti();
+}
+
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
+unsigned long __global_save_flags(void)
+{
+	int retval;
+	int local_enabled;
+	unsigned long flags;
+	int cpu = smp_processor_id();
+
+	__save_flags(flags);
+	local_enabled = (flags & ST0_IE);
+	/* default to local */
+	retval = 2 + local_enabled;
+
+	/* check for global flags if we're not in an interrupt */
+	if (!local_irq_count(cpu)) {
+		if (local_enabled)
+			retval = 1;
+		if (global_irq_holder == cpu)
+			retval = 0;
+	}
+
+	return retval;
+}
+
+void __global_restore_flags(unsigned long flags)
+{
+	switch (flags) {
+		case 0:
+			__global_cli();
+			break;
+		case 1:
+			__global_sti();
+			break;
+		case 2:
+			__cli();
+			break;
+		case 3:
+			__sti();
+			break;
+		default:
+			printk("global_restore_flags: %08lx\n", flags);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- linux-2.4.6-pre8/arch/mips/kernel/syscall.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/mips/kernel/syscall.c	Mon Dec  3 22:50:37 2001
@@ -92,22 +92,23 @@
 	return do_mmap2(addr, len, prot, flags, fd, pgoff);
 }
 
-asmlinkage int sys_fork(struct pt_regs regs)
+save_static_function(sys_fork);
+static_unused int _sys_fork(struct pt_regs regs)
 {
 	int res;
 
-	save_static(&regs);
 	res = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
 	return res;
 }
 
-asmlinkage int sys_clone(struct pt_regs regs)
+
+save_static_function(sys_clone);
+static_unused int _sys_clone(struct pt_regs regs)
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
 	int res;
 
-	save_static(&regs);
 	clone_flags = regs.regs[4];
 	newsp = regs.regs[5];
 	if (!newsp)
diff -urN linux-2.4.6-pre8/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- linux-2.4.6-pre8/arch/mips/kernel/syscalls.h	Fri Aug 11 14:29:04 2000
+++ linux/arch/mips/kernel/syscalls.h	Mon Dec  3 22:50:37 2001
@@ -1,10 +1,9 @@
-/* $Id: syscalls.h,v 1.22 2000/02/18 00:24:30 ralf Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle
  */
 
 /*
@@ -228,10 +227,11 @@
 SYS(sys_mmap2, 6)				/* 4210 */
 SYS(sys_truncate64, 2)
 SYS(sys_ftruncate64, 2)
-SYS(sys_stat64, 3)
-SYS(sys_lstat64, 3)
-SYS(sys_fstat64, 3)				/* 4215 */
+SYS(sys_stat64, 2)
+SYS(sys_lstat64, 2)
+SYS(sys_fstat64, 2)				/* 4215 */
 SYS(sys_pivot_root, 2)
 SYS(sys_mincore, 3)
 SYS(sys_madvise, 3)
 SYS(sys_getdents64, 3)
+SYS(sys_fcntl64, 3)				/* 4220 */
diff -urN linux-2.4.6-pre8/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- linux-2.4.6-pre8/arch/mips/kernel/sysirix.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/mips/kernel/sysirix.c	Mon Dec  3 22:50:37 2001
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller
  * Copyright (C) 1997 Miguel de Icaza
- * Copyright (C) 1997, 1998 Ralf Baechle
+ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -27,7 +27,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
-#include <asm/sgialib.h>
 #include <asm/inventory.h>
 
 /* 2,191 lines of complete and utter shit coming up... */
@@ -1249,9 +1248,9 @@
 
 	ks.st_blksize = (s32) sb->st_blksize;
 	ks.st_blocks = (long long) sb->st_blocks;
-	memcpy(&ks.st_fstype[0], &sb->st_fstype[0], 16);
-	ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] =
-		ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
+	memset(ks.st_fstype, 0, 16);
+	ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = 0;
+	ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
 
 	/* Now write it all back. */
 	copy_to_user(sb, &ks, sizeof(struct xstat64));
diff -urN linux-2.4.6-pre8/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
--- linux-2.4.6-pre8/arch/mips/kernel/sysmips.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/kernel/sysmips.c	Mon Dec  3 22:50:37 2001
@@ -7,6 +7,7 @@
  *
  * Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/mm.h>
@@ -21,6 +22,8 @@
 #include <asm/sysmips.h>
 #include <asm/uaccess.h>
 
+extern asmlinkage void syscall_trace(void);
+
 /*
  * How long a hostname can we get from user space?
  *  -EFAULT if invalid area or too long
@@ -49,7 +52,7 @@
 {
 	int	*p;
 	char	*name;
-	int	flags, tmp, len, retval, errno;
+	int	tmp, len, retval, errno;
 
 	switch(cmd) {
 	case SETNAME: {
@@ -72,8 +75,7 @@
 	}
 
 	case MIPS_ATOMIC_SET: {
-		/* This is broken in case of page faults and SMP ...
-		    Risc/OS faults after maximum 20 tries with EAGAIN.  */
+#ifdef CONFIG_CPU_HAS_LLSC
 		unsigned int tmp;
 
 		p = (int *) arg1;
@@ -81,16 +83,46 @@
 		if (errno)
 			return errno;
 		errno = 0;
-		save_and_cli(flags);
-		errno |= __get_user(tmp, p);
-		errno |= __put_user(arg2, p);
-		restore_flags(flags);
+
+		__asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t"
+			".set\tmips2\n\t"
+			".set\tnoat\n\t"
+			"1:\tll\t%0, %4\n\t"
+			"move\t$1, %3\n\t"
+			"2:\tsc\t$1, %1\n\t"
+			"beqz\t$1, 1b\n\t"
+			".set\tpop\n\t"
+			".section\t.fixup,\"ax\"\n"
+			"3:\tli\t%2, 1\t\t\t# error\n\t"
+			".previous\n\t"
+			".section\t__ex_table,\"a\"\n\t"
+			".word\t1b, 3b\n\t"
+			".word\t2b, 3b\n\t"
+			".previous\n\t"
+			: "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno)
+			: "r" (arg2), "o" (* (u32 *) p), "2" (errno)
+			: "$1");
 
 		if (errno)
-			return tmp;
+			return -EFAULT;
 
-		return tmp;             /* This is broken ...  */ 
-        }
+		/* We're skipping error handling etc.  */
+		if (current->ptrace & PT_TRACESYS)
+			syscall_trace();
+
+		((struct pt_regs *)&cmd)->regs[2] = tmp;
+		((struct pt_regs *)&cmd)->regs[7] = 0;
+
+		__asm__ __volatile__(
+			"move\t$29, %0\n\t"
+			"j\to32_ret_from_sys_call"
+			: /* No outputs */
+			: "r" (&cmd));
+		/* Unreached */
+#else
+	printk("sys_sysmips(MIPS_ATOMIC_SET, ...) not ready for !CONFIG_CPU_HAS_LLSC\n");
+#endif
+	}
 
 	case MIPS_FIXADE:
 		tmp = current->thread.mflags & ~3;
diff -urN linux-2.4.6-pre8/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- linux-2.4.6-pre8/arch/mips/kernel/time.c	Mon Oct 16 12:58:51 2000
+++ linux/arch/mips/kernel/time.c	Mon Dec  3 22:50:37 2001
@@ -1,551 +1,542 @@
-/*
- * Copyright (C) 1991, 1992, 1995  Linus Torvalds
- * Copyright (C) 1996 - 2000  Ralf Baechle
+/***********************************************************************
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/kernel/time.c
+ *     Common time service routines for MIPS machines.  See 
+ *     Documents/MIPS/time.txt. 
  *
- * This file contains the time handling details for PC-style clocks as
- * found in some MIPS systems.
+ * 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 <linux/errno.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/kernel.h>
 #include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/smp.h>
 #include <linux/kernel_stat.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/ddb5074.h>
-
-#include <linux/mc146818rtc.h>
-#include <linux/timex.h>
-
-extern volatile unsigned long wall_jiffies;
-unsigned long r4k_interval;
-extern rwlock_t xtime_lock;
-
-/*
- * Change this if you have some constant time drift
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/hardirq.h>
+
+/* 
+ * macro for catching spurious errors.  Eable to LL_DEBUG in kernel hacking
+ * config menu.
  */
-/* This is the value for the PC-style PICs. */
-/* #define USECS_PER_JIFFY (1000020/HZ) */
+#ifdef CONFIG_LL_DEBUG
+#define	MIPS_ASSERT(x)	if (!(x)) { panic("MIPS_ASSERT failed at %s:%d\n", __FILE__, __LINE__); }
+#define MIPS_DEBUG(x)  do { x; } while (0)
+#else
+#define MIPS_ASSERT(x)
+#define MIPS_DEBUG(x)
+#endif
 
 /* This is for machines which generate the exact clock. */
 #define USECS_PER_JIFFY (1000000/HZ)
+#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff)
 
-/* Cycle counter value at the previous timer interrupt.. */
-
-static unsigned int timerhi, timerlo;
+/*
+ * forward reference
+ */
+extern rwlock_t xtime_lock;
+extern volatile unsigned long wall_jiffies;
 
 /*
- * On MIPS only R4000 and better have a cycle counter.
- *
- * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ * By default we provide the null RTC ops
  */
-static unsigned long do_fast_gettimeoffset(void)
+static unsigned long null_rtc_get_time(void)
 {
-	u32 count;
-	unsigned long res, tmp;
-
-	/* Last jiffy when do_fast_gettimeoffset() was called. */
-	static unsigned long last_jiffies;
-	unsigned long quotient;
+	return mktime(2000, 1, 1, 0, 0, 0);
+}
 
-	/*
-	 * Cached "1/(clocks per usec)*2^32" value.
-	 * It has to be recalculated once each jiffy.
-	 */
-	static unsigned long cached_quotient;
+static int null_rtc_set_time(unsigned long sec)
+{
+	return 0;
+}
 
-	tmp = jiffies;
+unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
 
-	quotient = cached_quotient;
 
-	if (tmp && last_jiffies != tmp) {
-		last_jiffies = tmp;
-		__asm__(".set\tnoreorder\n\t"
-			".set\tnoat\n\t"
-			".set\tmips3\n\t"
-			"lwu\t%0,%2\n\t"
-			"dsll32\t$1,%1,0\n\t"
-			"or\t$1,$1,%0\n\t"
-			"ddivu\t$0,$1,%3\n\t"
-			"mflo\t$1\n\t"
-			"dsll32\t%0,%4,0\n\t"
-			"nop\n\t"
-			"ddivu\t$0,%0,$1\n\t"
-			"mflo\t%0\n\t"
-			".set\tmips0\n\t"
-			".set\tat\n\t"
-			".set\treorder"
-			:"=&r" (quotient)
-			:"r" (timerhi),
-			 "m" (timerlo),
-			 "r" (tmp),
-			 "r" (USECS_PER_JIFFY)
-			:"$1");
-		cached_quotient = quotient;
-	}
+/*
+ * timeofday services, for syscalls.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+        unsigned long flags;
 
-	/* Get last timer tick in absolute kernel time */
-	count = read_32bit_cp0_register(CP0_COUNT);
+        read_lock_irqsave (&xtime_lock, flags);
+        *tv = xtime;
+        tv->tv_usec += do_gettimeoffset();
+
+        /*
+         * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+         * is nonzero if the timer bottom half hasnt executed yet.
+         */
+        if (jiffies - wall_jiffies)
+                tv->tv_usec += USECS_PER_JIFFY;
+
+        read_unlock_irqrestore (&xtime_lock, flags);
+
+        if (tv->tv_usec >= 1000000) {
+                tv->tv_usec -= 1000000;
+                tv->tv_sec++;
+        }
+}
 
-	/* .. relative to previous jiffy (32 bits is enough) */
-	count -= timerlo;
-//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo);
-
-	__asm__("multu\t%1,%2\n\t"
-		"mfhi\t%0"
-		:"=r" (res)
-		:"r" (count),
-		 "r" (quotient));
+void do_settimeofday(struct timeval *tv)
+{
+        write_lock_irq (&xtime_lock);
 
-	/*
- 	 * Due to possible jiffies inconsistencies, we need to check 
-	 * the result so that we'll get a timer that is monotonic.
-	 */
-	if (res >= USECS_PER_JIFFY)
-		res = USECS_PER_JIFFY-1;
+        /* This is revolting. We need to set the xtime.tv_usec
+         * correctly. However, the value in this location is
+         * is value at the last tick.
+         * Discover what correction gettimeofday
+         * would have done, and then undo it!
+         */
+        tv->tv_usec -= do_gettimeoffset();
+
+        if (tv->tv_usec < 0) {
+                tv->tv_usec += 1000000;
+                tv->tv_sec--;
+        }
+        xtime = *tv;
+        time_adjust = 0;                /* stop active adjtime() */
+        time_status |= STA_UNSYNC;
+        time_maxerror = NTP_PHASE_LIMIT;
+        time_esterror = NTP_PHASE_LIMIT;
 
-	return res;
+        write_unlock_irq (&xtime_lock);
 }
 
-/* This function must be called with interrupts disabled 
- * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
- * 
- * However, the pc-audio speaker driver changes the divisor so that
- * it gets interrupted rather more often - it loads 64 into the
- * counter rather than 11932! This has an adverse impact on
- * do_gettimeoffset() -- it stops working! What is also not
- * good is that the interval that our timer function gets called
- * is no longer 10.0002 ms, but 9.9767 ms. To get around this
- * would require using a different timing source. Maybe someone
- * could use the RTC - I know that this can interrupt at frequencies
- * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
- * it so that at startup, the timer code in sched.c would select
- * using either the RTC or the 8253 timer. The decision would be
- * based on whether there was any other device around that needed
- * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
- * and then do some jiggery to have a version of do_timer that 
- * advanced the clock by 1/1024 s. Every time that reached over 1/100
- * of a second, then do all the old code. If the time was kept correct
- * then do_gettimeoffset could just return 0 - there is no low order
- * divider that can be accessed.
+
+/*
+ * Gettimeoffset routines.  These routines returns the time duration
+ * since last timer interrupt in usecs.
  *
- * Ideally, you would be able to use the RTC for the speaker driver,
- * but it appears that the speaker driver really needs interrupt more
- * often than every 120 us or so.
+ * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset.
+ * Otherwise use calibrate_gettimeoffset()
  *
- * Anyway, this needs more thought....		pjsg (1993-08-28)
- * 
- * If you are really that interested, you should be reading
- * comp.protocols.time.ntp!
+ * If the CPU does not have counter register all, you can either supply
+ * your own gettimeoffset() routine, or use null_gettimeoffset() routines,
+ * which gives the same resolution as HZ.
  */
 
-#define TICK_SIZE tick
 
-static unsigned long do_slow_gettimeoffset(void)
-{
-	int count;
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
 
-	static int count_p = LATCH;    /* for the first call after boot */
-	static unsigned long jiffies_p;
+/* usecs per counter cycle, shifted to left by 32 bits */
+static unsigned int sll32_usecs_per_cycle=0;
 
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off. 
-	 */
-	unsigned long jiffies_t;
+/* how many counter cycles in a jiffy */
+static unsigned long cycles_per_jiffy=0;
+
+/* Cycle counter value at the previous timer interrupt.. */
+static unsigned int timerhi, timerlo;
 
-	/* timer count may underflow right here */
-	outb_p(0x00, 0x43);	/* latch the count ASAP */
+/* last time when xtime and rtc are sync'ed up */
+static long last_rtc_update;
 
-	count = inb_p(0x40);	/* read the latched count */
+/* the function pointer to one of the gettimeoffset funcs*/
+unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset;
 
-	/*
-	 * We do this guaranteed double memory access instead of a _p 
-	 * postfix in the previous port access. Wheee, hackady hack
-	 */
-	jiffies_t = jiffies;
+unsigned long null_gettimeoffset(void)
+{
+	return 0;
+}
 
-	count |= inb_p(0x40) << 8;
+unsigned long fixed_rate_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res;
 
-	/*
-	 * avoiding timer inconsistencies (they are rare, but they happen)...
-	 * there are two kinds of problems that must be avoided here:
-	 *  1. the timer counter underflows
-	 *  2. hardware problem with the timer, not giving us continuous time,
-	 *     the counter does small "jumps" upwards on some Pentium systems,
-	 *     (see c't 95/10 page 335 for Neptun bug.)
-	 */
+	MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER);
+	MIPS_ASSERT(mips_counter_frequency != 0);
+	MIPS_ASSERT(sll32_usecs_per_cycle != 0);
 
-	if( jiffies_t == jiffies_p ) {
-		if( count > count_p ) {
-			/* the nutcase */
-
-			outb_p(0x0A, 0x20);
-
-			/* assumption about timer being IRQ1 */
-			if (inb(0x20) & 0x01) {
-				/*
-				 * We cannot detect lost timer interrupts ... 
-				 * well, that's why we call them lost, don't we? :)
-				 * [hmm, on the Pentium and Alpha we can ... sort of]
-				 */
-				count -= LATCH;
-			} else {
-				printk("do_slow_gettimeoffset(): hardware timer problem?\n");
-			}
-		}
-	} else
-		jiffies_p = jiffies_t;
+	/* Get last timer tick in absolute kernel time */
+        count = read_32bit_cp0_register(CP0_COUNT);
 
-	count_p = count;
+        /* .. relative to previous jiffy (32 bits is enough) */
+        count -= timerlo;
 
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	count = (count + LATCH/2) / LATCH;
+        __asm__("multu\t%1,%2\n\t"
+                "mfhi\t%0"
+                :"=r" (res)
+                :"r" (count),
+                 "r" (sll32_usecs_per_cycle));
+
+        /*
+         * Due to possible jiffies inconsistencies, we need to check
+         * the result so that we'll get a timer that is monotonic.
+         */
+        if (res >= USECS_PER_JIFFY)
+                res = USECS_PER_JIFFY-1;
 
-	return count;
+        return res;
 }
 
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-
 /*
- * This version of gettimeofday has near microsecond resolution.
+ * Cached "1/(clocks per usec)*2^32" value.
+ * It has to be recalculated once each jiffy.
  */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long flags;
+static unsigned long cached_quotient;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_gettimeoffset();
+/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */
+static unsigned long last_jiffies = 0;
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+/* 
+ * copied from include/asm/div64.  
+ * We do the copy instead of include the header file because we don't
+ * want to reply on _MIPS_ISA value.
+ */
+#define do_div64_32(res, high, low, base) ({ \
+        unsigned long __quot, __mod; \
+        unsigned long __cf, __tmp, __i; \
+        \
+        __asm__(".set   push\n\t" \
+                ".set   noat\n\t" \
+                ".set   noreorder\n\t" \
+                "b      1f\n\t" \
+                " li    %4,0x21\n" \
+                "0:\n\t" \
+                "sll    $1,%0,0x1\n\t" \
+                "srl    %3,%0,0x1f\n\t" \
+                "or     %0,$1,$2\n\t" \
+                "sll    %1,%1,0x1\n\t" \
+                "sll    %2,%2,0x1\n" \
+                "1:\n\t" \
+                "bnez   %3,2f\n\t" \
+                "sltu   $2,%0,%z5\n\t" \
+                "bnez   $2,3f\n\t" \
+                "2:\n\t" \
+                " addiu %4,%4,-1\n\t" \
+                "subu   %0,%0,%z5\n\t" \
+                "addiu  %2,%2,1\n" \
+                "3:\n\t" \
+                "bnez   %4,0b\n\t" \
+                " srl   $2,%1,0x1f\n\t" \
+                ".set   pop" \
+                : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+                  "=&r" (__i) \
+                : "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \
+                /* Aarrgh!  Ran out of gcc's limit on constraints... */ \
+                : "$1", "$2"); \
+        \
+        (res) = __quot; \
+        __mod; })
 
-	read_unlock_irqrestore (&xtime_lock, flags);
+/*
+ * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Mercij.
+ */
+unsigned long calibrate_div32_gettimeoffset(void)
+{
+        u32 count;
+        unsigned long res, tmp;
+        unsigned long quotient;
+
+	MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER);
+
+        tmp = jiffies;
+
+        quotient = cached_quotient;
+
+        if (last_jiffies != tmp) {
+                last_jiffies = tmp;
+                if (last_jiffies != 0) {
+                        unsigned long r0;
+                        do_div64_32(r0, timerhi, timerlo, tmp);
+                        do_div64_32(quotient, USECS_PER_JIFFY,
+                                    USECS_PER_JIFFY_FRAC, r0);
+                        cached_quotient = quotient;
+                }
+        }
+
+        /* Get last timer tick in absolute kernel time */
+        count = read_32bit_cp0_register(CP0_COUNT);
+
+        /* .. relative to previous jiffy (32 bits is enough) */
+        count -= timerlo;
+
+        __asm__("multu  %2,%3"
+                : "=l" (tmp), "=h" (res)
+                : "r" (count), "r" (quotient));
+
+        /*
+         * Due to possible jiffies inconsistencies, we need to check
+         * the result so that we'll get a timer that is monotonic.
+         */
+        if (res >= USECS_PER_JIFFY)
+                res = USECS_PER_JIFFY - 1;
 
-	if (tv->tv_usec >= 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
-	}
+        return res;
 }
 
-void do_settimeofday(struct timeval *tv)
+unsigned long calibrate_div64_gettimeoffset(void)
 {
-	write_lock_irq (&xtime_lock);
-	/* This is revolting. We need to set the xtime.tv_usec
-	 * correctly. However, the value in this location is
-	 * is value at the last tick.
-	 * Discover what correction gettimeofday
-	 * would have done, and then undo it!
-	 */
-	tv->tv_usec -= do_gettimeoffset();
-
-	if (tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
-		tv->tv_sec--;
-	}
+        u32 count;
+        unsigned long res, tmp;
+        unsigned long quotient;
+
+
+	MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER);
+	MIPS_ASSERT((mips_cpu.isa_level != MIPS_CPU_ISA_I) &&
+		    (mips_cpu.isa_level != MIPS_CPU_ISA_II) &&
+		    (mips_cpu.isa_level != MIPS_CPU_ISA_M32));
+
+
+        tmp = jiffies;
+
+        quotient = cached_quotient;
+
+        if (tmp && last_jiffies != tmp) {
+                last_jiffies = tmp;
+                __asm__(".set\tnoreorder\n\t"
+                        ".set\tnoat\n\t"
+                        ".set\tmips3\n\t"
+                        "lwu\t%0,%2\n\t"
+                        "dsll32\t$1,%1,0\n\t"
+                        "or\t$1,$1,%0\n\t"
+                        "ddivu\t$0,$1,%3\n\t"
+                        "mflo\t$1\n\t"
+                        "dsll32\t%0,%4,0\n\t"
+                        "nop\n\t"
+                        "ddivu\t$0,%0,$1\n\t"
+                        "mflo\t%0\n\t"
+                        ".set\tmips0\n\t"
+                        ".set\tat\n\t"
+                        ".set\treorder"
+                        :"=&r" (quotient)
+                        :"r" (timerhi),
+                         "m" (timerlo),
+                         "r" (tmp),
+                         "r" (USECS_PER_JIFFY)
+                        :"$1");
+                cached_quotient = quotient;
+        }
+
+        /* Get last timer tick in absolute kernel time */
+        count = read_32bit_cp0_register(CP0_COUNT);
+
+        /* .. relative to previous jiffy (32 bits is enough) */
+        count -= timerlo;
+
+        __asm__("multu\t%1,%2\n\t"
+                "mfhi\t%0"
+                :"=r" (res)
+                :"r" (count),
+                 "r" (quotient));
+
+        /*
+         * Due to possible jiffies inconsistencies, we need to check
+         * the result so that we'll get a timer that is monotonic.
+         */
+        if (res >= USECS_PER_JIFFY)
+                res = USECS_PER_JIFFY-1;
 
-	xtime = *tv;
-	time_adjust = 0;		/* stop active adjtime() */
-	time_status |= STA_UNSYNC;
-	time_maxerror = NTP_PHASE_LIMIT;
-	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq (&xtime_lock);
+        return res;
 }
 
+
 /*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- *      sets the minutes. Usually you won't notice until after reboot!
+ * high-level timer interrupt service routines.  This function
+ * is set as irqaction->handler and is invoked through do_IRQ.
  */
-static int set_rtc_mmss(unsigned long nowtime)
+void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	int retval = 0;
-	int real_seconds, real_minutes, cmos_minutes;
-	unsigned char save_control, save_freq_select;
-
-	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
-	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+	if (mips_cpu.options & MIPS_CPU_COUNTER) {
+		unsigned int count;
 
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
-	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+		/*
+		 * The cycle counter is only 32 bit which is good for about
+		 * a minute at current count rates of upto 150MHz or so.
+		 */
+		count = read_32bit_cp0_register(CP0_COUNT);
+		timerhi += (count < timerlo);   /* Wrap around */
+		timerlo = count;
 
-	cmos_minutes = CMOS_READ(RTC_MINUTES);
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-		BCD_TO_BIN(cmos_minutes);
+		/*
+		 * set up for next timer interrupt - no harm if the machine
+		 * is using another timer interrupt source.
+		 * Note that writing to COMPARE register clears the interrupt
+		 */
+		write_32bit_cp0_register (CP0_COMPARE,
+					  count + cycles_per_jiffy);
 
-	/*
-	 * since we're only adjusting minutes and seconds,
-	 * don't interfere with hour overflow. This avoids
-	 * messing with unknown time zones but requires your
-	 * RTC not to be off by more than 15 minutes
-	 */
-	real_seconds = nowtime % 60;
-	real_minutes = nowtime / 60;
-	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-		real_minutes += 30;		/* correct for half hour time zone */
-	real_minutes %= 60;
-
-	if (abs(real_minutes - cmos_minutes) < 30) {
-		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-			BIN_TO_BCD(real_seconds);
-			BIN_TO_BCD(real_minutes);
-		}
-		CMOS_WRITE(real_seconds,RTC_SECONDS);
-		CMOS_WRITE(real_minutes,RTC_MINUTES);
-	} else {
-		printk(KERN_WARNING
-		       "set_rtc_mmss: can't update from %d to %d\n",
-		       cmos_minutes, real_minutes);
- 		retval = -1;
 	}
 
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	CMOS_WRITE(save_control, RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-
-	return retval;
-}
-
-/* last time the cmos clock got updated */
-static long last_rtc_update;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static void inline
-timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-#ifdef CONFIG_DDB5074
-	static unsigned cnt, period, dist;
-
-	if (cnt == 0 || cnt == dist)
-	    ddb5074_led_d2(1);
-	else if (cnt == 7 || cnt == dist+7)
-	    ddb5074_led_d2(0);
-	
-	if (++cnt > period) {
-	    cnt = 0;
-	    /* The hyperbolic function below modifies the heartbeat period
-	     * length in dependency of the current (5min) load. It goes
-	     * through the points f(0)=126, f(1)=86, f(5)=51,
-	     * f(inf)->30. */
-	     period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-	     dist = period / 4;
-	}
-#endif
-	if(!user_mode(regs)) {
+        if(!user_mode(regs)) {
 		if (prof_buffer && current->pid) {
-			extern int _stext;
-			unsigned long pc = regs->cp0_epc;
+                        extern int _stext;
+                        unsigned long pc = regs->cp0_epc;
 
-			pc -= (unsigned long) &_stext;
-			pc >>= prof_shift;
-			/*
-			 * Dont ignore out-of-bounds pc values silently,
-			 * put them into the last histogram slot, so if
-			 * present, they will show up as a sharp peak.
-			 */
-			if (pc > prof_len-1)
-				pc = prof_len-1;
-			atomic_inc((atomic_t *)&prof_buffer[pc]);
-		}
-	}
-	do_timer(regs);
+                        pc -= (unsigned long) &_stext;
+                        pc >>= prof_shift;
+                        /*
+                         * Dont ignore out-of-bounds pc values silently,
+                         * put them into the last histogram slot, so if
+                         * present, they will show up as a sharp peak.
+                         */
+                        if (pc > prof_len-1)
+                                pc = prof_len-1;
+                        atomic_inc((atomic_t *)&prof_buffer[pc]);
+                }
+        }
 
 	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
+	 * call the generic timer interrupt handling
 	 */
-	read_lock (&xtime_lock); 
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
-	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
-	  if (set_rtc_mmss(xtime.tv_sec) == 0)
-	    last_rtc_update = xtime.tv_sec;
-	  else
-	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
-	/* As we return to user mode fire off the other CPU schedulers.. this is 
-	   basically because we don't yet share IRQ's around. This message is
-	   rigged to be safe on the 386 - basically it's a hack, so don't look
-	   closely for now.. */
-	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
-	read_unlock (&xtime_lock); 
-}
+        do_timer(regs);
 
-static inline void 
-r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-	unsigned int count;
+        /*
+         * If we have an externally synchronized Linux clock, then update
+         * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
+         * called as close as possible to 500 ms before the new second starts.
+         */
+        read_lock (&xtime_lock);
+        if ((time_status & STA_UNSYNC) == 0 &&
+            xtime.tv_sec > last_rtc_update + 660 &&
+            xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+            xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
+
+		if (rtc_set_time(xtime.tv_sec) == 0) {
+			last_rtc_update = xtime.tv_sec;
+		} else {
+			last_rtc_update = xtime.tv_sec - 600; 
+			/* do it again in 60 s */
+		}
+        }
+        read_unlock (&xtime_lock);
 
 	/*
-	 * The cycle counter is only 32 bit which is good for about
-	 * a minute at current count rates of upto 150MHz or so.
-	 */
-	count = read_32bit_cp0_register(CP0_COUNT);
-	timerhi += (count < timerlo);	/* Wrap around */
-	timerlo = count;
-
-#ifdef CONFIG_SGI_IP22
-	/* Since we don't get anything but r4k timer interrupts, we need to
-	 * set this up so that we'll get one next time. Fortunately since we
-	 * have timerhi/timerlo, we don't care so much if we miss one. So
-	 * we need only ask for the next in r4k_interval counts. On other
-	 * archs we have a real timer, so we don't want this.
-	 */
-	write_32bit_cp0_register (CP0_COMPARE, 
-				  (unsigned long) (count + r4k_interval));
-        kstat.irqs[0][irq]++;
-#endif
-
-	timer_interrupt(irq, dev_id, regs);
-
-	if (!jiffies)
-	{
-		/*
-		 * If jiffies has overflowed in this timer_interrupt we must
-		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
-		 * quotient calc still valid. -arca
-		 */
-		timerhi = timerlo = 0;
-	}
+	 * If jiffies has overflowed in this timer_interrupt we must
+	 * update the timer[hi]/[lo] to make fast gettimeoffset funcs
+	 * quotient calc still valid. -arca
+	 */
+        if (!jiffies) {
+                timerhi = timerlo = 0;
+        }
 }
 
-void indy_r4k_timer_interrupt (struct pt_regs *regs)
+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
 {
-	static const int INDY_R4K_TIMER_IRQ = 7;
-	r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs);
-}
+	int cpu = smp_processor_id();
 
-char cyclecounter_available;
+	irq_enter(cpu, irq);
+	kstat.irqs[cpu][irq]++;
 
-static inline void init_cycle_counter(void)
-{
-	switch(mips_cputype) {
-	case CPU_UNKNOWN:
-	case CPU_R2000:
-	case CPU_R3000:
-	case CPU_R3000A:
-	case CPU_R3041:
-	case CPU_R3051:
-	case CPU_R3052:
-	case CPU_R3081:
-	case CPU_R3081E:
-	case CPU_R6000:
-	case CPU_R6000A:
-	case CPU_R8000:		/* Not shure about that one, play safe */
-		cyclecounter_available = 0;
-		break;
-	case CPU_R4000PC:
-	case CPU_R4000SC:
-	case CPU_R4000MC:
-	case CPU_R4200:
-	case CPU_R4400PC:
-	case CPU_R4400SC:
-	case CPU_R4400MC:
-	case CPU_R4600:
-	case CPU_R10000:
-	case CPU_R4300:
-	case CPU_R4650:
-	case CPU_R4700:
-	case CPU_R5000:
-	case CPU_R5000A:
-	case CPU_R4640:
-	case CPU_NEVADA:
-		cyclecounter_available = 1;
-		break;
-	}
-}
+	/* we keep interrupt disabled all the time */
+	timer_interrupt(irq, NULL, regs);
+	
+	irq_exit(cpu, irq);
 
-struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0,
-                                  "timer", NULL, NULL};
+	/* check for bottom half */
+        if (softirq_active(cpu)&softirq_mask(cpu))
+                do_softirq();
+}
 
 
-void (*board_time_init)(struct irqaction *irq);
+/*
+ * time_init() - it does the following things.
+ *
+ * 1) board_time_init() - 
+ * 	a) (optional) set up RTC routines, 
+ *      b) (optional) calibrate and set the mips_counter_frequency
+ *	    (only needed if you intended to use fixed_rate_gettimeoffset
+ *	     or use cpu counter as timer interrupt source)
+ * 2) setup xtime based on rtc_get_time().
+ * 3) choose a appropriate gettimeoffset routine.
+ * 4) calculate a couple of cached variables for later usage
+ * 5) board_timer_setup() - 
+ *	a) (optional) over-write any choices made above by time_init().
+ *	b) machine specific code should setup the timer irqaction.
+ *	c) enable the timer interrupt
+ */ 
+
+void (*board_time_init)(void) = NULL;
+void (*board_timer_setup)(struct irqaction *irq) = NULL;
+
+unsigned int mips_counter_frequency = 0;
+
+static struct irqaction timer_irqaction = {
+	timer_interrupt,
+	SA_INTERRUPT,
+	0,
+	"timer",
+	NULL,
+	NULL};
 
 void __init time_init(void)
 {
-	unsigned int epoch = 0, year, mon, day, hour, min, sec;
-	int i;
+	printk("New MIPS time_init() invoked.\n");
 
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-	/* read RTC exactly on falling edge of update flag */
-	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
-		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
-			break;
-	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
-		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
-			break;
-	do { /* Isn't this overkill ? UIP above should guarantee consistency */
-		sec = CMOS_READ(RTC_SECONDS);
-		min = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
-	} while (sec != CMOS_READ(RTC_SECONDS));
-	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-	  {
-	    BCD_TO_BIN(sec);
-	    BCD_TO_BIN(min);
-	    BCD_TO_BIN(hour);
-	    BCD_TO_BIN(day);
-	    BCD_TO_BIN(mon);
-	    BCD_TO_BIN(year);
-	  }
-
-	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c so
-	   no stupid things will happen to timekeeping.  Who knows, maybe Ultrix
-  	   also uses 1952 as epoch ...  */
-	if (year > 10 && year < 44) {
-		epoch = 1980;
-	} else if (year < 96) {
-		epoch = 1952;
-	}
-	year += epoch;
+	if (board_time_init)
+		board_time_init();
 
-	write_lock_irq (&xtime_lock);
-	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	/* setup xtime */
+	write_lock_irq(&xtime_lock);
+	xtime.tv_sec = rtc_get_time();
 	xtime.tv_usec = 0;
-	write_unlock_irq (&xtime_lock);
-
-	init_cycle_counter();
+	write_unlock_irq(&xtime_lock);
 
-	if (cyclecounter_available) {
-		write_32bit_cp0_register(CP0_COUNT, 0);
-		do_gettimeoffset = do_fast_gettimeoffset;
-		irq0.handler = r4k_timer_interrupt;
-	}
-
-	board_time_init(&irq0);
+	/* choose appropriate gettimeoffset routine */
+	if ( ! (mips_cpu.options & MIPS_CPU_COUNTER) ) {
+		/* no cpu counter - sorry */
+		do_gettimeoffset = null_gettimeoffset;
+	} else if (mips_counter_frequency != 0) {
+		/* we have cpu counter and know counter frequency! */
+		do_gettimeoffset = fixed_rate_gettimeoffset;
+	} else if ((mips_cpu.isa_level == MIPS_CPU_ISA_M32) ||
+		   (mips_cpu.isa_level == MIPS_CPU_ISA_I) ||
+		   (mips_cpu.isa_level == MIPS_CPU_ISA_II) ) {
+		/* we need to calibrate the counter but we don't have
+		 * 64-bit division. */
+		do_gettimeoffset = calibrate_div32_gettimeoffset;
+	} else {
+		/* we need to calibrate the counter but we *do* have
+		 * 64-bit division. */
+		do_gettimeoffset = calibrate_div64_gettimeoffset;
+	}	
+
+	/* caclulate cache parameters */
+	if (mips_counter_frequency) {
+		cycles_per_jiffy = mips_counter_frequency / HZ;
+
+		/* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */
+		/* any better way to do this? */
+		sll32_usecs_per_cycle = mips_counter_frequency / 100000;
+		sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle;
+		sll32_usecs_per_cycle *= 10;
+
+		MIPS_DEBUG(printk("cycles_per_jiffy = %d\n", 
+				  cycles_per_jiffy));
+		MIPS_DEBUG(printk("sll32_usecs_per_cycle = %d \n",
+				  sll32_usecs_per_cycle));
+	}
+
+	/* 
+	 * Call board specific timer interrupt setup.
+	 *
+	 * this pointer must be setup in machine setup routine. 
+	 *
+	 * Even if the machine choose to use low-level timer interrupt,
+	 * it still needs to setup the timer_irqaction.
+	 * In that case, it might be better to set timer_irqaction.handler 
+	 * to be NULL function so that we are sure the high-level code
+	 * is not invoked accidentally.
+	 */
+	MIPS_ASSERT(board_timer_setup != NULL);
+	board_timer_setup(&timer_irqaction);
 }
diff -urN linux-2.4.6-pre8/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- linux-2.4.6-pre8/arch/mips/kernel/traps.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/traps.c	Mon Dec  3 22:50:37 2001
@@ -32,6 +32,9 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#ifndef CONFIG_MIPS_FPU_EMULATOR 
+#include <asm/inst.h>
+#endif
 
 /*
  * Machine specific interrupt handlers
@@ -90,9 +93,9 @@
 #define RT     0x001f0000
 #define OFFSET 0x0000ffff
 #define LL     0xc0000000
-#define SC     0xd0000000
+#define SC     0xe0000000
 
-#define DEBUG_LLSC
+#undef DEBUG_LLSC
 #endif
 
 /*
@@ -268,9 +271,6 @@
 	/*
 	 * Assume it would be too dangerous to continue ...
 	 */
-/* XXX */
-printk("Got Bus Error at %08x\n", (unsigned int)regs->cp0_epc);
-show_regs(regs); while(1);
 	force_sig(SIGBUS, current);
 }
 
@@ -410,7 +410,7 @@
 
 	epc = (unsigned int *) (unsigned long) regs->cp0_epc;
 	if (regs->cp0_cause & CAUSEF_BD)
-		epc += 4;
+		epc++;
 
 	if (verify_area(VERIFY_READ, epc, 4)) {
 		force_sig(SIGSEGV, current);
@@ -423,6 +423,7 @@
 
 void do_bp(struct pt_regs *regs)
 {
+	siginfo_t info;
 	unsigned int opcode, bcode;
 
 	/*
@@ -491,48 +492,69 @@
 
 #if !defined(CONFIG_CPU_HAS_LLSC)
 
+#ifdef CONFIG_SMP
+#error "ll/sc emulation is not SMP safe"
+#endif
+
 /*
  * userland emulation for R2300 CPUs
  * needed for the multithreading part of glibc
+ *
+ * this implementation can handle only sychronization between 2 or more
+ * user contexts and is not SMP safe.
  */
 void do_ri(struct pt_regs *regs)
 {
 	unsigned int opcode;
 
+	if (!user_mode(regs))
+		BUG();
+
 	if (!get_insn_opcode(regs, &opcode)) {
-		if ((opcode & OPCODE) == LL)
+		if ((opcode & OPCODE) == LL) {
 			simulate_ll(regs, opcode);
-		if ((opcode & OPCODE) == SC)
+			return;
+		}
+		if ((opcode & OPCODE) == SC) {
 			simulate_sc(regs, opcode);
-	} else {
-	printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
-	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+			return;
+		}
 	}
+	printk("[%s:%d] Illegal instruction %08lx at %08lx, ra=%08lx, CP0_STATUS=%08lx\n",
+	       current->comm, current->pid, *((unsigned long*)regs->cp0_epc), regs->cp0_epc,
+		regs->regs[31], regs->cp0_status);
 	if (compute_return_epc(regs))
 		return;
 	force_sig(SIGILL, current);
 }
 
 /*
- * the ll_bit will be cleared by r2300_switch.S
+ * The ll_bit is cleared by r*_switch.S
  */
-unsigned long ll_bit, *lladdr;
- 
+
+unsigned long ll_bit;
+#ifdef CONFIG_PROC_FS
+extern unsigned long ll_ops;
+extern unsigned long sc_ops;
+#endif
+
+static struct task_struct *ll_task = NULL;
+
 void simulate_ll(struct pt_regs *regp, unsigned int opcode)
 {
-	unsigned long *addr, *vaddr;
+	unsigned long value, *vaddr;
 	long offset;
- 
+	int signal = 0;
+
 	/*
 	 * analyse the ll instruction that just caused a ri exception
 	 * and put the referenced address to addr.
 	 */
+
 	/* sign extend offset */
 	offset = opcode & OFFSET;
-	if (offset & 0x00008000)
-		offset = -(offset & 0x00007fff);
-	else
-		offset = (offset & 0x00007fff);
+	offset <<= 16;
+	offset >>= 16;
 
 	vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
 
@@ -540,31 +562,44 @@
 	printk("ll: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (opcode & RT) >> 16);
 #endif
 
-	/*
-	 * TODO: compute physical address from vaddr
-	 */
-	panic("ll: emulation not yet finished!");
+#ifdef CONFIG_PROC_FS
+	ll_ops++;
+#endif
 
-	lladdr = addr;
-	ll_bit = 1;
-	regp->regs[(opcode & RT) >> 16] = *addr;
+	if ((unsigned long)vaddr & 3)
+		signal = SIGBUS;
+	else if (get_user(value, vaddr))
+		signal = SIGSEGV;
+	else {
+		if (ll_task == NULL || ll_task == current) {
+			ll_bit = 1;
+		} else {
+			ll_bit = 0;
+		}
+		ll_task = current;
+		regp->regs[(opcode & RT) >> 16] = value;
+	}
+	if (compute_return_epc(regp))
+		return;
+	if (signal)
+		send_sig(signal, current, 1);
 }
- 
+
 void simulate_sc(struct pt_regs *regp, unsigned int opcode)
 {
-	unsigned long *addr, *vaddr, reg;
+	unsigned long *vaddr, reg;
 	long offset;
+	int signal = 0;
 
 	/*
 	 * analyse the sc instruction that just caused a ri exception
 	 * and put the referenced address to addr.
 	 */
+
 	/* sign extend offset */
 	offset = opcode & OFFSET;
-	if (offset & 0x00008000)
-		offset = -(offset & 0x00007fff);
-	else
-		offset = (offset & 0x00007fff);
+	offset <<= 16;
+	offset >>= 16;
 
 	vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
 	reg = (opcode & RT) >> 16;
@@ -573,28 +608,34 @@
 	printk("sc: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (unsigned int)reg);
 #endif
 
-	/*
-	 * TODO: compute physical address from vaddr
-	 */
-	panic("sc: emulation not yet finished!");
-
-	lladdr = addr;
+#ifdef CONFIG_PROC_FS
+	sc_ops++;
+#endif
 
-	if (ll_bit == 0) {
+	if ((unsigned long)vaddr & 3)
+		signal = SIGBUS;
+	else if (ll_bit == 0 || ll_task != current)
 		regp->regs[reg] = 0;
+	else if (put_user(regp->regs[reg], vaddr))
+		signal = SIGSEGV;
+	else
+		regp->regs[reg] = 1;
+	if (compute_return_epc(regp))
 		return;
-	}
-
-	*addr = regp->regs[reg];
-	regp->regs[reg] = 1;
+	if (signal)
+		send_sig(signal, current, 1);
 }
 
 #else /* MIPS 2 or higher */
 
 void do_ri(struct pt_regs *regs)
 {
-	printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
-	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+	unsigned int opcode;
+
+        get_insn_opcode(regs, &opcode);
+	printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n",
+	       current->comm, (unsigned long)current->pid, opcode,
+	       regs->cp0_epc, regs->regs[31]);
 	if (compute_return_epc(regs))
 		return;
 	force_sig(SIGILL, current);
@@ -662,50 +703,101 @@
 	panic("Caught WATCH exception - probably caused by stack overflow.");
 }
 
+void do_mcheck(struct pt_regs *regs)
+{
+	show_regs(regs);
+	panic("Caught Machine Check exception - probably caused by multiple "
+	      "matching entries in the TLB.");
+}
+
 void do_reserved(struct pt_regs *regs)
 {
 	/*
-	 * Game over - no way to handle this if it ever occurs.
-	 * Most probably caused by a new unknown cpu type or
-	 * after another deadly hard/software error.
+	 * Game over - no way to handle this if it ever occurs.  Most probably
+	 * caused by a new unknown cpu type or after another deadly
+	 * hard/software error.
 	 */
+	show_regs(regs);
 	panic("Caught reserved exception - should not happen.");
 }
 
-static inline void watch_init(unsigned long cputype)
+static inline void watch_init(void)
 {
-	switch(cputype) {
-	case CPU_R10000:
-	case CPU_R4000MC:
-	case CPU_R4400MC:
-	case CPU_R4000SC:
-	case CPU_R4400SC:
-	case CPU_R4000PC:
-	case CPU_R4400PC:
-	case CPU_R4200:
-	case CPU_R4300:
-		set_except_vector(23, handle_watch);
-		watch_available = 1;
-		break;
-	}
+        if(mips_cpu.options & MIPS_CPU_WATCH ) {
+		(void)set_except_vector(23, handle_watch);
+ 		watch_available = 1;
+ 	}
 }
 
 /*
  * Some MIPS CPUs have a dedicated interrupt vector which reduces the
  * interrupt processing overhead.  Use it where available.
- * FIXME: more CPUs than just the Nevada have this feature.
  */
 static inline void setup_dedicated_int(void)
 {
 	extern void except_vec4(void);
-	switch(mips_cputype) {
-	case CPU_NEVADA:
+
+	if(mips_cpu.options & MIPS_CPU_DIVEC) {
 		memcpy((void *)(KSEG0 + 0x200), except_vec4, 8);
-		set_cp0_cause(CAUSEF_IV, CAUSEF_IV);
+		set_cp0_cause(CAUSEF_IV);
 		dedicated_iv_available = 1;
 	}
 }
 
+/*
+ * Some MIPS CPUs can enable/disable for cache parity detection, but does
+ * it different ways.
+ */
+static inline void parity_protection_init(void)
+{
+	switch(mips_cpu.cputype) {
+	case CPU_5KC:
+		/* Set the PE bit (bit 31) in the CP0_ECC register. */
+		printk(KERN_INFO "Enable the cache parity protection for "
+		       "MIPS 5KC CPUs.\n");
+		write_32bit_cp0_register(CP0_ECC,
+		                         read_32bit_cp0_register(CP0_ECC)
+		                         | 0x80000000); 
+		break;
+	default:
+		break;
+	}
+}
+
+void cache_parity_error(void)
+{
+        unsigned int reg_val;
+
+        /* For the moment, report the problem and hang. */
+        reg_val = read_32bit_cp0_register(CP0_ERROREPC);
+	printk("Cache error exception:\n");
+	printk("cp0_errorepc == %08x\n", reg_val);
+	reg_val = read_32bit_cp0_register(CP0_CACHEERR);
+	printk("cp0_cacheerr == %08x\n", reg_val);
+
+	printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.\n",
+	       reg_val&(1<<30)?"secondary":"primary",
+	       reg_val&(1<<31)?"data":"insn");
+	printk("Error bits: %s%s%s%s%s%s%s\n",
+	       reg_val&(1<<29)?"ED ":"",
+	       reg_val&(1<<28)?"ET ":"",
+	       reg_val&(1<<26)?"EE ":"",
+	       reg_val&(1<<25)?"EB ":"",
+	       reg_val&(1<<24)?"EI ":"",
+	       reg_val&(1<<23)?"E1 ":"",
+	       reg_val&(1<<22)?"E0 ":"");
+	printk("IDX: 0x%08x\n", reg_val&((1<<22)-1));
+
+	if (reg_val&(1<<22))
+		printk("DErrAddr0: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR0));
+
+	if (reg_val&(1<<23))
+		printk("DErrAddr1: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR1));
+
+
+	panic("Can't handle the cache error - panic!");
+}
+
 unsigned long exception_handlers[32];
 
 /*
@@ -713,23 +805,36 @@
  * to interrupt handlers in the address range from
  * KSEG0 <= x < KSEG0 + 256mb on the Nevada.  Oh well ...
  */
-void set_except_vector(int n, void *addr)
+void *set_except_vector(int n, void *addr)
 {
 	unsigned handler = (unsigned long) addr;
+	unsigned old_handler = exception_handlers[n];
 	exception_handlers[n] = handler;
 	if (n == 0 && dedicated_iv_available) {
 		*(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
 		                                 (0x03ffffff & (handler >> 2));
 		flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
 	}
+	return (void *)old_handler;
 }
 
+asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage int _save_fp_context(struct sigcontext *sc);
+extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+#endif
+
 void __init trap_init(void)
 {
 	extern char except_vec0_nevada, except_vec0_r4000;
 	extern char except_vec0_r4600, except_vec0_r2300;
 	extern char except_vec1_generic, except_vec2_generic;
 	extern char except_vec3_generic, except_vec3_r4000;
+	extern char except_vec_ejtag_debug;
 	unsigned long i;
 
 	if(mips_machtype == MACH_MIPS_MAGNUM_4000 ||
@@ -737,101 +842,121 @@
 		EISA_bus = 1;
 
 	/* Some firmware leaves the BEV flag set, clear it.  */
-	set_cp0_status(ST0_BEV, 0);
+	clear_cp0_status(ST0_BEV);
 
 	/* Copy the generic exception handler code to it's final destination. */
 	memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
 	memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
 	memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
-
+	flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200);
 	/*
 	 * Setup default vectors
 	 */
 	for(i = 0; i <= 31; i++)
-		set_except_vector(i, handle_reserved);
+		(void)set_except_vector(i, handle_reserved);
+
+	/* 
+	 * Copy the EJTAG debug exception vector handler code to it's final 
+	 * destination.
+	 */
+	memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
 
 	/*
 	 * Only some CPUs have the watch exceptions or a dedicated
 	 * interrupt vector.
 	 */
-	watch_init(mips_cputype);
+	watch_init();
 	setup_dedicated_int();
 
-	set_except_vector(1, handle_mod);
-	set_except_vector(2, handle_tlbl);
-	set_except_vector(3, handle_tlbs);
-	set_except_vector(4, handle_adel);
-	set_except_vector(5, handle_ades);
+	/*
+	 * Some CPUs can enable/disable for cache parity detection, but does
+	 * it different ways.
+	 */
+	parity_protection_init();
+
+	(void)set_except_vector(1, handle_mod);
+	(void)set_except_vector(2, handle_tlbl);
+	(void)set_except_vector(3, handle_tlbs);
+	(void)set_except_vector(4, handle_adel);
+	(void)set_except_vector(5, handle_ades);
 	/*
 	 * The Data Bus Error/ Instruction Bus Errors are signaled
 	 * by external hardware.  Therefore these two expection have
 	 * board specific handlers.
 	 */
-	set_except_vector(6, handle_ibe);
-	set_except_vector(7, handle_dbe);
+	(void)set_except_vector(6, handle_ibe);
+	(void)set_except_vector(7, handle_dbe);
 	ibe_board_handler = default_be_board_handler;
 	dbe_board_handler = default_be_board_handler;
 
-	set_except_vector(8, handle_sys);
-	set_except_vector(9, handle_bp);
-	set_except_vector(10, handle_ri);
-	set_except_vector(11, handle_cpu);
-	set_except_vector(12, handle_ov);
-	set_except_vector(13, handle_tr);
-	set_except_vector(15, handle_fpe);
-
+	(void)set_except_vector(8, handle_sys);
+	(void)set_except_vector(9, handle_bp);
+	(void)set_except_vector(10, handle_ri);
+	(void)set_except_vector(11, handle_cpu);
+	(void)set_except_vector(12, handle_ov);
+	(void)set_except_vector(13, handle_tr);
+	(void)set_except_vector(15, handle_fpe);
+	
 	/*
 	 * Handling the following exceptions depends mostly of the cpu type
 	 */
-	switch(mips_cputype) {
-	case CPU_R10000:
-		/*
-		 * The R10000 is in most aspects similar to the R4400.  It
-		 * should get some special optimizations.
-		 */
-		write_32bit_cp0_register(CP0_FRAMEMASK, 0);
-		set_cp0_status(ST0_XX, ST0_XX);
-		/*
-		 * The R10k might even work for Linux/MIPS - but we're paranoid
-		 * and refuse to run until this is tested on real silicon
-		 */
-		panic("CPU too expensive - making holiday in the ANDES!");
-		break;
-	case CPU_R4000MC:
-	case CPU_R4400MC:
-	case CPU_R4000SC:
-	case CPU_R4400SC:
-		vce_available = 1;
-		/* Fall through ...  */
-	case CPU_R4000PC:
-	case CPU_R4400PC:
-	case CPU_R4200:
-	case CPU_R4300:
-     /* case CPU_R4640: */
-	case CPU_R4600:
-        case CPU_R5000:
-        case CPU_NEVADA:
-		if(mips_cputype == CPU_NEVADA) {
+	if ((mips_cpu.options & MIPS_CPU_4KEX)
+	    && (mips_cpu.options & MIPS_CPU_4KTLB)) {
+		if(mips_cpu.cputype == CPU_NEVADA) {
 			memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
-		} else if (mips_cputype == CPU_R4600)
+		} else if (mips_cpu.cputype == CPU_R4600)
 			memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
 		else
 			memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
 
 		/* Cache error vector already set above.  */
 
-		if (vce_available) {
+		if (mips_cpu.options & MIPS_CPU_VCE) {
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
 			       0x80);
 		} else {
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
 			       0x80);
 		}
-		break;
 
+		if(mips_cpu.options & MIPS_CPU_FPU) {
+		        save_fp_context = _save_fp_context;
+			restore_fp_context = _restore_fp_context;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+		} else {
+		        save_fp_context = fpu_emulator_save_context;
+			restore_fp_context = fpu_emulator_restore_context;
+#endif
+		}
+	} else switch(mips_cpu.cputype) {
+	case CPU_R10000:
+		/*
+		 * The R10000 is in most aspects similar to the R4400.  It
+		 * should get some special optimizations.
+		 */
+		write_32bit_cp0_register(CP0_FRAMEMASK, 0);
+		set_cp0_status(ST0_XX);
+		/*
+		 * The R10k might even work for Linux/MIPS - but we're paranoid
+		 * and refuse to run until this is tested on real silicon
+		 */
+		panic("CPU too expensive - making holiday in the ANDES!");
+		break;
+	case CPU_SB1:
+		/* XXX - This should be folded in to the "cleaner" handling, above */
+		memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
+		memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
+		save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
+		/* Enable timer interrupt and scd mapped interrupt in status register */
+		clear_cp0_status(0xf000);
+		set_cp0_status(0xc00);
+		break;
 	case CPU_R6000:
 	case CPU_R6000A:
-#if 0
+	        save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
+		
 		/*
 		 * The R6000 is the only R-series CPU that features a machine
 		 * check exception (similar to the R4000 cache error) and
@@ -840,9 +965,8 @@
 		 * current list of targets for Linux/MIPS.
 		 * (Duh, crap, there is someone with a tripple R6k machine)
 		 */
-		set_except_vector(14, handle_mc);
-		set_except_vector(15, handle_ndc);
-#endif
+		//set_except_vector(14, handle_mc);
+		//set_except_vector(15, handle_ndc);
 	case CPU_R2000:
 	case CPU_R3000:
 	case CPU_R3000A:
@@ -851,12 +975,17 @@
 	case CPU_R3052:
 	case CPU_R3081:
 	case CPU_R3081E:
+	case CPU_TX3912:
+	case CPU_TX3922:
+	case CPU_TX3927:
+	        save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
 		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
 		memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
 		break;
 	case CPU_R8000:
 		printk("Detected unsupported CPU type %s.\n",
-			cpu_names[mips_cputype]);
+			cpu_names[mips_cpu.cputype]);
 		panic("Can't handle CPU");
 		break;
 
@@ -868,5 +997,6 @@
 
 	atomic_inc(&init_mm.mm_count);	/* XXX  UP?  */
 	current->active_mm = &init_mm;
-	current_pgd = init_mm.pgd;
+	write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
+	current_pgd[0] = init_mm.pgd;
 }
diff -urN linux-2.4.6-pre8/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c
--- linux-2.4.6-pre8/arch/mips/kernel/unaligned.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/unaligned.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,4 @@
-/* $Id: unaligned.c,v 1.7 1999/12/04 03:59:00 ralf Exp $
- *
+/*
  * Handle unaligned accesses by emulation.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -83,6 +82,7 @@
 #include <asm/byteorder.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
+#include <asm/system.h>
 
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
@@ -91,8 +91,8 @@
  * User code may only access USEG; kernel code may access the
  * entire address space.
  */
-#define check_axs(p,a,s)                                \
-	if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0)      \
+#define check_axs(pc,a,s)				\
+	if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0)	\
 		goto sigbus;
 
 static inline void
@@ -365,12 +365,15 @@
 		return;
 	}
 
+	die_if_kernel ("Unhandled kernel unaligned access", regs);
 	send_sig(SIGSEGV, current, 1);
 	return;
 sigbus:
+	die_if_kernel ("Unhandled kernel unaligned access", regs);
 	send_sig(SIGBUS, current, 1);
 	return;
 sigill:
+	die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs);
 	send_sig(SIGILL, current, 1);
 	return;
 }
@@ -380,6 +383,21 @@
 asmlinkage void do_ade(struct pt_regs *regs)
 {
 	unsigned long pc;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+        extern int do_dsemulret(struct pt_regs *);
+
+        /* 
+         * Address errors may be deliberately induced
+         * by the FPU emulator to take retake control
+         * of the CPU after executing the instruction
+         * in the delay slot of an emulated branch.
+         */
+
+        if((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) {
+                (void)do_dsemulret(regs);
+                return;
+        }
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
 
 	/*
 	 * Did we catch a fault trying to load an instruction?
@@ -401,6 +419,7 @@
 	return;
 
 sigbus:
+	die_if_kernel ("Kernel unaligned instruction access", regs);
 	force_sig(SIGBUS, current);
 
 	return;
diff -urN linux-2.4.6-pre8/arch/mips/ld.script.big linux/arch/mips/ld.script.big
--- linux-2.4.6-pre8/arch/mips/ld.script.big	Wed Jul 12 15:14:41 2000
+++ linux/arch/mips/ld.script.big	Wed Dec 31 16:00:00 1969
@@ -1,120 +0,0 @@
-OUTPUT_FORMAT("elf32-bigmips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
-  .init          : { *(.init)		} =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-
-  /* Startup code */
-  . = ALIGN(4096);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);	/* Align double page for init_task_union */
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  __bss_start = .;
-  _fbss = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-  }
-
-  /* Sections to be discarded */
-  /DISCARD/ :
-  {
-        *(.text.exit)
-        *(.data.exit)
-        *(.exitcall.exit)
-  }
-
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff -urN linux-2.4.6-pre8/arch/mips/ld.script.in linux/arch/mips/ld.script.in
--- linux-2.4.6-pre8/arch/mips/ld.script.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ld.script.in	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,147 @@
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = @@LOADADDR@@;
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___dbe_table = .;	/* Exception table for data bus errors */
+  __dbe_table : { *(__dbe_table) }
+  __stop___dbe_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;
+
+  . = ALIGN(8192);
+  .data.init_task : { *(.data.init_task) }
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);	/* Align double page for init_task_union */
+  __init_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+
+   /* Align the initial ramdisk image (INITRD) on page boundaries. */
+   . = ALIGN(4096);
+   __rd_start = .;
+   *(.initrd)
+   __rd_end = .;
+   . = ALIGN(4096);
+
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  . = ALIGN(4);
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __bss_start = .;
+  _fbss = .;
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   .  = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+  }
+
+  /* Sections to be discarded */
+  /DISCARD/ :
+  {
+        *(.text.exit)
+        *(.data.exit)
+        *(.exitcall.exit)
+  }
+
+  /* This is the MIPS specific mdebug section.  */
+  .mdebug : { *(.mdebug) }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+  .comment : { *(.comment) }
+  .note : { *(.note) }
+}
diff -urN linux-2.4.6-pre8/arch/mips/ld.script.little linux/arch/mips/ld.script.little
--- linux-2.4.6-pre8/arch/mips/ld.script.little	Wed Jul 12 15:14:41 2000
+++ linux/arch/mips/ld.script.little	Wed Dec 31 16:00:00 1969
@@ -1,120 +0,0 @@
-OUTPUT_FORMAT("elf32-littlemips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
-  .init          : { *(.init)		} =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-
-  /* Startup code */
-  . = ALIGN(4096);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);	/* Align double page for init_task_union */
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  __bss_start = .;
-  _fbss = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-  }
-
-  /* Sections to be discarded */
-  /DISCARD/ : 
-  {
-        *(.text.exit)
-        *(.data.exit)
-        *(.exitcall.exit)
-  }
-
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff -urN linux-2.4.6-pre8/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- linux-2.4.6-pre8/arch/mips/lib/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/lib/Makefile	Mon Dec  3 22:50:37 2001
@@ -17,11 +17,7 @@
 ifdef CONFIG_CPU_R3000
   obj-y	+= r3k_dump_tlb.o 
 else
-  ifdef CONFIG_CPU_R3912
-    obj-y	+= r3k_dump_tlb.o 
-  else
-    obj-y	+= dump_tlb.o 
-  endif
+  obj-y	+= dump_tlb.o 
 endif
 
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy-no.o floppy-std.o
diff -urN linux-2.4.6-pre8/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c
--- linux-2.4.6-pre8/arch/mips/lib/kbd-std.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/lib/kbd-std.c	Mon Dec  3 22:50:37 2001
@@ -8,7 +8,6 @@
  *
  * Copyright (C) 1998, 1999 by Ralf Baechle
  */
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/pc_keyb.h>
@@ -21,7 +20,6 @@
 static void std_kbd_request_region(void)
 {
 #ifdef CONFIG_MIPS_ITE8172
-	printk("std_kbd_request_region\n");
 	request_region(0x14000060, 16, "keyboard");
 #else
 	request_region(0x60, 16, "keyboard");
@@ -30,7 +28,6 @@
 
 static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
 {
-	printk("std_kbd_request_irq\n");
 	return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
 }
 
diff -urN linux-2.4.6-pre8/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S
--- linux-2.4.6-pre8/arch/mips/lib/memset.S	Tue Dec  5 23:15:12 2000
+++ linux/arch/mips/lib/memset.S	Mon Dec  3 22:50:37 2001
@@ -54,6 +54,7 @@
 1:
 
 EXPORT(__bzero)
+	.type   __bzero, @function
 	sltiu	t0, a2, 4			/* very small region? */
 	bnez	t0, small_memset
 	 andi	t0, a0, 3			/* aligned? */
diff -urN linux-2.4.6-pre8/arch/mips/lib/rtc-no.c linux/arch/mips/lib/rtc-no.c
--- linux-2.4.6-pre8/arch/mips/lib/rtc-no.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/lib/rtc-no.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,4 @@
-/* $Id: rtc-no.c,v 1.2 1998/06/25 20:19:15 ralf Exp $
- *
+/*
  * 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.
@@ -7,28 +6,25 @@
  * Stub RTC routines to keep Linux from crashing on machine which don't
  * have a RTC chip.
  *
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2001 by Ralf Baechle
  */
 #include <linux/kernel.h>
 #include <linux/mc146818rtc.h>
 
-static unsigned char no_rtc_read_data(unsigned long addr)
+static unsigned int shouldnt_happen(void)
 {
-	panic("no_rtc_read_data called - shouldn't happen.");
-}
+	static int called;
 
-static void no_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	panic("no_rtc_write_data called - shouldn't happen.");
-}
+	if (!called) {
+		called = 1;
+		printk(KERN_DEBUG "RTC functions called - shouldn't happen\n");
+	}
 
-static int no_rtc_bcd_mode(void)
-{
-	panic("no_rtc_bcd_mode called - shouldn't happen.");
+	return 0;
 }
 
 struct rtc_ops no_rtc_ops = {
-	&no_rtc_read_data,
-	&no_rtc_write_data,
-	&no_rtc_bcd_mode
+    rtc_read_data:  (void *) &shouldnt_happen,
+    rtc_write_data: (void *) &shouldnt_happen,
+    rtc_bcd_mode:   (void *) &shouldnt_happen
 };
diff -urN linux-2.4.6-pre8/arch/mips/lib/rtc-std.c linux/arch/mips/lib/rtc-std.c
--- linux-2.4.6-pre8/arch/mips/lib/rtc-std.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/lib/rtc-std.c	Mon Dec  3 22:50:37 2001
@@ -1,12 +1,11 @@
-/* $Id: rtc-std.c,v 1.2 1998/06/25 20:19:16 ralf Exp $
- *
+/*
  * 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.
  *
  * RTC routines for PC style attached Dallas chip.
  *
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2001 by Ralf Baechle
  */
 #include <linux/mc146818rtc.h>
 #include <asm/io.h>
diff -urN linux-2.4.6-pre8/arch/mips/math-emu/cp1emu.c linux/arch/mips/math-emu/cp1emu.c
--- linux-2.4.6-pre8/arch/mips/math-emu/cp1emu.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/math-emu/cp1emu.c	Mon Dec  3 22:50:37 2001
@@ -49,6 +49,7 @@
  *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  *  Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
  *************************************************************************/
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
diff -urN linux-2.4.6-pre8/arch/mips/math-emu/dp_sub.c linux/arch/mips/math-emu/dp_sub.c
--- linux-2.4.6-pre8/arch/mips/math-emu/dp_sub.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/math-emu/dp_sub.c	Mon Dec  3 22:50:37 2001
@@ -176,11 +176,12 @@
 			xe = xe;
 			xs = ys;
 		}
-		if (xm == 0)
+		if (xm == 0) {
 			if (ieee754_csr.rm == IEEE754_RD)
 				return ieee754dp_zero(1);	/* round negative inf. => sign = -1 */
 			else
 				return ieee754dp_zero(0);	/* other round modes   => sign = 1 */
+		}
 
 		/* normalize to rounding precision 
 		 */
diff -urN linux-2.4.6-pre8/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile
--- linux-2.4.6-pre8/arch/mips/mm/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/mm/Makefile	Mon Dec  3 22:50:37 2001
@@ -9,11 +9,10 @@
 
 O_TARGET := mm.o
 
-export-objs			+= umap.o
-obj-y				+= extable.o init.o fault.o loadmmu.o
+export-objs			+= ioremap.o umap.o
+obj-y				+= extable.o init.o ioremap.o fault.o loadmmu.o
 
 obj-$(CONFIG_CPU_R3000)		+= r2300.o
-obj-$(CONFIG_CPU_R3912)		+= r2300.o
 obj-$(CONFIG_CPU_R4300)		+= r4xx0.o
 obj-$(CONFIG_CPU_R4X00)		+= r4xx0.o
 obj-$(CONFIG_CPU_R5000)		+= r4xx0.o
diff -urN linux-2.4.6-pre8/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c
--- linux-2.4.6-pre8/arch/mips/tools/offset.c	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/tools/offset.c	Mon Dec  3 22:50:37 2001
@@ -1,12 +1,13 @@
-/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $
- *
+/*
  * offset.c: Calculate pt_regs and task_struct offsets.
  *
  * Copyright (C) 1996 David S. Miller
  * Copyright (C) 1997, 1998, 1999 Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
  */
-
 #include <linux/types.h>
 #include <linux/sched.h>
 
@@ -84,6 +85,7 @@
 	offset("#define TASK_COUNTER       ", struct task_struct, counter);
 	offset("#define TASK_NICE          ", struct task_struct, nice);
 	offset("#define TASK_MM            ", struct task_struct, mm);
+	offset("#define TASK_PID           ", struct task_struct, pid);
 	size("#define TASK_STRUCT_SIZE   ", struct task_struct);
 	linefeed;
 }
@@ -119,6 +121,10 @@
 	       thread.irix_trampoline);
 	offset("#define THREAD_OLDCTX  ", struct task_struct, \
 	       thread.irix_oldctx);
+	offset("#define THREAD_DSEEPC  ", struct task_struct, \
+	       thread.dsemul_epc);
+	offset("#define THREAD_DSEAERPC ", struct task_struct, \
+	       thread.dsemul_aerpc);
 	linefeed;
 }
 
diff -urN linux-2.4.6-pre8/arch/mips64/ld.script.elf32.S linux/arch/mips64/ld.script.elf32.S
--- linux-2.4.6-pre8/arch/mips64/ld.script.elf32.S	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/ld.script.elf32.S	Mon Dec  3 22:50:37 2001
@@ -8,6 +8,7 @@
   {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -urN linux-2.4.6-pre8/arch/mips64/ld.script.elf64 linux/arch/mips64/ld.script.elf64
--- linux-2.4.6-pre8/arch/mips64/ld.script.elf64	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/ld.script.elf64	Mon Dec  3 22:50:37 2001
@@ -18,6 +18,7 @@
   .text : {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/Makefile linux/arch/mips64/math-emu/Makefile
--- linux-2.4.6-pre8/arch/mips64/math-emu/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/Makefile	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,24 @@
+#
+# Makefile for the Linux/MIPS kernel FPU emulation.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+EXTRA_ASFLAGS = -mips2 -mcpu=r4000
+
+O_TARGET:= fpu_emulator.o
+
+obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
+	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
+	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
+	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
+	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
+	   dp_sqrt.o sp_sqrt.o kernel_linkage.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/cp1emu.c linux/arch/mips64/math-emu/cp1emu.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/cp1emu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/cp1emu.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,1807 @@
+/*
+ * MIPS floating point support
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ * 
+ * A complete emulator for MIPS coprocessor 1 instructions.  This is
+ * required for #float(switch) or #float(trap), where it catches all
+ * COP1 instructions via the "CoProcessor Unusable" exception.  
+ *
+ * More surprisingly it is also required for #float(ieee), to help out
+ * the hardware fpu at the boundaries of the IEEE-754 representation
+ * (denormalised values, infinities, underflow, etc).  It is made
+ * quite nasty because emulation of some non-COP1 instructions is
+ * required, e.g. in branch delay slots.
+ * 
+ * Notes: 
+ *  1) the IEEE754 library (-le) performs the actual arithmetic;
+ *  2) if you know that you won't have an fpu, then you'll get much 
+ *     better performance by compiling with -msoft-float!  */
+ *
+ *  Nov 7, 2000
+ *  Massive changes to integrate with Linux kernel.
+ *
+ *  Replace use of kernel data area with use of user stack 
+ *  for execution of instructions in branch delay slots.
+ *
+ *  Replace use of static kernel variables with thread_struct elements.
+ *
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+#include <asm/fpu_emulator.h>
+
+#include "ieee754.h"
+
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+typedef void *vaddr_t;
+
+/* Function which emulates the instruction in a branch delay slot. */
+
+static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
+
+/* Function which emulates a floating point instruction. */
+
+static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+	 mips_instruction);
+
+#if __mips >= 4 && __mips != 32
+static int fpux_emu(struct pt_regs *,
+		    struct mips_fpu_soft_struct *, mips_instruction);
+#endif
+
+/* Further private data for which no space exists in mips_fpu_soft_struct */
+
+struct mips_fpu_emulator_private fpuemuprivate;
+
+/* Control registers */
+
+#define FPCREG_RID	0	/* $0  = revision id */
+#define FPCREG_CSR	31	/* $31 = csr */
+
+/* Convert Mips rounding mode (0..3) to IEEE library modes. */
+static const unsigned char ieee_rm[4] = {
+	IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+};
+
+#if __mips >= 4
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+	FPU_CSR_COND0,
+	FPU_CSR_COND1,
+	FPU_CSR_COND2,
+	FPU_CSR_COND3,
+	FPU_CSR_COND4,
+	FPU_CSR_COND5,
+	FPU_CSR_COND6,
+	FPU_CSR_COND7
+};
+#endif
+
+
+
+/* 
+ * Redundant with logic already in kernel/branch.c,
+ * embedded in compute_return_epc.  At some point,
+ * a single subroutine should be used across both
+ * modules.
+ */
+static int isBranchInstr(mips_instruction * i)
+{
+	switch (MIPSInst_OPCODE(*i)) {
+	case spec_op:
+		switch (MIPSInst_FUNC(*i)) {
+		case jalr_op:
+		case jr_op:
+			return 1;
+		}
+		break;
+
+	case bcond_op:
+		switch (MIPSInst_RT(*i)) {
+		case bltz_op:
+		case bgez_op:
+		case bltzl_op:
+		case bgezl_op:
+		case bltzal_op:
+		case bgezal_op:
+		case bltzall_op:
+		case bgezall_op:
+			return 1;
+		}
+		break;
+
+	case j_op:
+	case jal_op:
+	case jalx_op:
+	case beq_op:
+	case bne_op:
+	case blez_op:
+	case bgtz_op:
+	case beql_op:
+	case bnel_op:
+	case blezl_op:
+	case bgtzl_op:
+		return 1;
+
+	case cop0_op:
+	case cop1_op:
+	case cop2_op:
+	case cop1x_op:
+		if (MIPSInst_RS(*i) == bc_op)
+			return 1;
+		break;
+	}
+
+	return 0;
+}
+
+#define REG_TO_VA (vaddr_t)
+#define VA_TO_REG (unsigned long)
+
+static unsigned long
+mips_get_word(struct pt_regs *xcp, void *va, int *perr)
+{
+	unsigned long temp;
+
+	if (!user_mode(xcp)) {
+		*perr = 0;
+		return (*(unsigned long *) va);
+	} else {
+		/* Use kernel get_user() macro */
+		*perr = (int) get_user(temp, (unsigned long *) va);
+		return temp;
+	}
+}
+
+static unsigned long long
+mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
+{
+	unsigned long long temp;
+
+	if (!user_mode(xcp)) {
+		*perr = 0;
+		return (*(unsigned long long *) va);
+	} else {
+		/* Use kernel get_user() macro */
+		*perr = (int) get_user(temp, (unsigned long long *) va);
+		return temp;
+	}
+}
+
+static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
+{
+	if (!user_mode(xcp)) {
+		*(unsigned long *) va = val;
+		return 0;
+	} else {
+		/* Use kernel get_user() macro */
+		return (int) put_user(val, (unsigned long *) va);
+	}
+}
+
+static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
+{
+	if (!user_mode(xcp)) {
+		*(unsigned long long *) va = val;
+		return 0;
+	} else {
+		/* Use kernel get_user() macro */
+		return (int) put_user(val, (unsigned long long *) va);
+	}
+}
+
+
+/*
+ * In the Linux kernel, we support selection of FPR format on the
+ * basis of the Status.FR bit.  This does imply that, if a full 32
+ * FPRs are desired, there needs to be a flip-flop that can be written
+ * to one at that bit position.  In any case, normal MIPS ABI uses
+ * only the even FPRs (Status.FR = 0).
+ */
+
+#define CP0_STATUS_FR_SUPPORT
+
+/*
+ * Emulate the single floating point instruction pointed at by EPC.
+ * Two instructions if the instruction is in a branch delay slot.
+ */
+
+static int
+cop1Emulate(int xcptno, struct pt_regs *xcp,
+	    struct mips_fpu_soft_struct *ctx)
+{
+	mips_instruction ir;
+	vaddr_t emulpc;
+	vaddr_t contpc;
+	unsigned int cond;
+	int err = 0;
+
+
+	ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
+	if (err) {
+		fpuemuprivate.stats.errors++;
+		return SIGBUS;
+	}
+
+	/* XXX NEC Vr54xx bug workaround */
+	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
+		xcp->cp0_cause &= ~CAUSEF_BD;
+
+	if (xcp->cp0_cause & CAUSEF_BD) {
+		/*
+		 * The instruction to be emulated is in a branch delay slot
+		 * which means that we have to  emulate the branch instruction
+		 * BEFORE we do the cop1 instruction. 
+		 *
+		 * This branch could be a COP1 branch, but in that case we
+		 * would have had a trap for that instruction, and would not
+		 * come through this route.
+		 *
+		 * Linux MIPS branch emulator operates on context, updating the
+		 * cp0_epc.
+		 */
+		emulpc = REG_TO_VA(xcp->cp0_epc + 4);	/* Snapshot emulation target */
+
+		if (__compute_return_epc(xcp)) {
+#ifdef CP1DBG
+			printk("failed to emulate branch at %p\n",
+				    REG_TO_VA(xcp->cp0_epc));
+#endif
+			return SIGILL;;
+		}
+		ir = mips_get_word(xcp, emulpc, &err);
+		if (err) {
+			fpuemuprivate.stats.errors++;
+			return SIGBUS;
+		}
+		contpc = REG_TO_VA xcp->cp0_epc;
+	} else {
+		emulpc = REG_TO_VA xcp->cp0_epc;
+		contpc = REG_TO_VA xcp->cp0_epc + 4;
+	}
+
+      emul:
+	fpuemuprivate.stats.emulated++;
+	switch (MIPSInst_OPCODE(ir)) {
+#ifdef CP0_STATUS_FR_SUPPORT
+		/* R4000+ 64-bit fpu registers */
+#ifndef SINGLE_ONLY_FPU
+	case ldc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			int ft = MIPSInst_RT(ir);
+			if (!(xcp->cp0_status & ST0_FR))
+				ft &= ~1;
+			ctx->regs[ft] = mips_get_dword(xcp, va, &err);
+			fpuemuprivate.stats.loads++;
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+
+	case sdc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			int ft = MIPSInst_RT(ir);
+			if (!(xcp->cp0_status & ST0_FR))
+				ft &= ~1;
+			fpuemuprivate.stats.stores++;
+			if (mips_put_dword(xcp, va, ctx->regs[ft])) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+#endif
+
+	case lwc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			fpureg_t val;
+			int ft = MIPSInst_RT(ir);
+			fpuemuprivate.stats.loads++;
+			val = mips_get_word(xcp, va, &err);
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+			if (xcp->cp0_status & ST0_FR) {
+				/* load whole register */
+				ctx->regs[ft] = val;
+			} else if (ft & 1) {
+				/* load to m.s. 32 bits */
+#ifdef SINGLE_ONLY_FPU
+				/* illegal register in single-float mode */
+				return SIGILL;
+#else
+				ctx->regs[(ft & ~1)] &= 0xffffffff;
+				ctx->regs[(ft & ~1)] |= val << 32;
+#endif
+			} else {
+				/* load to l.s. 32 bits */
+				ctx->regs[ft] &= ~0xffffffffLL;
+				ctx->regs[ft] |= val;
+			}
+		}
+		break;
+
+	case swc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int val;
+			int ft = MIPSInst_RT(ir);
+			fpuemuprivate.stats.stores++;
+			if (xcp->cp0_status & ST0_FR) {
+				/* store whole register */
+				val = ctx->regs[ft];
+			} else if (ft & 1) {
+#ifdef SINGLE_ONLY_FPU
+				/* illegal register in single-float mode */
+				return SIGILL;
+#else
+				/* store from m.s. 32 bits */
+				val = ctx->regs[(ft & ~1)] >> 32;
+#endif
+			} else {
+				/* store from l.s. 32 bits */
+				val = ctx->regs[ft];
+			}
+			if (mips_put_word(xcp, va, val)) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+#else				/* old 32-bit fpu registers */
+	case lwc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			ctx->regs[MIPSInst_RT(ir)] =
+			    mips_get_word(xcp, va, &err);
+			fpuemuprivate.stats.loads++;
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+
+	case swc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			fpuemuprivate.stats.stores++;
+			if (mips_put_word
+			    (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+	case ldc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int rt = MIPSInst_RT(ir) & ~1;
+			int errs = 0;
+			fpuemuprivate.stats.loads++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+			ctx->regs[rt + 1] =
+			    mips_get_word(xcp, va + 0, &err);
+			errs += err;
+			ctx->regs[rt + 0] =
+			    mips_get_word(xcp, va + 4, &err);
+			errs += err;
+#else
+			ctx->regs[rt + 0] =
+			    mips_get_word(xcp, va + 0, &err);
+			errs += err;
+			ctx->regs[rt + 1] =
+			    mips_get_word(xcp, va + 4, &err);
+			errs += err;
+#endif
+			if (err)
+				return SIGBUS;
+		}
+		break;
+
+	case sdc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int rt = MIPSInst_RT(ir) & ~1;
+			fpuemuprivate.stats.stores++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
+				return SIGBUS;
+			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
+				return SIGBUS;
+#else
+			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
+				return SIGBUS;
+			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
+				return SIGBUS;
+#endif
+		}
+		break;
+#endif
+
+	case cop1_op:
+		switch (MIPSInst_RS(ir)) {
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case dmfc_op:
+			/* copregister fs -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				int fs = MIPSInst_RD(ir);
+				if (!(xcp->cp0_status & ST0_FR))
+					fs &= ~1;
+				xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
+			}
+			break;
+
+		case dmtc_op:
+			/* copregister fs <- rt */
+			{
+				fpureg_t value;
+				int fs = MIPSInst_RD(ir);
+				if (!(xcp->cp0_status & ST0_FR))
+					fs &= ~1;
+				value =
+				    (MIPSInst_RT(ir) ==
+				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+				ctx->regs[fs] = value;
+			}
+			break;
+#endif
+
+		case mfc_op:
+			/* copregister rd -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				/* default value from l.s. 32 bits */
+				int value = ctx->regs[MIPSInst_RD(ir)];
+				if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+					/* illegal register in single-float mode */
+					return SIGILL;
+#else
+					if (!(xcp->cp0_status & ST0_FR)) {
+						/* move from m.s. 32 bits */
+						value =
+						    ctx->
+						    regs[MIPSInst_RD(ir) &
+							 ~1] >> 32;
+					}
+#endif
+				}
+				xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case mtc_op:
+			/* copregister rd <- rt */
+			{
+				fpureg_t value;
+				if (MIPSInst_RT(ir) == 0)
+					value = 0;
+				else
+					value =
+					    (unsigned int) xcp->
+					    regs[MIPSInst_RT(ir)];
+				if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+					/* illegal register in single-float mode */
+					return SIGILL;
+#else
+					if (!(xcp->cp0_status & ST0_FR)) {
+						/* move to m.s. 32 bits */
+						ctx->
+						    regs[
+							 (MIPSInst_RD(ir) &
+							  ~1)] &=
+						    0xffffffff;
+						ctx->
+						    regs[
+							 (MIPSInst_RD(ir) &
+							  ~1)] |=
+						    value << 32;
+						break;
+					}
+#endif
+				}
+				/* move to l.s. 32 bits */
+				ctx->regs[MIPSInst_RD(ir)] &=
+				    ~0xffffffffLL;
+				ctx->regs[MIPSInst_RD(ir)] |= value;
+			}
+			break;
+#else
+
+		case mfc_op:
+			/* copregister rd -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				unsigned value =
+				    ctx->regs[MIPSInst_RD(ir)];
+				xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case mtc_op:
+			/* copregister rd <- rt */
+			{
+				unsigned value;
+				value =
+				    (MIPSInst_RT(ir) ==
+				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+				ctx->regs[MIPSInst_RD(ir)] = value;
+			}
+			break;
+#endif
+
+		case cfc_op:
+			/* cop control register rd -> gpr[rt] */
+			{
+				unsigned value;
+
+				if (MIPSInst_RD(ir) == FPCREG_CSR) {
+					value = ctx->sr;
+#ifdef CSRTRACE
+					printk
+					    ("%p gpr[%d]<-csr=%08x\n",
+					     REG_TO_VA(xcp->cp0_epc),
+					     MIPSInst_RT(ir), value);
+#endif
+				} else if (MIPSInst_RD(ir) == FPCREG_RID)
+					value = 0;
+				else
+					value = 0;
+				if (MIPSInst_RT(ir))
+					xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case ctc_op:
+			/* copregister rd <- rt */
+			{
+				unsigned value;
+
+				if (MIPSInst_RT(ir) == 0)
+					value = 0;
+				else
+					value = xcp->regs[MIPSInst_RT(ir)];
+
+				/* we only have one writable control reg
+				 */
+				if (MIPSInst_RD(ir) == FPCREG_CSR) {
+#ifdef CSRTRACE
+					printk
+					    ("%p gpr[%d]->csr=%08x\n",
+					     REG_TO_VA(xcp->cp0_epc),
+					     MIPSInst_RT(ir), value);
+#endif
+					ctx->sr = value;
+					/* copy new rounding mode to ieee library state! */
+					ieee754_csr.rm =
+					    ieee_rm[value & 0x3];
+				}
+			}
+			break;
+
+		case bc_op:
+			if (xcp->cp0_cause & CAUSEF_BD) {
+				return SIGILL;
+			}
+			{
+				int likely = 0;
+
+#if __mips >= 4
+				cond =
+				    ctx->
+				    sr & fpucondbit[MIPSInst_RT(ir) >> 2];
+#else
+				cond = ctx->sr & FPU_CSR_COND;
+#endif
+				switch (MIPSInst_RT(ir) & 3) {
+				case bcfl_op:
+					likely = 1;
+				case bcf_op:
+					cond = !cond;
+					break;
+				case bctl_op:
+					likely = 1;
+				case bct_op:
+					break;
+				default:
+					/* thats an illegal instruction */
+					return SIGILL;
+				}
+
+				xcp->cp0_cause |= CAUSEF_BD;
+				if (cond) {
+					/* branch taken: emulate dslot instruction */
+					xcp->cp0_epc += 4;
+					contpc =
+					    REG_TO_VA xcp->cp0_epc +
+					    (MIPSInst_SIMM(ir) << 2);
+
+					ir =
+					    mips_get_word(xcp,
+							  REG_TO_VA(xcp->
+								    cp0_epc),
+							  &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+
+					switch (MIPSInst_OPCODE(ir)) {
+					case lwc1_op:
+					case swc1_op:
+#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+					case ldc1_op:
+					case sdc1_op:
+#endif
+					case cop1_op:
+#if __mips >= 4 && __mips != 32
+					case cop1x_op:
+#endif
+						/* its one of ours */
+						goto emul;
+#if __mips >= 4
+					case spec_op:
+						if (MIPSInst_FUNC(ir) ==
+						    movc_op) goto emul;
+						break;
+#endif
+					}
+
+					/* single step the non-cp1 instruction in the dslot */
+					return mips_dsemul(xcp, ir, contpc);
+				} else {
+					/* branch not taken */
+					if (likely)
+						/* branch likely nullifies dslot if not taken */
+						xcp->cp0_epc += 4;
+					/* else continue & execute dslot as normal insn */
+				}
+			}
+			break;
+
+		default:
+			if (!(MIPSInst_RS(ir) & 0x10)) {
+				return SIGILL;
+			}
+			/* a real fpu computation instruction */
+			{
+				int sig;
+				if ((sig = fpu_emu(xcp, ctx, ir)))
+					return sig;
+			}
+		}
+		break;
+
+#if __mips >= 4 && __mips != 32
+	case cop1x_op:
+		{
+			int sig;
+			if ((sig = fpux_emu(xcp, ctx, ir)))
+				return sig;
+		}
+		break;
+#endif
+
+#if __mips >= 4
+	case spec_op:
+		if (MIPSInst_FUNC(ir) != movc_op)
+			return SIGILL;
+		cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+		if (((ctx->sr & cond) != 0) !=
+		    ((MIPSInst_RT(ir) & 1) != 0)) return 0;
+		xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+		break;
+#endif
+
+	default:
+		return SIGILL;
+	}
+
+	/* we did it !! */
+	xcp->cp0_epc = VA_TO_REG(contpc);
+	xcp->cp0_cause &= ~CAUSEF_BD;
+	return 0;
+}
+
+/*
+ * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
+ * we have to emulate the instruction in a COP1 branch delay slot.  Do
+ * not change cp0_epc due to the instruction
+ *
+ * According to the spec:
+ * 1) it shouldnt be a branch :-)
+ * 2) it can be a COP instruction :-(
+ * 3) if we are tring to run a protected memory space we must take
+ *    special care on memory access instructions :-(
+ */
+
+/*
+ * "Trampoline" return routine to catch exception following
+ *  execution of delay-slot instruction execution.
+ */
+
+int do_dsemulret(struct pt_regs *xcp)
+{
+#ifdef DSEMUL_TRACE
+	printk("desemulret\n");
+#endif
+	/* Set EPC to return to post-branch instruction */
+	xcp->cp0_epc = current->thread.dsemul_epc;
+	/*
+	 * Clear the state that got us here.
+	 */
+	current->thread.dsemul_aerpc = (unsigned long) 0;
+
+	return 0;
+}
+
+
+#define AdELOAD 0x8c000001	/* lw $0,1($0) */
+
+static int
+mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
+{
+	mips_instruction *dsemul_insns;
+	mips_instruction forcetrap;
+	extern asmlinkage void handle_dsemulret(void);
+
+	if (ir == 0) {		/* a nop is easy */
+		xcp->cp0_epc = VA_TO_REG(cpc);
+		return 0;
+	}
+#ifdef DSEMUL_TRACE
+	printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc);
+#endif
+
+	/* 
+	 * The strategy is to push the instruction onto the user stack 
+	 * and put a trap after it which we can catch and jump to 
+	 * the required address any alternative apart from full 
+	 * instruction emulation!!.
+	 */
+	dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
+	dsemul_insns -= 3;	/* Two instructions, plus one for luck ;-) */
+	/* Verify that the stack pointer is not competely insane */
+	if (verify_area
+	    (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2))
+		return SIGBUS;
+
+	if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
+		fpuemuprivate.stats.errors++;
+		return (SIGBUS);
+	}
+
+	/* 
+	 * Algorithmics used a system call instruction, and
+	 * borrowed that vector.  MIPS/Linux version is a bit
+	 * more heavyweight in the interests of portability and
+	 * multiprocessor support.  We flag the thread for special
+	 * handling in the unaligned access handler and force an
+	 * address error excpetion.
+	 */
+
+	/* If one is *really* paranoid, one tests for a bad stack pointer */
+	if ((xcp->regs[29] & 0x3) == 0x3)
+		forcetrap = AdELOAD - 1;
+	else
+		forcetrap = AdELOAD;
+
+	if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
+		fpuemuprivate.stats.errors++;
+		return (SIGBUS);
+	}
+
+	/* Set thread state to catch and handle the exception */
+	current->thread.dsemul_epc = (unsigned long) cpc;
+	current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
+	xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
+
+	/* What we'd really like to do is just flush the line(s) of the */
+	/* icache containing the dsemulret instructions, but there's no */
+	/* mechanism to do this yet...  */
+	flush_cache_all();
+	return SIGILL;		/* force out of emulation loop */
+}
+
+/* 
+ * Conversion table from MIPS compare ops 48-63
+ * cond = ieee754dp_cmp(x,y,IEEE754_UN);
+ */
+static const unsigned char cmptab[8] = {
+	0,					/* cmp_0 (sig) cmp_sf */
+	IEEE754_CUN,				/* cmp_un (sig) cmp_ngle */
+	IEEE754_CEQ,				/* cmp_eq (sig) cmp_seq */
+	IEEE754_CEQ | IEEE754_CUN,		/* cmp_ueq (sig) cmp_ngl  */
+	IEEE754_CLT,				/* cmp_olt (sig) cmp_lt */
+	IEEE754_CLT | IEEE754_CUN,		/* cmp_ult (sig) cmp_nge */
+	IEEE754_CLT | IEEE754_CEQ,		/* cmp_ole (sig) cmp_le */
+	IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
+};
+
+#define SIFROMREG(si,x)	((si) = ctx->regs[x])
+#define SITOREG(si,x)	(ctx->regs[x] = (int)(si))
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#define DIFROMREG(di,x)	((di) = ctx->regs[x])
+#define DITOREG(di,x)	(ctx->regs[x] = (di))
+#endif
+
+#define SPFROMREG(sp,x)	((sp).bits = ctx->regs[x])
+#define SPTOREG(sp,x)	(ctx->regs[x] = (sp).bits)
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#define DPFROMREG(dp,x)	((dp).bits = \
+			ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
+#define DPTOREG(dp,x)	(ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\
+			= (dp).bits)
+#else
+/* Beware: MIPS COP1 doubles are always little_word endian in registers */
+#define DPFROMREG(dp,x)	\
+  ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
+#define DPTOREG(dp,x) \
+  (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
+#endif
+
+#if __mips >= 4 && __mips != 32
+
+/*
+ * Additional MIPS4 instructions
+ */
+
+static ieee754dp fpemu_dp_recip(ieee754dp d)
+{
+	return ieee754dp_div(ieee754dp_one(0), d);
+}
+
+static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+{
+	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
+}
+
+static ieee754sp fpemu_sp_recip(ieee754sp s)
+{
+	return ieee754sp_div(ieee754sp_one(0), s);
+}
+
+static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+{
+	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
+}
+
+
+static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_add(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_sub(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
+}
+
+static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
+}
+
+
+static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_add(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_sub(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
+}
+
+static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
+}
+
+static int
+fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+	 mips_instruction ir)
+{
+	unsigned rcsr = 0;	/* resulting csr */
+
+	fpuemuprivate.stats.cp1xops++;
+
+	switch (MIPSInst_FMA_FFMT(ir)) {
+	case s_fmt:		/* 0 */
+		{
+			ieee754sp(*handler) (ieee754sp, ieee754sp,
+					     ieee754sp);
+			ieee754sp fd, fr, fs, ft;
+
+			switch (MIPSInst_FUNC(ir)) {
+			case lwxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					fpureg_t val;
+					int err = 0;
+					val = mips_get_word(xcp, va, &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+					if (xcp->cp0_status & ST0_FR) {
+						/* load whole register */
+						ctx->
+						    regs[MIPSInst_FD(ir)] =
+						    val;
+					} else if (MIPSInst_FD(ir) & 1) {
+						/* load to m.s. 32 bits */
+#if defined(SINGLE_ONLY_FPU)
+						/* illegal register in single-float mode */
+						return SIGILL;
+#else
+						ctx->
+						    regs[
+							 (MIPSInst_FD(ir) &
+							  ~1)] &=
+						    0xffffffff;
+						ctx->
+						    regs[
+							 (MIPSInst_FD(ir) &
+							  ~1)] |=
+						    val << 32;
+#endif
+					} else {
+						/* load to l.s. 32 bits */
+						ctx->
+						    regs[MIPSInst_FD(ir)]
+						    &= ~0xffffffffLL;
+						ctx->
+						    regs[MIPSInst_FD(ir)]
+						    |= val;
+					}
+				}
+				break;
+
+			case swxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					unsigned int val;
+					if (xcp->cp0_status & ST0_FR) {
+						/* store whole register */
+						val =
+						    ctx->
+						    regs[MIPSInst_FS(ir)];
+					} else if (MIPSInst_FS(ir) & 1) {
+#if defined(SINGLE_ONLY_FPU)
+						/* illegal register in single-float mode */
+						return SIGILL;
+#else
+						/* store from m.s. 32 bits */
+						val =
+						    ctx->
+						    regs[
+							 (MIPSInst_FS(ir) &
+							  ~1)] >> 32;
+#endif
+					} else {
+						/* store from l.s. 32 bits */
+						val =
+						    ctx->
+						    regs[MIPSInst_FS(ir)];
+					}
+					if (mips_put_word(xcp, va, val)) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case madd_s_op:
+				handler = fpemu_sp_madd;
+				goto scoptop;
+			case msub_s_op:
+				handler = fpemu_sp_msub;
+				goto scoptop;
+			case nmadd_s_op:
+				handler = fpemu_sp_nmadd;
+				goto scoptop;
+			case nmsub_s_op:
+				handler = fpemu_sp_nmsub;
+				goto scoptop;
+
+			      scoptop:
+				SPFROMREG(fr, MIPSInst_FR(ir));
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+				fd = (*handler) (fr, fs, ft);
+				SPTOREG(fd, MIPSInst_FD(ir));
+
+			      copcsr:
+				if (ieee754_cxtest(IEEE754_INEXACT))
+					rcsr |=
+					    FPU_CSR_INE_X | FPU_CSR_INE_S;
+				if (ieee754_cxtest(IEEE754_UNDERFLOW))
+					rcsr |=
+					    FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+				if (ieee754_cxtest(IEEE754_OVERFLOW))
+					rcsr |=
+					    FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+				if (ieee754_cxtest
+				    (IEEE754_INVALID_OPERATION)) rcsr |=
+					    FPU_CSR_INV_X | FPU_CSR_INV_S;
+
+				ctx->sr =
+				    (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+				if ((ctx->sr >> 5) & ctx->
+				    sr & FPU_CSR_ALL_E) {
+		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+					return SIGFPE;
+				}
+
+				break;
+
+			default:
+				return SIGILL;
+			}
+		}
+		break;
+
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt:		/* 1 */
+		{
+			ieee754dp(*handler) (ieee754dp, ieee754dp,
+					     ieee754dp);
+			ieee754dp fd, fr, fs, ft;
+
+			switch (MIPSInst_FUNC(ir)) {
+			case ldxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					int err = 0;
+					ctx->regs[MIPSInst_FD(ir)] =
+					    mips_get_dword(xcp, va, &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case sdxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					if (mips_put_dword
+					    (xcp, va,
+					     ctx->regs[MIPSInst_FS(ir)])) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case madd_d_op:
+				handler = fpemu_dp_madd;
+				goto dcoptop;
+			case msub_d_op:
+				handler = fpemu_dp_msub;
+				goto dcoptop;
+			case nmadd_d_op:
+				handler = fpemu_dp_nmadd;
+				goto dcoptop;
+			case nmsub_d_op:
+				handler = fpemu_dp_nmsub;
+				goto dcoptop;
+
+			      dcoptop:
+				DPFROMREG(fr, MIPSInst_FR(ir));
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+				fd = (*handler) (fr, fs, ft);
+				DPTOREG(fd, MIPSInst_FD(ir));
+				goto copcsr;
+
+			default:
+				return SIGILL;
+			}
+		}
+		break;
+#endif
+
+	case 0x7:		/* 7 */
+		{
+			if (MIPSInst_FUNC(ir) != pfetch_op) {
+				return SIGILL;
+			}
+			/* ignore prefx operation */
+		}
+		break;
+
+	default:
+		return SIGILL;
+	}
+
+	return 0;
+}
+#endif
+
+
+
+/*
+ * Emulate a single COP1 arithmetic instruction.
+ */
+static int
+fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+	mips_instruction ir)
+{
+	int rfmt;		/* resulting format */
+	unsigned rcsr = 0;	/* resulting csr */
+	unsigned cond;
+	union {
+		ieee754dp d;
+		ieee754sp s;
+		int w;
+#if __mips64
+		long long l;
+#endif
+	} rv;			/* resulting value */
+
+	fpuemuprivate.stats.cp1ops++;
+	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+
+	case s_fmt:{		/* 0 */
+		ieee754sp(*handler) ();
+
+		switch (MIPSInst_FUNC(ir)) {
+			/* binary ops */
+		case fadd_op:
+			handler = ieee754sp_add;
+			goto scopbop;
+		case fsub_op:
+			handler = ieee754sp_sub;
+			goto scopbop;
+		case fmul_op:
+			handler = ieee754sp_mul;
+			goto scopbop;
+		case fdiv_op:
+			handler = ieee754sp_div;
+			goto scopbop;
+
+			/* unary  ops */
+#if __mips >= 2 || __mips64
+		case fsqrt_op:
+			handler = ieee754sp_sqrt;
+			goto scopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+		case frsqrt_op:
+			handler = fpemu_sp_rsqrt;
+			goto scopuop;
+		case frecip_op:
+			handler = fpemu_sp_recip;
+			goto scopuop;
+#endif
+#if __mips >= 4
+		case fmovc_op:
+			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+			if (((ctx->sr & cond) != 0) !=
+			    ((MIPSInst_FT(ir) & 1) != 0))
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+		case fmovz_op:
+			if (xcp->regs[MIPSInst_FT(ir)] != 0)
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+		case fmovn_op:
+			if (xcp->regs[MIPSInst_FT(ir)] == 0)
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+#endif
+		case fabs_op:
+			handler = ieee754sp_abs;
+			goto scopuop;
+		case fneg_op:
+			handler = ieee754sp_neg;
+			goto scopuop;
+		case fmov_op:
+			/* an easy one */
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+			/* binary op on handler */
+scopbop:
+			{
+				ieee754sp fs, ft;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+
+				rv.s = (*handler) (fs, ft);
+				goto copcsr;
+			}
+scopuop:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.s = (*handler) (fs);
+				goto copcsr;
+			}
+copcsr:
+			if (ieee754_cxtest(IEEE754_INEXACT))
+				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+			if (ieee754_cxtest(IEEE754_UNDERFLOW))
+				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+			if (ieee754_cxtest(IEEE754_OVERFLOW))
+				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
+			if (ieee754_cxtest
+				(IEEE754_INVALID_OPERATION)) rcsr |=
+					    FPU_CSR_INV_X | FPU_CSR_INV_S;
+				break;
+
+				/* unary conv ops */
+		case fcvts_op:
+			return SIGILL;	/* not defined */
+		case fcvtd_op:
+#if defined(SINGLE_ONLY_FPU)
+			return SIGILL;	/* not defined */
+#else
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.d = ieee754dp_fsp(fs);
+				rfmt = d_fmt;
+				goto copcsr;
+			}
+#endif
+		case fcvtw_op:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.w = ieee754sp_tint(fs);
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+
+#if __mips >= 2 || __mips64
+		case fround_op:
+		case ftrunc_op:
+		case fceil_op:
+		case ffloor_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.w = ieee754sp_tint(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+#endif			/* __mips >= 2 */
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case fcvtl_op:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.l = ieee754sp_tlong(fs);
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+
+		case froundl_op:
+		case ftruncl_op:
+		case fceill_op:
+		case ffloorl_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.l = ieee754sp_tlong(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+#endif /* __mips64 && !fpu(single) */
+
+		default:
+			if (MIPSInst_FUNC(ir) >= fcmp_op) {
+				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+				ieee754sp fs, ft;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+				rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+				rfmt = -1;
+				if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
+					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+				} else {
+					return SIGILL;
+				}
+				break;
+			}
+			break;
+		}
+
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt: {
+		ieee754dp(*handler) ();
+
+		switch (MIPSInst_FUNC(ir)) {
+			/* binary ops */
+		case fadd_op:
+			handler = ieee754dp_add;
+			goto dcopbop;
+		case fsub_op:
+			handler = ieee754dp_sub;
+			goto dcopbop;
+		case fmul_op:
+			handler = ieee754dp_mul;
+			goto dcopbop;
+		case fdiv_op:
+			handler = ieee754dp_div;
+			goto dcopbop;
+
+			/* unary  ops */
+#if __mips >= 2 || __mips64
+		case fsqrt_op:
+			handler = ieee754dp_sqrt;
+			goto dcopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+		case frsqrt_op:
+			handler = fpemu_dp_rsqrt;
+			goto dcopuop;
+		case frecip_op:
+			handler = fpemu_dp_recip;
+			goto dcopuop;
+#endif
+#if __mips >= 4
+		case fmovc_op:
+			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+			if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+		case fmovz_op:
+			if (xcp->regs[MIPSInst_FT(ir)] != 0)
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+		case fmovn_op:
+			if (xcp->regs[MIPSInst_FT(ir)] == 0)
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+#endif
+		case fabs_op:
+			handler = ieee754dp_abs;
+			goto dcopuop;
+		case fneg_op:
+			handler = ieee754dp_neg;
+			goto dcopuop;
+		case fmov_op:
+			/* an easy one */
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+
+			/* binary op on handler */
+dcopbop:
+			{
+				ieee754dp fs, ft;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+
+				rv.d = (*handler) (fs, ft);
+				goto copcsr;
+			}
+dcopuop:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.d = (*handler) (fs);
+				goto copcsr;
+			}
+
+		/* unary conv ops */
+		case fcvts_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.s = ieee754sp_fdp(fs);
+				rfmt = s_fmt;
+				goto copcsr;
+			}
+		case fcvtd_op:
+			return SIGILL;	/* not defined */
+		case fcvtw_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.w = ieee754dp_tint(fs);	/* wrong */
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+
+#if __mips >= 2 || __mips64
+		case fround_op:
+		case ftrunc_op:
+		case fceil_op:
+		case ffloor_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.w = ieee754dp_tint(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+#endif
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case fcvtl_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.l = ieee754dp_tlong(fs);
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+
+		case froundl_op:
+		case ftruncl_op:
+		case fceill_op:
+		case ffloorl_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.l = ieee754dp_tlong(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+#endif /* __mips >= 3 && !fpu(single) */
+
+		default:
+			if (MIPSInst_FUNC(ir) >= fcmp_op) {
+				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+				ieee754dp fs, ft;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+				rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+				rfmt = -1;
+				if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
+					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+			} else {
+				return SIGILL;
+			}
+			break;
+		}
+		break;
+	}
+#endif				/* !defined(SINGLE_ONLY_FPU) */
+
+	case w_fmt: {
+		switch (MIPSInst_FUNC(ir)) {
+		case fcvts_op:
+			/* convert word to single precision real */
+			rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = s_fmt;
+			goto copcsr;
+#if !defined(SINGLE_ONLY_FPU)
+		case fcvtd_op:
+			/* convert word to double precision real */
+			rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = d_fmt;
+			goto copcsr;
+#endif
+		default:
+			return SIGILL;
+		}
+		break;
+	}
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+	case l_fmt: {
+		switch (MIPSInst_FUNC(ir)) {
+		case fcvts_op:
+			/* convert long to single precision real */
+			rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = s_fmt;
+			goto copcsr;
+		case fcvtd_op:
+			/* convert long to double precision real */
+			rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = d_fmt;
+			goto copcsr;
+		default:
+			return SIGILL;
+		}
+		break;
+	}
+#endif
+
+	default:
+		return SIGILL;
+	}
+
+	/*
+	 * Update the fpu CSR register for this operation.
+	 * If an exception is required, generate a tidy SIGFPE exception,
+	 * without updating the result register.
+	 * Note: cause exception bits do not accumulate, they are rewritten
+	 * for each op; only the flag/sticky bits accumulate.
+	 */
+	ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+	if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
+		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+		return SIGFPE;
+	}
+
+	/* 
+	 * Now we can safely write the result back to the register file.
+	 */
+	switch (rfmt) {
+	case -1: {
+#if __mips >= 4
+		cond = fpucondbit[MIPSInst_FD(ir) >> 2];
+#else
+		cond = FPU_CSR_COND;
+#endif
+		if (rv.w)
+			ctx->sr |= cond;
+		else
+			ctx->sr &= ~cond;
+		break;
+	}
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt:
+		DPTOREG(rv.d, MIPSInst_FD(ir));
+		break;
+#endif
+	case s_fmt:
+		SPTOREG(rv.s, MIPSInst_FD(ir));
+		break;
+	case w_fmt:
+		SITOREG(rv.w, MIPSInst_FD(ir));
+		break;
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+	case l_fmt:
+		DITOREG(rv.l, MIPSInst_FD(ir));
+		break;
+#endif
+	default:
+		return SIGILL;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Emulate the floating point instruction at EPC, and continue
+ * to run until we hit a non-fp instruction, or a backward
+ * branch.  This cuts down dramatically on the per instruction 
+ * exception overhead.
+ */
+int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp)
+{
+	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+	unsigned long oldepc, prevepc;
+	unsigned int insn;
+	int sig = 0;
+	int err = 0;
+
+	oldepc = xcp->cp0_epc;
+	do {
+		prevepc = xcp->cp0_epc;
+		insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
+		if (err) {
+			fpuemuprivate.stats.errors++;
+			return SIGBUS;
+		}
+		if (insn != 0)
+			sig = cop1Emulate(xcptno, xcp, ctx);
+		else
+			xcp->cp0_epc += 4;	/* skip nops */
+	} while (xcp->cp0_epc > prevepc && sig == 0);
+
+	/* SIGILL indicates a non-fpu instruction */
+	if (sig == SIGILL && xcp->cp0_epc != oldepc)
+		/* but if epc has advanced, then ignore it */
+		sig = 0;
+
+	return sig;
+}
+
+
+#ifdef NOTDEF
+/*
+ * Patch up the hardware fpu state when an f.p. exception occurs.  
+ */
+static int cop1Patcher(int xcptno, struct pt_regs *xcp)
+{
+	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+	unsigned sr;
+	int sig;
+
+	/* reenable Cp1, else fpe_save() will get nested exception */
+	sr = mips_bissr(ST0_CU1);
+
+	/* get fpu registers and status, then clear pending exceptions */
+	fpe_save(ctx);
+	fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
+
+	/* get current rounding mode for IEEE library, and emulate insn */
+	ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
+	sig = cop1Emulate(xcptno, xcp, ctx);
+
+	/* don't return with f.p. exceptions pending */
+	ctx->sr &= ~FPU_CSR_ALL_X;
+	fpe_restore(ctx);
+
+	mips_setsr(sr);
+	return sig;
+}
+
+void _cop1_init(int emulate)
+{
+	extern int _nofpu;
+
+	if (emulate) {
+		/* 
+		 * Install cop1 emulator to handle "coprocessor unusable" exception
+		 */
+		xcption(XCPTCPU, cop1Handler);
+		fpuemuactive = 1;	/* tell dbg.c that we are in charge */
+		_nofpu = 0;	/* tell setjmp() it "has" an fpu */
+	} else {
+		/* 
+		 * Install cop1 emulator for floating point exceptions only,
+		 * i.e. denormalised results, underflow, overflow etc, which
+		 * must be emulated in s/w.
+		 */
+#ifdef 1
+		/* r4000 or above use dedicate exception */
+		xcption(XCPTFPE, cop1Patcher);
+#else
+		/* r3000 et al use interrupt */
+		extern int _sbd_getfpuintr(void);
+		int intno = _sbd_getfpuintr();
+		intrupt(intno, cop1Patcher, 0);
+		mips_bissr(SR_IM0 << intno);
+#endif
+
+#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
+		/* For R4640/R4650 compiled *without* the -msingle-float flag,
+		   then we share responsibility: the h/w handles the single
+		   precision operations, and the trap emulator handles the
+		   double precision. We set fpuemuactive so that dbg.c first
+		   fetches the s/w state before saving the h/w state. */
+		fpuemuactive = 1;
+		{
+			int i;
+			/* initialise the unused d.p high order words to be NaN */
+			for (i = 0; i < 32; i++)
+				current->thread.fpu.soft.regs[i] =
+				    0x7ff80bad00000000LL;
+		}
+#endif				/* (r4640 || r4650) && !fpu(single) */
+	}
+}
+#endif
+
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_add.c linux/arch/mips64/math-emu/dp_add.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_add.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_add.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,186 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	CLEARCX;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs == ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs == ys)
+			return x;
+		else
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+		/* FALL THROUGH */
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		ym = XDPSRS(ym, s);
+		ye += s;
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		xm = XDPSRS(xm, s);
+		xe += s;
+	}
+	assert(xe == ye);
+	assert(xe <= DP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 * leaving result in xm,xs,xe
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (DP_MBITS + 1 + 3)) {	/* carry out */
+			xm = XDPSRS1(xm);
+			xe++;
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+		/* normalize to rounding precision */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+
+	}
+	DPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_cmp.c linux/arch/mips64/math-emu/dp_cmp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_cmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_cmp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+		if (cmp & IEEE754_CUN)
+			return 1;
+		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+			if (SETCX(IEEE754_INVALID_OPERATION))
+				return ieee754si_xcpt(0, "fcmpf", x);
+		}
+		return 0;
+	} else {
+		long long int vx = x.bits;
+		long long int vy = y.bits;
+
+		if (vx < 0)
+			vx = -vx ^ DP_SIGN_BIT;
+		if (vy < 0)
+			vy = -vy ^ DP_SIGN_BIT;
+
+		if (vx < vy)
+			return (cmp & IEEE754_CLT) != 0;
+		else if (vx == vy)
+			return (cmp & IEEE754_CEQ) != 0;
+		else
+			return (cmp & IEEE754_CGT) != 0;
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_div.c linux/arch/mips64/math-emu/dp_div.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_div.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_div.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return ieee754dp_zero(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return ieee754dp_inf(xs ^ ys);
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_ZERO_DIVIDE);
+		return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return ieee754dp_zero(xs == ys ? 0 : 1);
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+	/* provide rounding space */
+	xm <<= 3;
+	ym <<= 3;
+
+	{
+		/* now the dirty work */
+
+		unsigned long long rm = 0;
+		int re = xe - ye;
+		unsigned long long bm;
+
+		for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
+			if (xm >= ym) {
+				xm -= ym;
+				rm |= bm;
+				if (xm == 0)
+					break;
+			}
+			xm <<= 1;
+		}
+		rm <<= 1;
+		if (xm)
+			rm |= 1;	/* have remainder, set sticky */
+
+		assert(rm);
+
+		/* normalise rm to rounding precision ?
+		 */
+		while ((rm >> (DP_MBITS + 3)) == 0) {
+			rm <<= 1;
+			re--;
+		}
+
+		DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_fint.c linux/arch/mips64/math-emu/dp_fint.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_fint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_fint.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fint(int x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754dp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754dp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754dp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1 << 31))
+			xm = ((unsigned) 1 << 31);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+
+#if 1
+	/* normalize - result can never be inexact or overflow */
+	xe = DP_MBITS;
+	while ((xm >> DP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+#else
+	/* normalize */
+	xe = DP_MBITS + 3;
+	while ((xm >> (DP_MBITS + 3)) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	DPNORMRET1(xs, xe, xm, "fint", x);
+#endif
+}
+
+ieee754dp ieee754dp_funs(unsigned int u)
+{
+	if ((int) u < 0)
+		return ieee754dp_add(ieee754dp_1e31(),
+				     ieee754dp_fint(u & ~(1 << 31)));
+	return ieee754dp_fint(u);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_flong.c linux/arch/mips64/math-emu/dp_flong.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_flong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_flong.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,76 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_flong(long long x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754dp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754dp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754dp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1ULL << 63))
+			xm = (1ULL << 63);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+
+	/* normalize */
+	xe = DP_MBITS + 3;
+	if (xm >> (DP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits */
+		while (xm >> (DP_MBITS + 1 + 3)) {
+			XDPSRSX1();
+		}
+	} else {
+		/* normalize in grs extended double precision */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	DPNORMRET1(xs, xe, xm, "dp_flong", x);
+}
+
+ieee754dp ieee754dp_fulong(unsigned long long u)
+{
+	if ((long long) u < 0)
+		return ieee754dp_add(ieee754dp_1e63(),
+				     ieee754dp_flong(u & ~(1ULL << 63)));
+	return ieee754dp_flong(u);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_frexp.c linux/arch/mips64/math-emu/dp_frexp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_frexp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_frexp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* close to ieeep754dp_logb 
+*/
+ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+{
+	COMPXDP;
+	CLEARCX;
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*eptr = 0;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	*eptr = xe + 1;
+	return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_fsp.c linux/arch/mips64/math-emu/dp_fsp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_fsp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_fsp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,70 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fsp(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(builddp(xs,
+						 DP_EMAX + 1 + DP_EBIAS,
+						 ((unsigned long long) xm
+						  << (DP_MBITS -
+						      SP_MBITS))), "fsp",
+					 x);
+	case IEEE754_CLASS_INF:
+		return ieee754dp_inf(xs);
+	case IEEE754_CLASS_ZERO:
+		return ieee754dp_zero(xs);
+	case IEEE754_CLASS_DNORM:
+		/* normalize */
+		while ((xm >> SP_MBITS) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+
+	/* CANT possibly overflow,underflow, or need rounding
+	 */
+
+	/* drop the hidden bit */
+	xm &= ~SP_HIDDEN_BIT;
+
+	return builddp(xs, xe + DP_EBIAS,
+		       (unsigned long long) xm << (DP_MBITS - SP_MBITS));
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_logb.c linux/arch/mips64/math-emu/dp_logb.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_logb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_logb.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_logb(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x, "logb", x);
+	case IEEE754_CLASS_QNAN:
+		return x;
+	case IEEE754_CLASS_INF:
+		return ieee754dp_inf(0);
+	case IEEE754_CLASS_ZERO:
+		return ieee754dp_inf(1);
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	return ieee754dp_fint(xe);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_modf.c linux/arch/mips64/math-emu/dp_modf.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_modf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_modf.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*ip = x;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		/* far to small */
+		*ip = ieee754dp_zero(xs);
+		return x;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe < 0) {
+		*ip = ieee754dp_zero(xs);
+		return x;
+	}
+	if (xe >= DP_MBITS) {
+		*ip = x;
+		return ieee754dp_zero(xs);
+	}
+	/* generate ipart mantissa by clearing bottom bits 
+	 */
+	*ip = builddp(xs, xe + DP_EBIAS,
+		      ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
+		      ~DP_HIDDEN_BIT);
+
+	/* generate fpart mantissa by clearing top bits
+	 * and normalizing (must be able to normalize)
+	 */
+	xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
+	if (xm == 0)
+		return ieee754dp_zero(xs);
+
+	while ((xm >> DP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_mul.c linux/arch/mips64/math-emu/dp_mul.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_mul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_mul.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		return ieee754dp_inf(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return ieee754dp_zero(xs ^ ys);
+
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* rm = xm * ym, re = xe+ye basicly */
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+	{
+		int re = xe + ye;
+		int rs = xs ^ ys;
+		unsigned long long rm;
+
+		/* shunt to top of word */
+		xm <<= 64 - (DP_MBITS + 1);
+		ym <<= 64 - (DP_MBITS + 1);
+
+		/* multiply 32bits xm,ym to give high 32bits rm with stickness
+		 */
+
+		/* 32 * 32 => 64 */
+#define DPXMULT(x,y)	((unsigned long long)(x) * (unsigned long long)y)
+
+		{
+			unsigned lxm = xm;
+			unsigned hxm = xm >> 32;
+			unsigned lym = ym;
+			unsigned hym = ym >> 32;
+			unsigned long long lrm;
+			unsigned long long hrm;
+
+			lrm = DPXMULT(lxm, lym);
+			hrm = DPXMULT(hxm, hym);
+
+			{
+				unsigned long long t = DPXMULT(lxm, hym);
+				{
+					unsigned long long at =
+					    lrm + (t << 32);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 32);
+			}
+
+			{
+				unsigned long long t = DPXMULT(hxm, lym);
+				{
+					unsigned long long at =
+					    lrm + (t << 32);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 32);
+			}
+			rm = hrm | (lrm != 0);
+		}
+
+		/*
+		 * sticky shift down to normal rounding precision
+		 */
+		if ((signed long long) rm < 0) {
+			rm =
+			    (rm >> (64 - (DP_MBITS + 1 + 3))) |
+			    ((rm << (DP_MBITS + 1 + 3)) != 0);
+			re++;
+		} else {
+			rm =
+			    (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
+			    ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
+		}
+		assert(rm & (DP_HIDDEN_BIT << 3));
+		DPNORMRET2(rs, re, rm, "mul", x, y);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_scalb.c linux/arch/mips64/math-emu/dp_scalb.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_scalb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_scalb.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x, "scalb", x, n);
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+{
+	return ieee754dp_scalb(x, n);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_simple.c linux/arch/mips64/math-emu/dp_simple.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_simple.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_finite(ieee754dp x)
+{
+	return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+{
+	CLEARCX;
+	DPSIGN(x) = DPSIGN(y);
+	return x;
+}
+
+
+ieee754dp ieee754dp_neg(ieee754dp x)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x))	/* but not infinity */
+		return ieee754dp_nanxcpt(x, "neg", x);
+
+	/* quick fix up */
+	DPSIGN(x) ^= 1;
+	return x;
+}
+
+
+ieee754dp ieee754dp_abs(ieee754dp x)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x))	/* but not infinity */
+		return ieee754dp_nanxcpt(x, "abs", x);
+
+	/* quick fix up */
+	DPSIGN(x) = 0;
+	return x;
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_sqrt.c linux/arch/mips64/math-emu/dp_sqrt.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_sqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_sqrt.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,167 @@
+/* IEEE754 floating point arithmetic
+ * double precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+static const struct ieee754dp_konst knan = {
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+	0, 0, DP_EBIAS + DP_EMAX + 1, 0
+#else
+	0, DP_EBIAS + DP_EMAX + 1, 0, 0
+#endif
+};
+
+#define nan	((ieee754dp)knan)
+
+static const unsigned table[] = {
+	0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
+	29598, 36145, 43202, 50740, 58733, 67158, 75992,
+	85215, 83599, 71378, 60428, 50647, 41945, 34246,
+	27478, 21581, 16499, 12183, 8588, 5674, 3403,
+	1742, 661, 130
+};
+
+ieee754dp ieee754dp_sqrt(ieee754dp x)
+{
+	struct ieee754_csr oldcsr;
+	ieee754dp y, z, t;
+	unsigned scalx, yh;
+	COMPXDP;
+
+	EXPLODEXDP;
+
+	/* x == INF or NAN? */
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		/* sqrt(Nan) = Nan */
+		return ieee754dp_nanxcpt(x, "sqrt");
+	case IEEE754_CLASS_ZERO:
+		/* sqrt(0) = 0 */
+		return x;
+	case IEEE754_CLASS_INF:
+		if (xs)
+			/* sqrt(-Inf) = Nan */
+			return ieee754dp_nanxcpt(nan, "sqrt");
+		/* sqrt(+Inf) = Inf */
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		/* fall through */
+	case IEEE754_CLASS_NORM:
+		if (xs)
+			/* sqrt(-x) = Nan */
+			return ieee754dp_nanxcpt(nan, "sqrt");
+		break;
+	}
+
+	/* save old csr; switch off INX enable & flag; set RN rounding */
+	oldcsr = ieee754_csr;
+	ieee754_csr.mx &= ~IEEE754_INEXACT;
+	ieee754_csr.sx &= ~IEEE754_INEXACT;
+	ieee754_csr.rm = IEEE754_RN;
+
+	/* adjust exponent to prevent overflow */
+	scalx = 0;
+	if (xe > 512) {		/* x > 2**-512? */
+		xe -= 512;	/* x = x / 2**512 */
+		scalx += 256;
+	} else if (xe < -512) {	/* x < 2**-512? */
+		xe += 512;	/* x = x * 2**512 */
+		scalx -= 256;
+	}
+
+	y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+
+	/* magic initial approximation to almost 8 sig. bits */
+	yh = y.bits >> 32;
+	yh = (yh >> 1) + 0x1ff80000;
+	yh = yh - table[(yh >> 15) & 31];
+	y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff);
+
+	/* Heron's rule once with correction to improve to ~18 sig. bits */
+	/* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
+	t = ieee754dp_div(x, y);
+	y = ieee754dp_add(y, t);
+	y.bits -= 0x0010000600000000LL;
+	y.bits &= 0xffffffff00000000LL;
+
+	/* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
+	/* t=y*y; z=t;  pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
+	z = t = ieee754dp_mul(y, y);
+	t.parts.bexp += 0x001;
+	t = ieee754dp_add(t, z);
+	z = ieee754dp_mul(ieee754dp_sub(x, z), y);
+
+	/* t=z/(t+x) ;  pt[n0]+=0x00100000; y+=t; */
+	t = ieee754dp_div(z, ieee754dp_add(t, x));
+	t.parts.bexp += 0x001;
+	y = ieee754dp_add(y, t);
+
+	/* twiddle last bit to force y correctly rounded */
+
+	/* set RZ, clear INEX flag */
+	ieee754_csr.rm = IEEE754_RZ;
+	ieee754_csr.sx &= ~IEEE754_INEXACT;
+
+	/* t=x/y; ...chopped quotient, possibly inexact */
+	t = ieee754dp_div(x, y);
+
+	if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
+
+		if (!(ieee754_csr.sx & IEEE754_INEXACT))
+			/* t = t-ulp */
+			t.bits -= 1;
+
+		/* add inexact to result status */
+		oldcsr.cx |= IEEE754_INEXACT;
+		oldcsr.sx |= IEEE754_INEXACT;
+
+		switch (oldcsr.rm) {
+		case IEEE754_RP:
+			y.bits += 1;
+			/* drop through */
+		case IEEE754_RN:
+			t.bits += 1;
+			break;
+		}
+
+		/* y=y+t; ...chopped sum */
+		y = ieee754dp_add(y, t);
+
+		/* adjust scalx for correctly rounded sqrt(x) */
+		scalx -= 1;
+	}
+
+	/* py[n0]=py[n0]+scalx; ...scale back y */
+	y.parts.bexp += scalx;
+
+	/* restore rounding mode, possibly set inexact */
+	ieee754_csr = oldcsr;
+
+	return y;
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_sub.c linux/arch/mips64/math-emu/dp_sub.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_sub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_sub.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,194 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs != ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+		return ieee754dp_inf(ys ^ 1);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs != ys)
+			return x;
+		else
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		/* quick fix up */
+		DPSIGN(y) ^= 1;
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+		/* FAAL THOROUGH */
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		/* normalize ym,ye */
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		/* normalize xm,xe */
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* flip sign of y and handle as add */
+	ys ^= 1;
+
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+
+	/* provide guard,round and stick bit dpace */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		ym = XDPSRS(ym, s);
+		ye += s;
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		xm = XDPSRS(xm, s);
+		xe += s;
+	}
+	assert(xe == ye);
+	assert(xe <= DP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (DP_MBITS + 1 + 3)) {	/* carry out */
+			xm = XDPSRS1(xm);	/* shift preserving sticky */
+			xe++;
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0) {
+			if (ieee754_csr.rm == IEEE754_RD)
+				return ieee754dp_zero(1);	/* round negative inf. => sign = -1 */
+			else
+				return ieee754dp_zero(0);	/* other round modes   => sign = 1 */
+		}
+
+		/* normalize to rounding precision 
+		 */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	DPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_tint.c linux/arch/mips64/math-emu/dp_tint.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_tint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_tint.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754dp.h"
+
+int ieee754dp_tint(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fixdp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 31) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fix", x);
+	}
+	/* oh gawd */
+	if (xe > DP_MBITS) {
+		xm <<= xe - DP_MBITS;
+	} else if (xe < DP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= DP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned int ieee754dp_tuns(ieee754dp x)
+{
+	ieee754dp hb = ieee754dp_1e31();
+
+	/* what if x < 0 ?? */
+	if (ieee754dp_lt(x, hb))
+		return (unsigned) ieee754dp_tint(x);
+
+	return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
+	    ((unsigned) 1 << 31);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/dp_tlong.c linux/arch/mips64/math-emu/dp_tlong.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/dp_tlong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_tlong.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,141 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+long long ieee754dp_tlong(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much too small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "dp_tlong", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 63) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	}
+	if (xe < 0) {
+		if (ieee754_csr.rm == IEEE754_RU) {
+			if (xs) {	/* Negative  */
+				return 0x0000000000000000LL;
+			} else {	/* Positive */
+				return 0x0000000000000001LL;
+			}
+		} else if (ieee754_csr.rm == IEEE754_RD) {
+			if (xs) {	/* Negative , return -1 */
+				return 0xffffffffffffffffLL;
+			} else {	/* Positive */
+				return 0x0000000000000000LL;
+			}
+		} else {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754di_xcpt(0, "dp_tlong", x);
+		}
+	}
+	/* oh gawd */
+	if (xe > DP_MBITS) {
+		xm <<= xe - DP_MBITS;
+	} else if (xe < DP_MBITS) {
+		unsigned long long residue;
+		unsigned long long mask = 0;
+		int i;
+		int round;
+		int sticky;
+		int odd;
+
+		/* compute mask */
+		for (i = 0; i < DP_MBITS - xe; i++) {
+			mask = mask << 1;
+			mask = mask | 0x1;
+		}
+		residue = (xm & mask) << (64 - (DP_MBITS - xe));
+		round =
+		    ((0x8000000000000000LL & residue) !=
+		     0x0000000000000000LL);
+		sticky =
+		    ((0x7fffffffffffffffLL & residue) !=
+		     0x0000000000000000LL);
+
+		xm >>= DP_MBITS - xe;
+
+		odd = ((xm & 0x1) != 0x0000000000000000LL);
+
+		/* Do the rounding */
+		if (!round && sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)) {
+				xm++;
+			}
+		} else if (round && !sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)
+			    || (ieee754_csr.rm == IEEE754_RN && odd)) {
+				xm++;
+			}
+		} else if (round && sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)
+			    || (ieee754_csr.rm == IEEE754_RN)) {
+				xm++;
+			}
+		}
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned long long ieee754dp_tulong(ieee754dp x)
+{
+	ieee754dp hb = ieee754dp_1e63();
+
+	/* what if x < 0 ?? */
+	if (ieee754dp_lt(x, hb))
+		return (unsigned long long) ieee754dp_tlong(x);
+
+	return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
+	    (1ULL << 63);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754.c linux/arch/mips64/math-emu/ieee754.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,138 @@
+/* ieee754 floating point arithmetic
+ * single and double precision
+ *
+ * BUGS
+ * not much dp done
+ * doesnt generate IEEE754_INEXACT
+ *
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+
+/* indexed by class */
+const char *const ieee754_cname[] = {
+	"Normal",
+	"Zero",
+	"Denormal",
+	"Infinity",
+	"QNaN",
+	"SNaN",
+};
+
+/* the control status register 
+*/
+struct ieee754_csr ieee754_csr;
+
+/* special constants
+*/
+
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#define SPSTR(s,b,m) {m,b,s}
+#define DPSTR(s,b,mh,ml) {ml,mh,b,s}
+#endif
+
+#ifdef __MIPSEB__
+#define SPSTR(s,b,m) {s,b,m}
+#define DPSTR(s,b,mh,ml) {s,b,mh,ml}
+#endif
+
+const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0),	/* + zero   */
+	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0),	/* - zero   */
+	DPSTR(0, DP_EBIAS, 0, 0),	/* + 1.0   */
+	DPSTR(1, DP_EBIAS, 0, 0),	/* - 1.0   */
+	DPSTR(0, 3 + DP_EBIAS, 0x40000, 0),	/* + 10.0   */
+	DPSTR(1, 3 + DP_EBIAS, 0x40000, 0),	/* - 10.0   */
+	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0),	/* + infinity */
+	DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0),	/* - infinity */
+	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0),	/* + indef quiet Nan */
+	DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* + max */
+	DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* - max */
+	DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0),	/* + min normal */
+	DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0),	/* - min normal */
+	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1),	/* + min denormal */
+	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1),	/* - min denormal */
+	DPSTR(0, 31 + DP_EBIAS, 0, 0),	/* + 1.0e31 */
+	DPSTR(0, 63 + DP_EBIAS, 0, 0),	/* + 1.0e63 */
+};
+
+const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0),	/* + zero   */
+	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0),	/* - zero   */
+	SPSTR(0, SP_EBIAS, 0),	/* + 1.0   */
+	SPSTR(1, SP_EBIAS, 0),	/* - 1.0   */
+	SPSTR(0, 3 + SP_EBIAS, 0x200000),	/* + 10.0   */
+	SPSTR(1, 3 + SP_EBIAS, 0x200000),	/* - 10.0   */
+	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0),	/* + infinity */
+	SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0),	/* - infinity */
+	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000),	/* + indef quiet Nan  */
+	SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF),	/* + max normal */
+	SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF),	/* - max normal */
+	SPSTR(0, SP_EMIN + SP_EBIAS, 0),	/* + min normal */
+	SPSTR(1, SP_EMIN + SP_EBIAS, 0),	/* - min normal */
+	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1),	/* + min denormal */
+	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1),	/* - min denormal */
+	SPSTR(0, 31 + SP_EBIAS, 0),	/* + 1.0e31 */
+	SPSTR(0, 63 + SP_EBIAS, 0),	/* + 1.0e63 */
+};
+
+
+int ieee754si_xcpt(int r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+	ax.op = op;
+	ax.rt = IEEE754_RT_SI;
+	ax.rv.si = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.si;
+}
+
+long long ieee754di_xcpt(long long r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+	ax.op = op;
+	ax.rt = IEEE754_RT_DI;
+	ax.rv.di = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.di;
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754.h linux/arch/mips64/math-emu/ieee754.h
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754.h	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,490 @@
+/* single and double precision fp ops
+ * missing extended precision.
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modification to allow integration with Linux kernel 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+/* Going from Algorithmics to Linux native environment, add this */
+#include <linux/types.h>
+
+/* 
+ * Not very pretty, but the Linux kernel's normal va_list definition 
+ * does not allow it to be used as a structure element, as it is here.
+ */
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#else
+
+/* Note that __KERNEL__ is taken to mean Linux kernel */
+
+#if #system(OpenBSD)
+#include <machine/types.h>
+#endif
+#include <machine/endian.h>
+
+#endif				/* __KERNEL__ */
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+struct ieee754dp_konst {
+	unsigned mantlo:32;
+	unsigned manthi:20;
+	unsigned bexp:11;
+	unsigned sign:1;
+};
+struct ieee754sp_konst {
+	unsigned mant:23;
+	unsigned bexp:8;
+	unsigned sign:1;
+};
+
+typedef union _ieee754dp {
+	struct ieee754dp_konst oparts;
+	struct {
+		unsigned long long mant:52;
+		unsigned int bexp:11;
+		unsigned int sign:1;
+	} parts;
+	unsigned long long bits;
+	double d;
+} ieee754dp;
+
+typedef union _ieee754sp {
+	struct ieee754sp_konst parts;
+	float f;
+	unsigned long bits;
+} ieee754sp;
+#endif
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+struct ieee754dp_konst {
+	unsigned sign:1;
+	unsigned bexp:11;
+	unsigned manthi:20;
+	unsigned mantlo:32;
+};
+typedef union _ieee754dp {
+	struct ieee754dp_konst oparts;
+	struct {
+		unsigned int sign:1;
+		unsigned int bexp:11;
+		unsigned long long mant:52;
+	} parts;
+	double d;
+	unsigned long long bits;
+} ieee754dp;
+
+struct ieee754sp_konst {
+	unsigned sign:1;
+	unsigned bexp:8;
+	unsigned mant:23;
+};
+
+typedef union _ieee754sp {
+	struct ieee754sp_konst parts;
+	float f;
+	unsigned long bits;
+} ieee754sp;
+#endif
+
+/*
+ * single precision (often aka float)
+*/
+int ieee754sp_finite(ieee754sp x);
+int ieee754sp_class(ieee754sp x);
+
+ieee754sp ieee754sp_abs(ieee754sp x);
+ieee754sp ieee754sp_neg(ieee754sp x);
+ieee754sp ieee754sp_scalb(ieee754sp x, int);
+ieee754sp ieee754sp_logb(ieee754sp x);
+
+/* x with sign of y */
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_fint(int x);
+ieee754sp ieee754sp_funs(unsigned x);
+ieee754sp ieee754sp_flong(long long x);
+ieee754sp ieee754sp_fulong(unsigned long long x);
+ieee754sp ieee754sp_fdp(ieee754dp x);
+
+int ieee754sp_tint(ieee754sp x);
+unsigned int ieee754sp_tuns(ieee754sp x);
+long long ieee754sp_tlong(ieee754sp x);
+unsigned long long ieee754sp_tulong(ieee754sp x);
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
+ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
+ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+
+ieee754sp ieee754sp_ceil(ieee754sp x);
+ieee754sp ieee754sp_floor(ieee754sp x);
+ieee754sp ieee754sp_trunc(ieee754sp x);
+
+ieee754sp ieee754sp_sqrt(ieee754sp x);
+
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_finite(ieee754dp x);
+int ieee754dp_class(ieee754dp x);
+
+/* x with sign of y */
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_abs(ieee754dp x);
+ieee754dp ieee754dp_neg(ieee754dp x);
+ieee754dp ieee754dp_scalb(ieee754dp x, int);
+
+/* return exponent as integer in floating point format 
+ */
+ieee754dp ieee754dp_logb(ieee754dp x);
+
+ieee754dp ieee754dp_fint(int x);
+ieee754dp ieee754dp_funs(unsigned x);
+ieee754dp ieee754dp_flong(long long x);
+ieee754dp ieee754dp_fulong(unsigned long long x);
+ieee754dp ieee754dp_fsp(ieee754sp x);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+int ieee754dp_tint(ieee754dp x);
+unsigned int ieee754dp_tuns(ieee754dp x);
+long long ieee754dp_tlong(ieee754dp x);
+unsigned long long ieee754dp_tulong(ieee754dp x);
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
+ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
+ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+ieee754dp ieee754dp_sqrt(ieee754dp x);
+
+
+
+/* 5 types of floating point number 
+*/
+#define IEEE754_CLASS_NORM	0x00
+#define IEEE754_CLASS_ZERO	0x01
+#define IEEE754_CLASS_DNORM	0x02
+#define IEEE754_CLASS_INF	0x03
+#define IEEE754_CLASS_SNAN	0x04
+#define IEEE754_CLASS_QNAN	0x05
+extern const char *const ieee754_cname[];
+
+/* exception numbers */
+#define IEEE754_INEXACT			0x01
+#define IEEE754_UNDERFLOW		0x02
+#define IEEE754_OVERFLOW		0x04
+#define IEEE754_ZERO_DIVIDE		0x08
+#define IEEE754_INVALID_OPERATION	0x10
+
+/* cmp operators
+*/
+#define IEEE754_CLT	0x01
+#define IEEE754_CEQ	0x02
+#define IEEE754_CGT	0x04
+#define IEEE754_CUN	0x08
+
+/* rounding mode 
+*/
+#define IEEE754_RN	0	/* round to nearest */
+#define IEEE754_RZ	1	/* round toward zero  */
+#define IEEE754_RD	2	/* round toward -Infinity */
+#define IEEE754_RU	3	/* round toward +Infinity */
+
+/* other naming */
+#define IEEE754_RM	IEEE754_RD
+#define IEEE754_RP	IEEE754_RU
+
+/* "normal" comparisons
+*/
+static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y,
+			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CGT);
+}
+
+
+static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y,
+			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CGT);
+}
+
+static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+
+/* like strtod
+*/
+ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+
+
+/* the control status register 
+*/
+struct ieee754_csr {
+	unsigned pad:13;
+	unsigned noq:1;		/* set 1 for no quiet NaN's */
+	unsigned nod:1;		/* set 1 for no denormalised numbers */
+	unsigned cx:5;		/* exceptions this operation */
+	unsigned mx:5;		/* exception enable  mask */
+	unsigned sx:5;		/* exceptions total */
+	unsigned rm:2;		/* current rounding mode */
+};
+extern struct ieee754_csr ieee754_csr;
+
+static __inline unsigned ieee754_getrm(void)
+{
+	return (ieee754_csr.rm);
+}
+static __inline unsigned ieee754_setrm(unsigned rm)
+{
+	return (ieee754_csr.rm = rm);
+}
+
+/*
+ * get current exceptions
+ */
+static __inline unsigned ieee754_getcx(void)
+{
+	return (ieee754_csr.cx);
+}
+
+/* test for current exception condition 
+ */
+static __inline int ieee754_cxtest(unsigned n)
+{
+	return (ieee754_csr.cx & n);
+}
+
+/*
+ * get sticky exceptions
+ */
+static __inline unsigned ieee754_getsx(void)
+{
+	return (ieee754_csr.sx);
+}
+
+/* clear sticky conditions
+*/
+static __inline unsigned ieee754_clrsx(void)
+{
+	return (ieee754_csr.sx = 0);
+}
+
+/* test for sticky exception condition 
+ */
+static __inline int ieee754_sxtest(unsigned n)
+{
+	return (ieee754_csr.sx & n);
+}
+
+/* debugging */
+ieee754sp ieee754sp_dump(char *s, ieee754sp x);
+ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+
+#define IEEE754_SPCVAL_PZERO	0
+#define IEEE754_SPCVAL_NZERO	1
+#define IEEE754_SPCVAL_PONE	2
+#define IEEE754_SPCVAL_NONE	3
+#define IEEE754_SPCVAL_PTEN	4
+#define IEEE754_SPCVAL_NTEN	5
+#define IEEE754_SPCVAL_PINFINITY	6
+#define IEEE754_SPCVAL_NINFINITY	7
+#define IEEE754_SPCVAL_INDEF	8
+#define IEEE754_SPCVAL_PMAX	9	/* +max norm */
+#define IEEE754_SPCVAL_NMAX	10	/* -max norm */
+#define IEEE754_SPCVAL_PMIN	11	/* +min norm */
+#define IEEE754_SPCVAL_NMIN	12	/* +min norm */
+#define IEEE754_SPCVAL_PMIND	13	/* +min denorm */
+#define IEEE754_SPCVAL_NMIND	14	/* +min denorm */
+#define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */
+
+extern const struct ieee754dp_konst __ieee754dp_spcvals[];
+extern const struct ieee754sp_konst __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+
+/* return infinity with given sign
+*/
+#define ieee754dp_inf(sn)	\
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+
+#define ieee754sp_inf(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+
+/* indefinite integer value 
+*/
+#define ieee754si_indef()	INT_MIN
+#ifdef LONG_LONG_MIN
+#define ieee754di_indef()	LONG_LONG_MIN
+#else
+#define ieee754di_indef()	(-9223372036854775807LL-1)
+#endif
+
+/* IEEE exception context, passed to handler */
+struct ieee754xctx {
+	const char *op;		/* operation name */
+	int rt;			/* result type */
+	union {
+		ieee754sp sp;	/* single precision */
+		ieee754dp dp;	/* double precision */
+#ifdef IEEE854_XP
+		ieee754xp xp;	/* extended precision */
+#endif
+		int si;		/* standard signed integer (32bits) */
+		long long di;	/* extended signed integer (64bits) */
+	} rv;			/* default result format implied by op */
+	va_list ap;
+};
+
+/* result types for xctx.rt */
+#define IEEE754_RT_SP	0
+#define IEEE754_RT_DP	1
+#define IEEE754_RT_XP	2
+#define IEEE754_RT_SI	3
+#define IEEE754_RT_DI	4
+
+extern void ieee754_xcpt(struct ieee754xctx *xcp);
+
+/* compat */
+#define ieee754dp_fix(x)	ieee754dp_tint(x)
+#define ieee754sp_fix(x)	ieee754sp_tint(x)
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754d.c linux/arch/mips64/math-emu/ieee754d.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754d.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754d.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,142 @@
+/* some debug functions
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modified to build and operate in Linux kernel environment. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+#define DP_FBITS	52
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+#define SP_FBITS	23
+
+#define DP_MBIT(x)	((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT	DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT	DP_MBIT(63)
+
+
+#define SP_MBIT(x)	((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT	SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT	SP_MBIT(31)
+
+
+#define SPSIGN(sp)	(sp.parts.sign)
+#define SPBEXP(sp)	(sp.parts.bexp)
+#define SPMANT(sp)	(sp.parts.mant)
+
+#define DPSIGN(dp)	(dp.parts.sign)
+#define DPBEXP(dp)	(dp.parts.bexp)
+#define DPMANT(dp)	(dp.parts.mant)
+
+ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+{
+	int i;
+
+	printk("%s", m);
+	printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32),
+	       (unsigned) x.bits);
+	printk("\t=");
+	switch (ieee754dp_class(x)) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		printk("Nan %c", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		break;
+	case IEEE754_CLASS_INF:
+		printk("%cInfinity", DPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_ZERO:
+		printk("%cZero", DPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_DNORM:
+		printk("%c0.", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		printk("e%d", DPBEXP(x) - DP_EBIAS);
+		break;
+	case IEEE754_CLASS_NORM:
+		printk("%c1.", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		printk("e%d", DPBEXP(x) - DP_EBIAS);
+		break;
+	default:
+		printk("Illegal/Unknown IEEE754 value class");
+	}
+	printk("\n");
+	return x;
+}
+
+ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+{
+	int i;
+
+	printk("%s=", m);
+	printk("<%08x>\n", (unsigned) x.bits);
+	printk("\t=");
+	switch (ieee754sp_class(x)) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		printk("Nan %c", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		break;
+	case IEEE754_CLASS_INF:
+		printk("%cInfinity", SPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_ZERO:
+		printk("%cZero", SPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_DNORM:
+		printk("%c0.", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		printk("e%d", SPBEXP(x) - SP_EBIAS);
+		break;
+	case IEEE754_CLASS_NORM:
+		printk("%c1.", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		printk("e%d", SPBEXP(x) - SP_EBIAS);
+		break;
+	default:
+		printk("Illegal/Unknown IEEE754 value class");
+	}
+	printk("\n");
+	return x;
+}
+
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754dp.c linux/arch/mips64/math-emu/ieee754dp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754dp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754dp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_class(ieee754dp x)
+{
+	COMPXDP;
+	EXPLODEXDP;
+	return xc;
+}
+
+int ieee754dp_isnan(ieee754dp x)
+{
+	return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754dp_issnan(ieee754dp x)
+{
+	assert(ieee754dp_isnan(x));
+	if (ieee754_csr.noq)
+		return 1;
+	return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1));
+}
+
+
+ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+	if (!TSTX())
+		return r;
+
+	ax.op = op;
+	ax.rt = IEEE754_RT_DP;
+	ax.rv.dp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	assert(ieee754dp_isnan(r));
+
+	if (!ieee754dp_issnan(r))	/* QNAN does not cause invalid op !! */
+		return r;
+
+	if (!SETCX(IEEE754_INVALID_OPERATION)) {
+		/* not enabled convert to a quiet NaN */
+		if (ieee754_csr.noq)
+			return r;
+		DPMANT(r) |= DP_MBIT(DP_MBITS - 1);
+		return r;
+	}
+
+	ax.op = op;
+	ax.rt = 0;
+	ax.rv.dp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+{
+	assert(ieee754dp_isnan(x));
+	assert(ieee754dp_isnan(y));
+
+	if (DPMANT(x) > DPMANT(y))
+		return x;
+	else
+		return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm)
+{
+	assert(xm);		/* we dont gen exact zeros (probably should) */
+
+	assert((xm >> (DP_MBITS + 1 + 3)) == 0);	/* no execess */
+	assert(xm & (DP_HIDDEN_BIT << 3));
+
+	if (xe < DP_EMIN) {
+		/* strip lower bits */
+		int es = DP_EMIN - xe;
+
+		if (ieee754_csr.nod) {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754dp_zero(sn);
+		}
+
+		/* sticky right shift es bits 
+		 */
+		xm = XDPSRS(xm, es);
+		xe += es;
+
+		assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+		assert(xe == DP_EMIN);
+	}
+	if (xm & (DP_MBIT(3) - 1)) {
+		SETCX(IEEE754_INEXACT);
+		/* inexact must round of 3 bits 
+		 */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+		/* adjust exponent for rounding add overflowing 
+		 */
+		if (xm >> (DP_MBITS + 3 + 1)) {	/* add causes mantissa overflow */
+			xm >>= 1;
+			xe++;
+		}
+	}
+	/* strip grs bits */
+	xm >>= 3;
+
+	assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */
+	assert(xe >= DP_EMIN);
+
+	if (xe > DP_EMAX) {
+		SETCX(IEEE754_OVERFLOW);
+		/* -O can be table indexed by (rm,sn) */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RN:
+			return ieee754dp_inf(sn);
+		case IEEE754_RZ:
+			return ieee754dp_max(sn);
+		case IEEE754_RU:	/* toward +Infinity */
+			if (sn == 0)
+				return ieee754dp_inf(0);
+			else
+				return ieee754dp_max(1);
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn == 0)
+				return ieee754dp_max(0);
+			else
+				return ieee754dp_inf(1);
+		}
+	}
+	/* gen norm/denorm/zero */
+
+	if ((xm & DP_HIDDEN_BIT) == 0) {
+		/* we underflow (tiny/zero) */
+		assert(xe == DP_EMIN);
+		SETCX(IEEE754_UNDERFLOW);
+		return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
+	} else {
+		assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */
+		assert(xm & DP_HIDDEN_BIT);
+
+		return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754dp.h linux/arch/mips64/math-emu/ieee754dp.h
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754dp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754dp.h	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,83 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended double precision sticky right shift */
+#define XDPSRS(v,rs)	\
+  ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+
+#define XDPSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define XDPSRS1(v)	\
+  (((v) >> 1) | ((v) & 1))
+
+/* convert denormal to normalized with extended exponent */
+#define DPDNORMx(m,e) \
+  while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+#define DPDNORMX	DPDNORMx(xm,xe)
+#define DPDNORMY	DPDNORMx(ym,ye)
+
+static __inline ieee754dp builddp(int s, int bx, unsigned long long m)
+{
+	ieee754dp r;
+
+	assert((s) == 0 || (s) == 1);
+	assert((bx) >= DP_EMIN - 1 + DP_EBIAS
+	       && (bx) <= DP_EMAX + 1 + DP_EBIAS);
+	assert(((m) >> DP_MBITS) == 0);
+
+	r.parts.sign = s;
+	r.parts.bexp = bx;
+	r.parts.mant = m;
+	return r;
+}
+
+extern int ieee754dp_isnan(ieee754dp);
+extern int ieee754dp_issnan(ieee754dp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
+extern ieee754dp ieee754dp_format(int, int, unsigned long long);
+
+
+#define DPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754dp V = ieee754dp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754dp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define DPNORMRET1(s,e,m,name,a0)  DPNORMRET2(s,e,m,name,a0,a0)
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754int.h linux/arch/mips64/math-emu/ieee754int.h
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754int.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754int.h	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,135 @@
+/* 
+ * IEEE754 floating point
+ * common internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+#define DP_MBITS	52
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+#define SP_MBITS	23
+
+#define DP_MBIT(x)	((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT	DP_MBIT(DP_MBITS)
+#define DP_SIGN_BIT	DP_MBIT(63)
+
+#define SP_MBIT(x)	((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT	SP_MBIT(SP_MBITS)
+#define SP_SIGN_BIT	SP_MBIT(31)
+
+
+#define SPSIGN(sp)	(sp.parts.sign)
+#define SPBEXP(sp)	(sp.parts.bexp)
+#define SPMANT(sp)	(sp.parts.mant)
+
+#define DPSIGN(dp)	(dp.parts.sign)
+#define DPBEXP(dp)	(dp.parts.bexp)
+#define DPMANT(dp)	(dp.parts.mant)
+
+#define CLPAIR(x,y)	((x)*6+(y))
+
+#define CLEARCX	\
+  (ieee754_csr.cx = 0)
+
+#define SETCX(x) \
+  (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x))
+
+#define TSTX()	\
+	(ieee754_csr.cx & ieee754_csr.mx)
+
+
+#define COMPXSP \
+  unsigned xm; int xe; int xs; int xc
+
+#define COMPYSP \
+  unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v,vc,vs,ve,vm) \
+{\
+    vs = SPSIGN(v);\
+    ve = SPBEXP(v);\
+    vm = SPMANT(v);\
+    if(ve == SP_EMAX+1+SP_EBIAS){\
+	if(vm == 0)\
+	  vc = IEEE754_CLASS_INF;\
+	else if(vm & SP_MBIT(SP_MBITS-1)) \
+	  vc = IEEE754_CLASS_QNAN;\
+	else \
+	  vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == SP_EMIN-1+SP_EBIAS) {\
+	if(vm) {\
+	    ve = SP_EMIN;\
+	    vc = IEEE754_CLASS_DNORM;\
+	} else\
+	  vc = IEEE754_CLASS_ZERO;\
+    } else {\
+	ve -= SP_EBIAS;\
+	vm |= SP_HIDDEN_BIT;\
+	vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm)
+#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym)
+
+
+#define COMPXDP \
+unsigned long long xm; int xe; int xs; int xc
+
+#define COMPYDP \
+unsigned long long ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v,vc,vs,ve,vm) \
+{\
+    vm = DPMANT(v);\
+    vs = DPSIGN(v);\
+    ve = DPBEXP(v);\
+    if(ve == DP_EMAX+1+DP_EBIAS){\
+	if(vm == 0)\
+	  vc = IEEE754_CLASS_INF;\
+	else if(vm & DP_MBIT(DP_MBITS-1)) \
+	  vc = IEEE754_CLASS_QNAN;\
+	else \
+	  vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == DP_EMIN-1+DP_EBIAS) {\
+	if(vm) {\
+	    ve = DP_EMIN;\
+	    vc = IEEE754_CLASS_DNORM;\
+	} else\
+	  vc = IEEE754_CLASS_ZERO;\
+    } else {\
+	ve -= DP_EBIAS;\
+	vm |= DP_HIDDEN_BIT;\
+	vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm)
+#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym)
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754m.c linux/arch/mips64/math-emu/ieee754m.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754m.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754m.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,56 @@
+/*
+ * floor, trunc, ceil
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+ieee754dp ieee754dp_floor(ieee754dp x)
+{
+	ieee754dp i;
+
+	if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+		return ieee754dp_sub(i, ieee754dp_one(0));
+	else
+		return i;
+}
+
+ieee754dp ieee754dp_ceil(ieee754dp x)
+{
+	ieee754dp i;
+
+	if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+		return ieee754dp_add(i, ieee754dp_one(0));
+	else
+		return i;
+}
+
+ieee754dp ieee754dp_trunc(ieee754dp x)
+{
+	ieee754dp i;
+
+	(void) ieee754dp_modf(x, &i);
+	return i;
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754sp.c linux/arch/mips64/math-emu/ieee754sp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754sp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754sp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_class(ieee754sp x)
+{
+	COMPXSP;
+	EXPLODEXSP;
+	return xc;
+}
+
+int ieee754sp_isnan(ieee754sp x)
+{
+	return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754sp_issnan(ieee754sp x)
+{
+	assert(ieee754sp_isnan(x));
+	if (ieee754_csr.noq)
+		return 1;
+	return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1));
+}
+
+
+ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+
+	ax.op = op;
+	ax.rt = IEEE754_RT_SP;
+	ax.rv.sp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	assert(ieee754sp_isnan(r));
+
+	if (!ieee754sp_issnan(r))	/* QNAN does not cause invalid op !! */
+		return r;
+
+	if (!SETCX(IEEE754_INVALID_OPERATION)) {
+		/* not enabled convert to a quiet NaN */
+		if (ieee754_csr.noq)
+			return r;
+		SPMANT(r) |= SP_MBIT(SP_MBITS - 1);
+		return r;
+	}
+
+	ax.op = op;
+	ax.rt = 0;
+	ax.rv.sp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+{
+	assert(ieee754sp_isnan(x));
+	assert(ieee754sp_isnan(y));
+
+	if (SPMANT(x) > SPMANT(y))
+		return x;
+	else
+		return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+{
+	assert(xm);		/* we dont gen exact zeros (probably should) */
+
+	assert((xm >> (SP_MBITS + 1 + 3)) == 0);	/* no execess */
+	assert(xm & (SP_HIDDEN_BIT << 3));
+
+	if (xe < SP_EMIN) {
+		/* strip lower bits */
+		int es = SP_EMIN - xe;
+
+		if (ieee754_csr.nod) {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754sp_zero(sn);
+		}
+
+		/* sticky right shift es bits 
+		 */
+		SPXSRSXn(es);
+
+		assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+		assert(xe == SP_EMIN);
+	}
+	if (xm & (SP_MBIT(3) - 1)) {
+		SETCX(IEEE754_INEXACT);
+		/* inexact must round of 3 bits 
+		 */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+		/* adjust exponent for rounding add overflowing 
+		 */
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* add causes mantissa overflow */
+			xm >>= 1;
+			xe++;
+		}
+	}
+	/* strip grs bits */
+	xm >>= 3;
+
+	assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */
+	assert(xe >= SP_EMIN);
+
+	if (xe > SP_EMAX) {
+		SETCX(IEEE754_OVERFLOW);
+		/* -O can be table indexed by (rm,sn) */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RN:
+			return ieee754sp_inf(sn);
+		case IEEE754_RZ:
+			return ieee754sp_max(sn);
+		case IEEE754_RU:	/* toward +Infinity */
+			if (sn == 0)
+				return ieee754sp_inf(0);
+			else
+				return ieee754sp_max(1);
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn == 0)
+				return ieee754sp_max(0);
+			else
+				return ieee754sp_inf(1);
+		}
+	}
+	/* gen norm/denorm/zero */
+
+	if ((xm & SP_HIDDEN_BIT) == 0) {
+		/* we underflow (tiny/zero) */
+		assert(xe == SP_EMIN);
+		SETCX(IEEE754_UNDERFLOW);
+		return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
+	} else {
+		assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */
+		assert(xm & SP_HIDDEN_BIT);
+
+		return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754sp.h linux/arch/mips64/math-emu/ieee754sp.h
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754sp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754sp.h	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,89 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended single precision sticky right shift */
+#define SPXSRSXn(rs) \
+  (xe += rs, \
+   xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+
+#define SPXSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define SPXSRSYn(rs) \
+   (ye+=rs, \
+    ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+
+#define SPXSRSY1() \
+   (ye++, (ym = (ym >> 1) | (ym & 1)))
+
+/* convert denormal to normalized with extended exponent */
+#define SPDNORMx(m,e) \
+  while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+#define SPDNORMX	SPDNORMx(xm,xe)
+#define SPDNORMY	SPDNORMx(ym,ye)
+
+static __inline ieee754sp buildsp(int s, int bx, unsigned m)
+{
+	ieee754sp r;
+
+	assert((s) == 0 || (s) == 1);
+	assert((bx) >= SP_EMIN - 1 + SP_EBIAS
+	       && (bx) <= SP_EMAX + 1 + SP_EBIAS);
+	assert(((m) >> SP_MBITS) == 0);
+
+	r.parts.sign = s;
+	r.parts.bexp = bx;
+	r.parts.mant = m;
+
+	return r;
+}
+
+extern int ieee754sp_isnan(ieee754sp);
+extern int ieee754sp_issnan(ieee754sp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
+extern ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754sp V = ieee754sp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754sp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define SPNORMRET1(s,e,m,name,a0)  SPNORMRET2(s,e,m,name,a0,a0)
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/ieee754xcpt.c linux/arch/mips64/math-emu/ieee754xcpt.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/ieee754xcpt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754xcpt.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,48 @@
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Added preprocessor hacks to map to Linux kernel diagnostics. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+/*
+ * Very naff exception handler (you can plug in your own and
+ * override this).
+ */
+
+static const char *const rtnames[] = {
+	"sp", "dp", "xp", "si", "di"
+};
+
+void ieee754_xcpt(struct ieee754xctx *xcp)
+{
+	printk("floating point exception in \"%s\", type=%s\n",
+		xcp->op, rtnames[xcp->rt]);
+}
+
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/kernel_linkage.c linux/arch/mips64/math-emu/kernel_linkage.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/kernel_linkage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/kernel_linkage.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,95 @@
+/**************************************************************************
+ *
+ *  arch/mips/math_emu/kernel_linkage.c
+ *
+ *  Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *************************************************************************/
+/*
+ * Routines corresponding to Linux kernel FP context
+ * manipulation primitives for the Algorithmics MIPS
+ * FPU Emulator
+ */
+
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpu_emulator.h>
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+void fpu_emulator_init_fpu(void)
+{
+	static int first = 1;
+	int i;
+ 
+	if (first) {
+		first = 0;
+		printk("Algorithmics/MIPS FPU Emulator v1.4\n");
+	}
+
+	current->thread.fpu.soft.sr = 0;
+	for (i = 0; i < 32; i++) {
+		current->thread.fpu.soft.regs[i] = SIGNALLING_NAN;
+	}
+}
+
+
+/*
+ * Emulator context save/restore to/from a signal context
+ * presumed to be on the user stack, and therefore accessed
+ * with appropriate macros from uaccess.h
+ */
+
+int fpu_emulator_save_context(struct sigcontext *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < 32; i++) {
+		err |=
+		    __put_user(current->thread.fpu.soft.regs[i],
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+	err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+	return err;
+}
+
+int fpu_emulator_restore_context(struct sigcontext *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < 32; i++) {
+		err |=
+		    __get_user(current->thread.fpu.soft.regs[i],
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+	err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+	return err;
+}
+
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_add.c linux/arch/mips64/math-emu/sp_add.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_add.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_add.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	CLEARCX;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs == ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs == ys)
+			return x;
+		else
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		SPXSRSYn(s);
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		SPXSRSXn(s);
+	}
+	assert(xe == ye);
+	assert(xe <= SP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 * leaving result in xm,xs,xe
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* carry out */
+			SPXSRSX1();
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+		/* normalize in extended single precision */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+
+	}
+	SPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_cmp.c linux/arch/mips64/math-emu/sp_cmp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_cmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_cmp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+		if (cmp & IEEE754_CUN)
+			return 1;
+		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+			if (SETCX(IEEE754_INVALID_OPERATION))
+				return ieee754si_xcpt(0, "fcmpf", x);
+		}
+		return 0;
+	} else {
+		int vx = x.bits;
+		int vy = y.bits;
+
+		if (vx < 0)
+			vx = -vx ^ SP_SIGN_BIT;
+		if (vy < 0)
+			vy = -vy ^ SP_SIGN_BIT;
+
+		if (vx < vy)
+			return (cmp & IEEE754_CLT) != 0;
+		else if (vx == vy)
+			return (cmp & IEEE754_CEQ) != 0;
+		else
+			return (cmp & IEEE754_CGT) != 0;
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_div.c linux/arch/mips64/math-emu/sp_div.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_div.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_div.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return ieee754sp_zero(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return ieee754sp_inf(xs ^ ys);
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_ZERO_DIVIDE);
+		return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return ieee754sp_zero(xs == ys ? 0 : 1);
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	/* provide rounding space */
+	xm <<= 3;
+	ym <<= 3;
+
+	{
+		/* now the dirty work */
+
+		unsigned rm = 0;
+		int re = xe - ye;
+		unsigned bm;
+
+		for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
+			if (xm >= ym) {
+				xm -= ym;
+				rm |= bm;
+				if (xm == 0)
+					break;
+			}
+			xm <<= 1;
+		}
+		rm <<= 1;
+		if (xm)
+			rm |= 1;	/* have remainder, set sticky */
+
+		assert(rm);
+
+		/* normalise rm to rounding precision ?
+		 */
+		while ((rm >> (SP_MBITS + 3)) == 0) {
+			rm <<= 1;
+			re--;
+		}
+
+		SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_fdp.c linux/arch/mips64/math-emu/sp_fdp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_fdp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_fdp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,69 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fdp(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(buildsp(xs,
+						 SP_EMAX + 1 + SP_EBIAS,
+						 (unsigned long)
+						 (xm >>
+						  (DP_MBITS - SP_MBITS))),
+					 "fdp", x);
+	case IEEE754_CLASS_INF:
+		return ieee754sp_inf(xs);
+	case IEEE754_CLASS_ZERO:
+		return ieee754sp_zero(xs);
+	case IEEE754_CLASS_DNORM:
+		/* cant possibly be sp representable */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+
+	{
+		unsigned long rm;
+
+		/* convert from DP_MBITS to SP_MBITS+3 with sticky right shift 
+		 */
+		rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
+		    ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+
+		SPNORMRET1(xs, xe, rm, "fdp", x);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_fint.c linux/arch/mips64/math-emu/sp_fint.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_fint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_fint.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fint(int x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754sp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754sp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754sp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1 << 31))
+			xm = ((unsigned) 1 << 31);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+	xe = SP_MBITS + 3;
+
+	if (xm >> (SP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits 
+		 */
+		while (xm >> (SP_MBITS + 1 + 3)) {
+			SPXSRSX1();
+		}
+	} else {
+		/* normalize in grs extended single precision 
+		 */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET1(xs, xe, xm, "fint", x);
+}
+
+
+ieee754sp ieee754sp_funs(unsigned int u)
+{
+	if ((int) u < 0)
+		return ieee754sp_add(ieee754sp_1e31(),
+				     ieee754sp_fint(u & ~(1 << 31)));
+	return ieee754sp_fint(u);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_flong.c linux/arch/mips64/math-emu/sp_flong.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_flong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_flong.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_flong(long long x)
+{
+	COMPXDP;		/* <--- need 64-bit mantissa temp */
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754sp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754sp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754sp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1ULL << 63))
+			xm = (1ULL << 63);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+	xe = SP_MBITS + 3;
+
+	if (xm >> (SP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits 
+		 */
+		while (xm >> (SP_MBITS + 1 + 3)) {
+			SPXSRSX1();
+		}
+	} else {
+		/* normalize in grs extended single precision */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET1(xs, xe, xm, "sp_flong", x);
+}
+
+
+ieee754sp ieee754sp_fulong(unsigned long long u)
+{
+	if ((long long) u < 0)
+		return ieee754sp_add(ieee754sp_1e63(),
+				     ieee754sp_flong(u & ~(1ULL << 63)));
+	return ieee754sp_flong(u);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_frexp.c linux/arch/mips64/math-emu/sp_frexp.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_frexp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_frexp.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* close to ieeep754sp_logb 
+*/
+ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+{
+	COMPXSP;
+	CLEARCX;
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*eptr = 0;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	*eptr = xe + 1;
+	return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_logb.c linux/arch/mips64/math-emu/sp_logb.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_logb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_logb.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_logb(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x, "logb", x);
+	case IEEE754_CLASS_QNAN:
+		return x;
+	case IEEE754_CLASS_INF:
+		return ieee754sp_inf(0);
+	case IEEE754_CLASS_ZERO:
+		return ieee754sp_inf(1);
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	return ieee754sp_fint(xe);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_modf.c linux/arch/mips64/math-emu/sp_modf.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_modf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_modf.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*ip = x;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		/* far to small */
+		*ip = ieee754sp_zero(xs);
+		return x;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe < 0) {
+		*ip = ieee754sp_zero(xs);
+		return x;
+	}
+	if (xe >= SP_MBITS) {
+		*ip = x;
+		return ieee754sp_zero(xs);
+	}
+	/* generate ipart mantissa by clearing bottom bits 
+	 */
+	*ip = buildsp(xs, xe + SP_EBIAS,
+		      ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
+		      ~SP_HIDDEN_BIT);
+
+	/* generate fpart mantissa by clearing top bits
+	 * and normalizing (must be able to normalize)
+	 */
+	xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
+	if (xm == 0)
+		return ieee754sp_zero(xs);
+
+	while ((xm >> SP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_mul.c linux/arch/mips64/math-emu/sp_mul.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_mul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_mul.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,174 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		return ieee754sp_inf(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return ieee754sp_zero(xs ^ ys);
+
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* rm = xm * ym, re = xe+ye basicly */
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	{
+		int re = xe + ye;
+		int rs = xs ^ ys;
+		unsigned rm;
+
+		/* shunt to top of word */
+		xm <<= 32 - (SP_MBITS + 1);
+		ym <<= 32 - (SP_MBITS + 1);
+
+		/* multiply 32bits xm,ym to give high 32bits rm with stickness
+		 */
+		{
+			unsigned short lxm = xm & 0xffff;
+			unsigned short hxm = xm >> 16;
+			unsigned short lym = ym & 0xffff;
+			unsigned short hym = ym >> 16;
+			unsigned lrm;
+			unsigned hrm;
+
+			lrm = lxm * lym;	/* 16 * 16 => 32 */
+			hrm = hxm * hym;	/* 16 * 16 => 32 */
+
+			{
+				unsigned t = lxm * hym;	/* 16 * 16 => 32 */
+				{
+					unsigned at = lrm + (t << 16);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 16);
+			}
+
+			{
+				unsigned t = hxm * lym;	/* 16 * 16 => 32 */
+				{
+					unsigned at = lrm + (t << 16);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 16);
+			}
+			rm = hrm | (lrm != 0);
+		}
+
+		/*
+		 * sticky shift down to normal rounding precision
+		 */
+		if ((int) rm < 0) {
+			rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
+			    ((rm << (SP_MBITS + 1 + 3)) != 0);
+			re++;
+		} else {
+			rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
+			    ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
+		}
+		assert(rm & (SP_HIDDEN_BIT << 3));
+
+		SPNORMRET2(rs, re, rm, "mul", x, y);
+	}
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_scalb.c linux/arch/mips64/math-emu/sp_scalb.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_scalb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_scalb.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x, "scalb", x, n);
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		return x;
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+{
+	return ieee754sp_scalb(x, n);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_simple.c linux/arch/mips64/math-emu/sp_simple.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_simple.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_finite(ieee754sp x)
+{
+	return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+{
+	CLEARCX;
+	SPSIGN(x) = SPSIGN(y);
+	return x;
+}
+
+
+ieee754sp ieee754sp_neg(ieee754sp x)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x))	/* but not infinity */
+		return ieee754sp_nanxcpt(x, "neg", x);
+
+	/* quick fix up */
+	SPSIGN(x) ^= 1;
+	return x;
+}
+
+
+ieee754sp ieee754sp_abs(ieee754sp x)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x))	/* but not infinity */
+		return ieee754sp_nanxcpt(x, "abs", x);
+
+	/* quick fix up */
+	SPSIGN(x) = 0;
+	return x;
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_sqrt.c linux/arch/mips64/math-emu/sp_sqrt.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_sqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_sqrt.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,115 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+static const struct ieee754sp_konst knan = {
+	0, SP_EBIAS + SP_EMAX + 1, 0
+};
+
+#define nan	((ieee754sp)knan)
+
+ieee754sp ieee754sp_sqrt(ieee754sp x)
+{
+	int sign = (int) 0x80000000;
+	int ix, s, q, m, t, i;
+	unsigned int r;
+	COMPXDP;
+
+	/* take care of Inf and NaN */
+
+	EXPLODEXDP;
+
+	/* x == INF or NAN? */
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		/* sqrt(Nan) = Nan */
+		return ieee754sp_nanxcpt(x, "sqrt");
+	case IEEE754_CLASS_ZERO:
+		/* sqrt(0) = 0 */
+		return x;
+	case IEEE754_CLASS_INF:
+		if (xs)
+			/* sqrt(-Inf) = Nan */
+			return ieee754sp_nanxcpt(nan, "sqrt");
+		/* sqrt(+Inf) = Inf */
+		return x;
+	case IEEE754_CLASS_DNORM:
+	case IEEE754_CLASS_NORM:
+		if (xs)
+			/* sqrt(-x) = Nan */
+			return ieee754sp_nanxcpt(nan, "sqrt");
+		break;
+	}
+
+	ix = x.bits;
+
+	/* normalize x */
+	m = (ix >> 23);
+	if (m == 0) {		/* subnormal x */
+		for (i = 0; (ix & 0x00800000) == 0; i++)
+			ix <<= 1;
+		m -= i - 1;
+	}
+	m -= 127;		/* unbias exponent */
+	ix = (ix & 0x007fffff) | 0x00800000;
+	if (m & 1)		/* odd m, double x to make it even */
+		ix += ix;
+	m >>= 1;		/* m = [m/2] */
+
+	/* generate sqrt(x) bit by bit */
+	ix += ix;
+	q = s = 0;		/* q = sqrt(x) */
+	r = 0x01000000;		/* r = moving bit from right to left */
+
+	while (r != 0) {
+		t = s + r;
+		if (t <= ix) {
+			s = t + r;
+			ix -= t;
+			q += r;
+		}
+		ix += ix;
+		r >>= 1;
+	}
+
+	if (ix != 0) {
+		switch (ieee754_csr.rm) {
+		case IEEE754_RP:
+			q += 2;
+			break;
+		case IEEE754_RN:
+			q += (q & 1);
+			break;
+		}
+	}
+	ix = (q >> 1) + 0x3f000000;
+	ix += (m << 23);
+	x.bits = ix;
+	return x;
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_sub.c linux/arch/mips64/math-emu/sp_sub.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_sub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_sub.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,187 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs != ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+		return ieee754sp_inf(ys ^ 1);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs != ys)
+			return x;
+		else
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		/* quick fix up */
+		DPSIGN(y) ^= 1;
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* flip sign of y and handle as add */
+	ys ^= 1;
+
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		SPXSRSYn(s);
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		SPXSRSXn(s);
+	}
+	assert(xe == ye);
+	assert(xe <= SP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* carry out */
+			SPXSRSX1();	/* shift preserving sticky */
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			if (ieee754_csr.rm == IEEE754_RD)
+				return ieee754sp_zero(1);	/* round negative inf. => sign = -1 */
+			else
+				return ieee754sp_zero(0);	/* other round modes   => sign = 1 */
+
+		/* normalize to rounding precision 
+		 */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_tint.c linux/arch/mips64/math-emu/sp_tint.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_tint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_tint.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754sp.h"
+
+int ieee754sp_tint(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fixsp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 31) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fix", x);
+	}
+	/* oh gawd */
+	if (xe > SP_MBITS) {
+		xm <<= xe - SP_MBITS;
+	} else if (xe < SP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= SP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned int ieee754sp_tuns(ieee754sp x)
+{
+	ieee754sp hb = ieee754sp_1e31();
+
+	/* what if x < 0 ?? */
+	if (ieee754sp_lt(x, hb))
+		return (unsigned) ieee754sp_tint(x);
+
+	return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
+	    ((unsigned) 1 << 31);
+}
diff -urN linux-2.4.6-pre8/arch/mips64/math-emu/sp_tlong.c linux/arch/mips64/math-emu/sp_tlong.c
--- linux-2.4.6-pre8/arch/mips64/math-emu/sp_tlong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_tlong.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,87 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+long long ieee754sp_tlong(ieee754sp x)
+{
+	COMPXDP;		/* <-- need 64-bit mantissa tmp */
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "sp_tlong", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 63) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "sp_tlong", x);
+	}
+	/* oh gawd */
+	if (xe > SP_MBITS) {
+		xm <<= xe - SP_MBITS;
+	} else if (xe < SP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= SP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned long long ieee754sp_tulong(ieee754sp x)
+{
+	ieee754sp hb = ieee754sp_1e63();
+
+	/* what if x < 0 ?? */
+	if (ieee754sp_lt(x, hb))
+		return (unsigned long long) ieee754sp_tlong(x);
+
+	return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
+	    (1ULL << 63);
+}
diff -urN linux-2.4.6-pre8/arch/parisc/vmlinux.lds linux/arch/parisc/vmlinux.lds
--- linux-2.4.6-pre8/arch/parisc/vmlinux.lds	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -22,7 +22,7 @@
 	} = 0
 
   . = ALIGN(16);
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   _etext = .;			/* End of text section */
diff -urN linux-2.4.6-pre8/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- linux-2.4.6-pre8/arch/ppc/8xx_io/commproc.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/8xx_io/commproc.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.commproc.c 1.8 05/18/01 07:54:04 patch
+ * BK Id: SCCS/s.commproc.c 1.11 06/15/01 13:00:20 paulus
  */
 
 /*
@@ -47,12 +47,12 @@
 /* CPM interrupt vector functions.
 */
 struct	cpm_action {
-	void	(*handler)(void *);
+	void	(*handler)(void *, struct pt_regs * regs);
 	void	*dev_id;
 };
 static	struct	cpm_action cpm_vecs[CPMVEC_NR];
 static	void	cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
-static	void	cpm_error_interrupt(void *);
+static	void	cpm_error_interrupt(void *, struct pt_regs * regs);
 
 void
 m8xx_cpm_reset(uint host_page_addr)
@@ -129,7 +129,7 @@
 	vec >>= 11;
 
 	if (cpm_vecs[vec].handler != 0)
-		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
+		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id, regs);
 	else
 		((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
 
@@ -146,14 +146,15 @@
  * tests in the interrupt handler.
  */
 static	void
-cpm_error_interrupt(void *dev)
+cpm_error_interrupt(void *dev, struct pt_regs *regs)
 {
 }
 
 /* Install a CPM interrupt handler.
 */
 void
-cpm_install_handler(int vec, void (*handler)(void *), void *dev_id)
+cpm_install_handler(int vec, void (*handler)(void *, struct pt_regs *regs),
+		    void *dev_id)
 {
 
 	/* If null handler, assume we are trying to free the IRQ.
diff -urN linux-2.4.6-pre8/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h
--- linux-2.4.6-pre8/arch/ppc/8xx_io/commproc.h	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/8xx_io/commproc.h	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.commproc.h 1.8 05/17/01 18:14:20 cort
+ * BK Id: SCCS/s.commproc.h 1.13 06/15/01 13:00:20 paulus
  */
 
 /*
@@ -789,7 +789,8 @@
 #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
 #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
 
-extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id);
+extern void cpm_install_handler(int vec, 
+		void (*handler)(void *, struct pt_regs *regs), void *dev_id);
 extern void cpm_free_handler(int vec);
 
 #endif /* __CPM_8XX__ */
diff -urN linux-2.4.6-pre8/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- linux-2.4.6-pre8/arch/ppc/8xx_io/uart.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/8xx_io/uart.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.uart.c 1.10 05/17/01 18:14:20 cort
+ * BK Id: SCCS/s.uart.c 1.14 06/27/01 14:49:55 trini
  */
 /*
  *  UART driver for MPC860 CPM SCC or SMC
@@ -44,6 +44,9 @@
 #include <asm/8xx_immap.h>
 #include <asm/mpc8xx.h>
 #include "commproc.h"
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
 
 #ifdef CONFIG_KGDB
 extern void breakpoint(void);
@@ -91,6 +94,15 @@
 static int serial_refcount;
 static int serial_console_setup(struct console *co, char *options);
 
+static int serial_console_wait_key(struct console *co);
+static void serial_console_write(struct console *c, const char *s,
+				unsigned count);
+static kdev_t serial_console_device(struct console *c);
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
 /*
  * Serial driver configuration section.  Here are the various options:
  */
@@ -202,6 +214,16 @@
 	cbd_t			*tx_cur;
 } ser_info_t;
 
+static struct console sercons = {
+	name:		"ttyS",
+	write:		serial_console_write,
+	device:		serial_console_device,
+	wait_key:	serial_console_wait_key,
+	setup:		serial_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		CONFIG_SERIAL_CONSOLE_PORT,
+};
+
 static void change_speed(ser_info_t *info);
 static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
 
@@ -325,7 +347,7 @@
 	mark_bh(SERIAL_BH);
 }
 
-static _INLINE_ void receive_chars(ser_info_t *info)
+static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, *cp;
@@ -413,7 +435,7 @@
 				}
 				 */
 				status &= info->read_status_mask;
-		
+
 				if (status & (BD_SC_BR)) {
 #ifdef SERIAL_DEBUG_INTR
 					printk("handling break....");
@@ -440,6 +462,17 @@
 					}
 				}
 			}
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+			if (break_pressed && info->line == sercons.index) {
+				if (ch != 0 && time_before(jiffies, 
+							break_pressed + HZ*5)) {
+					handle_sysrq(ch, regs, NULL, NULL);
+					break_pressed = 0;
+					goto ignore_char;
+				} else
+					break_pressed = 0;
+			}
+#endif
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				break;
 
@@ -448,6 +481,7 @@
 			tty->flip.count++;
 		}
 
+	ignore_char:	
 		/* This BD is ready to be used again.  Clear status.
 		 * Get next BD.
 		 */
@@ -459,17 +493,27 @@
 		else
 			bdp++;
 	}
-
 	info->rx_cur = (cbd_t *)bdp;
 
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void receive_break(ser_info_t *info)
+static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 
 	info->state->icount.brk++;
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	if (info->line == sercons.index) {
+		if (!break_pressed) {
+			break_pressed = jiffies;
+			return;
+		} else
+			break_pressed = 0;
+	}
+#endif
+
 	/* Check to see if there is room in the tty buffer for
 	 * the break.  If not, we exit now, losing the break.  FIXME
 	 */
@@ -482,7 +526,7 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void transmit_chars(ser_info_t *info)
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	
 	if ((info->flags & TX_WAKEUP) ||
@@ -571,7 +615,7 @@
 /*
  * This is the serial driver's interrupt routine for a single port
  */
-static void rs_8xx_interrupt(void *dev_id)
+static void rs_8xx_interrupt(void *dev_id, struct pt_regs *regs)
 {
 	u_char	events;
 	int	idx;
@@ -585,21 +629,23 @@
 	if (info->state->smc_scc_num & NUM_IS_SCC) {
 		sccp = &cpmp->cp_scc[idx];
 		events = sccp->scc_scce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
 		if (events & SCCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SCCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		sccp->scc_scce = events;
 	}
 	else {
 		smcp = &cpmp->cp_smc[idx];
 		events = smcp->smc_smce;
 		if (events & SMCM_BRKE)
-			receive_break(info);
+			receive_break(info, regs);
 		if (events & SMCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SMCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		smcp->smc_smce = events;
 	}
 	
@@ -2428,17 +2474,6 @@
 	return MKDEV(TTY_MAJOR, 64 + c->index);
 }
 
-
-static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
-};
-
 /*
  *	Register console.
  */
@@ -2771,7 +2806,7 @@
 					immap->im_ioport.iop_padir &= ~iobits;
 					immap->im_ioport.iop_paodr &= ~iobits;
 				}
-#endif
+#endif /* CONFIG_ALTSMC2 */
 
 				/* Connect the baud rate generator to the
 				 * SMC based upon index in rs_table.  Also
diff -urN linux-2.4.6-pre8/arch/ppc/boot/chrp/main.c linux/arch/ppc/boot/chrp/main.c
--- linux-2.4.6-pre8/arch/ppc/boot/chrp/main.c	Thu May 24 15:02:06 2001
+++ linux/arch/ppc/boot/chrp/main.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.main.c 1.9 06/12/01 16:42:26 paulus
  */
 /*
  * Copyright (C) Paul Mackerras 1997.
@@ -100,13 +100,13 @@
 	    rec->tag = BI_MACHTYPE;
 	    rec->data[0] = _MACH_chrp;
 	    rec->data[1] = 1;
-	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	    rec->size = sizeof(struct bi_record) + 2 * 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->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
 #endif
 	    rec->tag = BI_LAST;
diff -urN linux-2.4.6-pre8/arch/ppc/boot/common/misc-common.c linux/arch/ppc/boot/common/misc-common.c
--- linux-2.4.6-pre8/arch/ppc/boot/common/misc-common.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/boot/common/misc-common.c	Mon Dec  3 22:50:37 2001
@@ -38,7 +38,7 @@
 /* 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
+#if defined(CONFIG_ALL_PPC) && defined(CONFIG_VGA_CONSOLE)
 extern void cursor(int x, int y);
 extern void scroll(void);
 extern char *vidmem;
diff -urN linux-2.4.6-pre8/arch/ppc/boot/pmac/chrpmain.c linux/arch/ppc/boot/pmac/chrpmain.c
--- linux-2.4.6-pre8/arch/ppc/boot/pmac/chrpmain.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/chrpmain.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.chrpmain.c 1.9 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.chrpmain.c 1.12 06/12/01 16:42:26 paulus
  */
 /*
  * Copyright (C) Paul Mackerras 1997.
@@ -34,15 +34,6 @@
 
 #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;
@@ -98,7 +89,6 @@
     }
 
     flush_cache(dst, len);
-    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
     make_bi_recs((unsigned long) dst + len);
 
     sa = (unsigned long)PROG_START;
@@ -133,19 +123,14 @@
 	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->size = sizeof(struct bi_record) + 2 * 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->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
 #endif /* SYSMAP_OFFSET */
 	
diff -urN linux-2.4.6-pre8/arch/ppc/boot/pmac/coffmain.c linux/arch/ppc/boot/pmac/coffmain.c
--- linux-2.4.6-pre8/arch/ppc/boot/pmac/coffmain.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/coffmain.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.coffmain.c 1.9 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.coffmain.c 1.12 06/12/01 16:42:26 paulus
  */
 /*
  * Copyright (C) Paul Mackerras 1997.
@@ -24,7 +24,7 @@
 #define get_16be(x)	(*(unsigned short *)(x))
 #define get_32be(x)	(*(unsigned *)(x))
 
-#define RAM_START	0xc0000000
+#define RAM_START	0
 #define RAM_END		(RAM_START + 0x800000)	/* only 8M mapped with BATs */
 
 #define PROG_START	RAM_START
@@ -32,15 +32,6 @@
 
 #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;
@@ -81,7 +72,7 @@
     claim(0, PROG_SIZE, 0);
     dst = (void *) RAM_START;
     if (im[0] == 0x1f && im[1] == 0x8b) {
-	/* claim some memory for scratch space */
+	/* set up scratch space */
 	begin_avail = avail_high = avail_ram = heap;
 	end_avail = heap + sizeof(heap);
 	printf("heap at 0x%x\n", avail_ram);
@@ -95,7 +86,6 @@
     }
 
     flush_cache(dst, len);
-    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
     make_bi_recs((unsigned long)dst + len);
     
     sa = (unsigned long)PROG_START;
@@ -127,18 +117,13 @@
 	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->size = sizeof(struct bi_record) + 2 * 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);
diff -urN linux-2.4.6-pre8/arch/ppc/boot/pmac/ld.script linux/arch/ppc/boot/pmac/ld.script
--- linux-2.4.6-pre8/arch/ppc/boot/pmac/ld.script	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/ld.script	Mon Dec  3 22:50:37 2001
@@ -32,6 +32,7 @@
   {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     *(.got1)
   }
diff -urN linux-2.4.6-pre8/arch/ppc/boot/prep/Makefile linux/arch/ppc/boot/prep/Makefile
--- linux-2.4.6-pre8/arch/ppc/boot/prep/Makefile	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/prep/Makefile	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.15 05/21/01 11:51:32 trini
+# BK Id: SCCS/s.Makefile 1.17 06/12/01 16:47:44 paulus
 #
 # arch/ppc/boot/Makefile
 #
@@ -33,13 +33,17 @@
 endif
 
 ZLINKFLAGS = -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00800000
-OBJECTS := head.o misc.o vreset.o kbd.o ../common/misc-common.o \
+OBJECTS := head.o misc.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
+
+ifeq ($(CONFIG_VGA_CONSOLE),y)
+OBJECTS += vreset.o kbd.o
 endif
 
 # Tools
diff -urN linux-2.4.6-pre8/arch/ppc/boot/prep/misc.c linux/arch/ppc/boot/prep/misc.c
--- linux-2.4.6-pre8/arch/ppc/boot/prep/misc.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/boot/prep/misc.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.misc.c 1.10 06/05/01 20:20:05 paulus
+ * BK Id: SCCS/s.misc.c 1.14 06/16/01 20:43:20 trini
  */
 /*
  * misc.c
@@ -13,8 +13,9 @@
 #include <linux/types.h>
 #include "zlib.h"
 #include <asm/residual.h>
-#include <linux/elf.h>
 #include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/elf.h>
 #include <linux/pci_ids.h>
 #include <asm/page.h>
 #include <asm/processor.h>
@@ -102,6 +103,7 @@
 	return;
 }
 
+#ifdef CONFIG_VGA_CONSOLE
 void
 scroll()
 {
@@ -111,6 +113,7 @@
 	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
 		vidmem[i] = ' ';
 }
+#endif /* CONFIG_VGA_CONSOLE */
 
 /*
  * This routine is used to control the second processor on the 
@@ -170,7 +173,9 @@
 #if defined(CONFIG_SERIAL_CONSOLE)
 	com_port = serial_init(0);
 #endif /* CONFIG_SERIAL_CONSOLE */
-	vga_init((char)0xC0000000);
+#if defined(CONFIG_VGA_CONSOLE)
+	vga_init((unsigned char *)0xC0000000);
+#endif /* CONFIG_VGA_CONSOLE */
 
 	if (residual)
 	{
@@ -360,8 +365,15 @@
 	while (timer++ < 5*1000) {
 		if (tstc()) {
 			while ((ch = getc()) != '\n' && ch != '\r') {
-				if (ch == '\b') {
+				/* 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");
 					}
diff -urN linux-2.4.6-pre8/arch/ppc/boot/tree/Makefile linux/arch/ppc/boot/tree/Makefile
--- linux-2.4.6-pre8/arch/ppc/boot/tree/Makefile	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/tree/Makefile	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch
+# BK Id: SCCS/s.Makefile 1.7 06/15/01 13:16:10 paulus
 #
 #
 #    Module name: Makefile
@@ -26,12 +26,13 @@
 
 GZIP	= gzip -vf9
 RM	= rm -f
-MKEVIMG	= ../utils/mkevimg -l
+MKEVIMG	= ../utils/mkevimg -l -c
 MKIRIMG	= ../utils/mkirimg
+CFLAGS	+= -I$(TOPDIR)/drivers/net
 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
+		../common/misc-common.o ../common/ns16550.o
 LIBS	= ../lib/zlib.a
 
 treeboot: $(OBJS) $(LIBS) ld.script
diff -urN linux-2.4.6-pre8/arch/ppc/boot/tree/ld.script linux/arch/ppc/boot/tree/ld.script
--- linux-2.4.6-pre8/arch/ppc/boot/tree/ld.script	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/tree/ld.script	Mon Dec  3 22:50:37 2001
@@ -32,6 +32,7 @@
   {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     *(.got1)
   }
diff -urN linux-2.4.6-pre8/arch/ppc/boot/tree/main.c linux/arch/ppc/boot/tree/main.c
--- linux-2.4.6-pre8/arch/ppc/boot/tree/main.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/tree/main.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.main.c 1.9 06/15/01 13:16:10 paulus
  */
 /*
  *    Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
@@ -74,16 +74,6 @@
 
 #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 */
@@ -91,15 +81,11 @@
 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).
- */
+/* Needed for serial I/O.
+*/
+extern unsigned long *com_port;
 
+bd_t	board_info;
 
 /*
 ** The bootrom may change bootrom_cmdline to point to a buffer in the
@@ -116,35 +102,16 @@
 
 /* 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;
+extern void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp);
 
 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)
+kick_watchdog(void)
 {
- return ((*uart0_lsr & LSR_DR) != 0);
+#ifdef CONFIG_405GP
+    mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
+#endif
 }
 
-
 void start(void)
 {
     void *options;
@@ -156,40 +123,34 @@
     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 */
 
 
+    com_port = (struct NS16550 *)serial_init(0);
 
-#if defined(CONFIG_WALNUT)
-    /* turn off ethernet */
+#ifdef CONFIG_405GP
+    /* turn off on-chip 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;
+ 
+    {
+	/* Physical mapping of ethernet register space. */
+	static struct   ppc405_enet_regs *ppc405_enet_regp =
+	(struct ppc405_enet_regs *)PPC405_EM0_REG_ADDR;
+
+	mtdcr(DCRN_MALCR, MALCR_MMSR);                /* 1st reset MAL */
+
+	while (mfdcr(DCRN_MALCR) & MALCR_MMSR) {};    /* wait for the reset */
+    
+	ppc405_enet_regp->em0mr0 = 0x20000000;        /* then reset EMAC */
     }
 #endif
 
-
     if ((bip = get_board_info()) != NULL)
 	    memcpy(&board_info, bip, sizeof(bd_t));
 
     /* Init RAM disk (initrd) section */
 
+    kick_watchdog();
+
     if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) {
         initrd_start = (RAM_END - initrd_size) & ~0xFFF;
 
@@ -208,6 +169,8 @@
 
     /* Linux kernel image section */
 	
+    kick_watchdog();
+
     im = (unsigned char *)(imageSect_start);
     len = imageSect_size;
     dst = (void *)PROG_START;
@@ -233,6 +196,7 @@
 	memmove(dst, im, len);
     }
 
+    kick_watchdog();
 
     flush_cache(dst, len);
 
diff -urN linux-2.4.6-pre8/arch/ppc/boot/utils/mkevimg linux/arch/ppc/boot/utils/mkevimg
--- linux-2.4.6-pre8/arch/ppc/boot/utils/mkevimg	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/utils/mkevimg	Mon Dec  3 22:50:37 2001
@@ -23,7 +23,8 @@
 #	 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];
+#	 unsigned long checksum; 	32 bit checksum including header
+#	 unsigned long reserved[2];
 #      } boot_block_t;
 #
 #   
@@ -61,6 +62,7 @@
   }
 
   if ($status != 1) {
+    print("  -c         Put checksum in load information block.\n");
     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");
@@ -148,10 +150,14 @@
 
 sub decode_options {
 
-  if (!getopts("hlvV")) {
+  if (!getopts("chlvV")) {
     usage(1);
   }
 
+  if ($opt_c) {
+    $do_checksum = 1;
+  }
+
   if ($opt_h) {
     usage(0);
   }
@@ -360,14 +366,20 @@
     $output_size += $initrd_size;
   }
 
-  $num_blocks = $output_size / 512 + 1;
+  # 
+  # Compute size with header 
+  #
+
+  $header = pack("H8N7", "0052504f", 0, 0, 0, 0, 0, 0, 0);
+  $num_blocks = ($output_size + length($header) + 511) / 512;
 
   #
   # Write IBM PowerPC evaluation board boot_block_t header
   #
 
   $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0,
-		 $text_addr, 0, 0, 0);
+                 $text_addr, 0, 0, 0);
+
 
   $bytes = length($header);
   
@@ -412,18 +424,57 @@
 
   #
   # Pad to a multiple of 512 bytes
+  #  If the (size of the boot image mod 512) is between 509 and 511 bytes
+  #  then the tftp to the Walnut fails.  This may be fixed in more recent
+  #  Walnut bootrom.
   #
 
-  $pad_size = 512 - (length($header) + $output_size) % 512;
+  $pad_size = 512 - ((length($header) + $output_size) % 512);
+  if ($pad_size == 512) {
+    $pad_size = 0;
+  }
+
+  if ($pad_size != 0) {
+  
+    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";
 
-  if ($verbose) {
-    print("Padding boot image by an additional $pad_size bytes.\n");
   }
 
-  $pad_string = pack(("H8","deadbeef") x 128);
+  # 
+  # Compute 32 bit checksum over entire file.
+  #
+
+  if ($do_checksum) {
 
-  syswrite(BOOT, $pad_string, $pad_size) or
-    die "Could not pad boot image in output file.\n";
+    close(BOOT);
+    open(BOOT, "+<$ofile") || die "Cannot open output file";
+    undef $/;
+    $temp = unpack("%32N*", <BOOT>);
+    # Solaris and PPC Linux return 0x80000000 for "-$temp" when $temp
+    # is negative.  "~($temp - 1)" negates $temp properly.
+    $csum = ~($temp - 1);
+    printf("Checksum    = 0x%08x\r\n", $csum);
+
+    #
+    # Rewrite IBM PowerPC evaluation board boot_block_t header,
+    # this time with the checksum included
+    #
+
+    $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0,
+                    $text_addr, $csum, 0, 0);
+
+    seek(BOOT, 0, 0);
+    syswrite(BOOT, $header, length($header)) or
+         die("Could not write boot image header to output file.");
+
+  }
 
   #
   # Clean-up and leave
diff -urN linux-2.4.6-pre8/arch/ppc/config.in linux/arch/ppc/config.in
--- linux-2.4.6-pre8/arch/ppc/config.in	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/config.in	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.config.in 1.24 05/21/01 00:48:24 cort
+# BK Id: SCCS/s.config.in 1.30 06/27/01 14:49:58 trini
 #
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
@@ -84,9 +84,9 @@
 
 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
+	"CHRP/PowerMac/PReP	CONFIG_ALL_PPC		\
+  	 Amgia-APUS		CONFIG_APUS		\
+	 Synergy-Gemini        	CONFIG_GEMINI"		CHRP/PowerMac/PReP
 fi
 
 if [ "$CONFIG_PPC64BRIDGE" != "y" ]; then
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux-2.4.6-pre8/arch/ppc/kernel/Makefile	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/kernel/Makefile	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.19 05/26/01 14:48:14 paulus
+# BK Id: SCCS/s.Makefile 1.22 06/28/01 08:01:06 trini
 #
 #
 # Makefile for the linux kernel.
@@ -39,11 +39,7 @@
 obj-$(CONFIG_POWER4)		+= xics.o
 obj-$(CONFIG_PCI)		+= pci.o pci-dma.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
-obj-$(CONFIG_PMAC_PBOOK)	+= sleep.o
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_PPC_RTAS)		+= error_log.o proc_rtas.o
-obj-$(CONFIG_NVRAM)		+= pmac_nvram.o
-obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
 obj-$(CONFIG_4xx)		+= ppc4xx_pic.o
 obj-$(CONFIG_OAK)		+= oak_setup.o
 obj-$(CONFIG_WALNUT)		+= walnut_setup.o
@@ -52,12 +48,10 @@
 endif
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
 ifeq ($(CONFIG_8xx),y)
-obj-$(CONFIG_PCI)		+= qspan_pci.c
+obj-$(CONFIG_PCI)		+= qspan_pci.o
 ifndef CONFIG_MATH_EMULATION
 obj-y				+= softemu8xx.o
 endif
-else
-obj-y				+= hashtable.o
 endif
 obj-$(CONFIG_MBX)		+= i8259.o
 obj-$(CONFIG_APUS)		+= apus_setup.o
@@ -69,7 +63,11 @@
 					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_NVRAM)		+= pmac_nvram.o
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
+obj-$(CONFIG_PMAC_PBOOK)	+= sleep.o
+obj-$(CONFIG_PPC_RTAS)		+= error_log.o proc_rtas.o
+obj-$(CONFIG_PREP_RESIDUAL)	+= residual.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 -urN linux-2.4.6-pre8/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- linux-2.4.6-pre8/arch/ppc/kernel/chrp_pci.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/kernel/chrp_pci.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.chrp_pci.c 1.16 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.chrp_pci.c 1.17 06/28/01 16:11:56 paulus
  */
 /*
  * CHRP pci routines.
@@ -27,11 +27,6 @@
 #include "open_pic.h"
 #include "pci.h"
 
-
-#ifdef CONFIG_POWER4
-extern unsigned long pci_address_offset(int, unsigned int);
-#endif /* CONFIG_POWER4 */
-
 /* LongTrail */
 #define pci_config_addr(dev, offset) \
 (GG2_PCI_CONFIG_BASE | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
@@ -212,34 +207,6 @@
 	return 1;
 }
 
-#ifdef CONFIG_POWER4
-static void
-power4_fixup_dev(struct pci_dev *dev)
-{
-	int i;
-	unsigned long offset;
-
-	for (i = 0; i < 6; ++i) {
-		if (dev->resource[i].start == 0)
-			continue;
-		offset = pci_address_offset(dev->bus->number,
-					    dev->resource[i].flags);
-		if (offset) {
-			dev->resource[i].start += offset;
-			dev->resource[i].end += offset;
-			printk("device %x.%x[%d] now [%lx..%lx]\n",
-			       dev->bus->number, dev->devfn, i,
-			       dev->resource[i].start,
-			       dev->resource[i].end);
-		}
-		/* zap the 2nd function of the winbond chip */
-		if (dev->resource[i].flags & IORESOURCE_IO
-		    && dev->bus->number == 0 && dev->devfn == 0x81)
-			dev->resource[i].flags &= ~IORESOURCE_IO;
-	}
-}
-#endif /* CONFIG_POWER4 */
-
 void __init
 chrp_pcibios_fixup(void)
 {
@@ -261,48 +228,9 @@
 			pci_write_config_word(dev, PCI_VENDOR_ID,
 					      PCI_VENDOR_ID_AMD);
 		}
-#ifdef CONFIG_POWER4
-		power4_fixup_dev(dev);
-#endif
 	}
 }
 
-#if 0
-static struct {
-    /* parent is iomem */
-    struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash;
-    /* parent is isa_mem */
-    struct resource nvram;
-} gg2_resources = {
-    ram:	{ "RAM", 0x00000000, 0xbfffffff, IORESOURCE_MEM },
-    pci_mem:	{ "GG2 PCI mem", 0xc0000000, 0xf6ffffff, IORESOURCE_MEM },
-    isa_mem:	{ "GG2 ISA mem", 0xf7000000, 0xf7ffffff },
-    pci_io:	{ "GG2 PCI I/O", 0xf8000000, 0xf8ffffff },
-    pci_cfg:	{ "GG2 PCI cfg", 0xfec00000, 0xfec7ffff },
-    rom_exp:	{ "ROM exp", 0xff000000, 0xff7fffff, },
-    flash:	{ "Flash ROM", 0xfff80000, 0xffffffff },
-    nvram:	{ "NVRAM", 0xf70e0000, 0xf70e7fff },
-};
-
-static void __init gg2_pcibios_fixup(void)
-{
-	int i;
-	extern unsigned long *end_of_DRAM;
-
-	chrp_pcibios_fixup();
-	gg2_resources.ram.end = (unsigned long)end_of_DRAM-PAGE_OFFSET;
-	for (i = 0; i < 7; i++)
-	    request_resource(&iomem_resource,
-		    	     &((struct resource *)&gg2_resources)[i]);
-	request_resource(&gg2_resources.isa_mem, &gg2_resources.nvram);
-}
-
-static void __init gg2_pcibios_fixup_bus(struct pci_bus *bus)
-{
-    	bus->resource[1] = &gg2_resources.pci_mem;
-}
-#endif /* 0 */
-
 /* this is largely modeled and stolen after the pmac_pci code -- tgall
  */
 
@@ -314,14 +242,16 @@
 	struct pci_controller *hose;
 	volatile unsigned char *cfg;
 	unsigned int *dma;
-#ifdef CONFIG_POWER3
 	struct device_node *root = find_path_device("/");
+#ifdef CONFIG_POWER3
 	unsigned int *opprop = (unsigned int *)
 		get_property(root, "platform-open-pic", NULL);
 	int i;
 #endif
 
 	for(; dev != NULL; dev = dev->next, ++index) {
+		if (dev->parent != root)
+			continue;
 		if (dev->n_addrs < 1) {
 			printk(KERN_WARNING "Can't use %s: no address\n",
 			       dev->full_name);
@@ -374,23 +304,6 @@
 	}
 }
 
-#ifdef CONFIG_POWER4
-void __init
-power4_add_bridge(void)
-{
-	struct pci_controller* hose;
-
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-	
-	hose->ops = &rtas_pci_ops;
-	pci_dram_offset = 0;
-}
-#endif /* CONFIG_POWER4 */
-
 void __init
 chrp_find_bridges(void)
 {
@@ -400,9 +313,6 @@
 
 	ppc_md.pcibios_fixup = chrp_pcibios_fixup;
 
-#ifdef CONFIG_POWER4
-	power4_add_bridge();
-#else /* CONFIG_POWER4 */
 	model = get_property(find_path_device("/"), "model", NULL);
         if (!strncmp("MOT", model, 3)) {
 		struct pci_controller *hose;
@@ -452,36 +362,4 @@
 	hose->ops = &gg2_pci_ops;
 	pci_dram_offset = 0;
 	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 */
 }
-
-#ifdef CONFIG_PPC64BRIDGE
-#ifdef CONFIG_POWER4
-/*
- * Hack alert!!!
- * 64-bit machines like POWER3 and POWER4 have > 32 bit
- * physical addresses.  For now we remap particular parts
- * of the 32-bit physical address space that the Linux
- * page table gives us into parts of the physical address
- * space above 4GB so we can access the I/O devices.
- */
-unsigned long pci_address_offset(int busnr, unsigned int flags)
-{
-	unsigned long offset = 0;
-
-	if (busnr >= 0x1e) {
-		if (flags & IORESOURCE_IO)
-			offset = -0x100000;
-		else if (flags & IORESOURCE_MEM)
-			offset = 0x38000000;
-	} else if (busnr <= 0xf) {
-		if (flags & IORESOURCE_MEM)
-			offset = -0x40000000;
-		else
-	}
-	return offset;
-}
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_PPC64BRIDGE */
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux-2.4.6-pre8/arch/ppc/kernel/entry.S	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/kernel/entry.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.entry.S 1.15 06/09/01 22:16:38 paulus
+ * BK Id: SCCS/s.entry.S 1.17 06/19/01 22:40:51 paulus
  */
 /*
  *  PowerPC version 
@@ -283,6 +283,7 @@
 	 */ 
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
 	
 	lwz	r0,_MSR(r1)
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
--- linux-2.4.6-pre8/arch/ppc/kernel/feature.c	Fri May 25 12:41:46 2001
+++ linux/arch/ppc/kernel/feature.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.feature.c 1.10 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.feature.c 1.14 06/17/01 09:33:37 trini
  */
 /*
  *  arch/ppc/kernel/feature.c
@@ -288,11 +288,11 @@
   {	"AAPL,PowerBook1998",	FTR_CAN_SLEEP			}, /* Wallstreet PowerBook */
   {	"PowerBook1,1",		FTR_CAN_SLEEP			}, /* 101 (Lombard) PowerBook */
   {	"PowerBook2,1",		FTR_CAN_SLEEP 			}, /* iBook */
+  {	"PowerBook4,1",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* iBook Dual USB */
   {	"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 }
 };
 
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S
--- linux-2.4.6-pre8/arch/ppc/kernel/hashtable.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/hashtable.S	Wed Dec 31 16:00:00 1969
@@ -1,724 +0,0 @@
-/*
- * BK Id: SCCS/s.hashtable.S 1.11 05/17/01 18:14:21 cort
- */
-/*
- *  arch/ppc/kernel/hashtable.S
- *
- *  PowerPC version 
- *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
- *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
- *  Adapted for Power Macintosh by Paul Mackerras.
- *  Low-level exception handlers and MMU support
- *  rewritten by Paul Mackerras.
- *    Copyright (C) 1996 Paul Mackerras.
- *
- *  This file contains low-level assembler routines for managing
- *  the PowerPC MMU hash table.  (PPC 8xx processors don't use a
- *  hash table, so this file is not used on them.)
- *
- *  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 "ppc_asm.h"
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <linux/config.h>
-
-/*
- * Load a PTE into the hash table, if possible.
- * The address is in r3, and r4 contains access flags:
- * _PAGE_USER (4) if a user-mode access, ored with
- * _PAGE_RW (2) if a write.  r20 contains DSISR or SRR1,
- * so bit 1 (0x40000000) is set if the exception was due
- * to no matching PTE being found in the hash table.
- * SPRG3 contains the physical address of the current task's thread.
- *
- * Returns to the caller if the access is illegal or there is no
- * mapping for the address.  Otherwise it places an appropriate PTE
- * in the hash table and returns from the exception.
- * Uses r0, r2 - r6, ctr, lr.
- *
- * For speed, 4 of the instructions get patched once the size and
- * physical address of the hash table are known.  These definitions
- * of Hash_base and Hash_bits below are just an example.
- */
-Hash_base = 0x180000
-Hash_bits = 12				/* e.g. 256kB hash table */
-Hash_msk = (((1 << Hash_bits) - 1) * 64)
-	
-	.globl	hash_page
-hash_page:
-#ifdef CONFIG_PPC64BRIDGE
-	mfmsr	r0
-	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	MTMSRD(r0)
-	isync
-#endif
-#ifdef CONFIG_SMP
-	SAVE_2GPRS(7,r21)
-	eieio
-	lis	r2,hash_table_lock@h
-	ori	r2,r2,hash_table_lock@l
- 	tophys(r2,r2)
-	lis	r6,0x0fff0000@h
-	mtctr	r6
-	mfspr	r5,SPRG3
-	lwz	r0,PROCESSOR-THREAD(r5)
-	or	r0,r0,r6
-10:	lwarx	r6,0,r2
-	cmpi	0,r6,0
-	bne-	12f
-	stwcx.	r0,0,r2
-	beq+	11f
-	/* spin here a bit */
-12:	mfctr	r7
-	li	r8,1000
-	mtctr	r8
-13:
-	bdnz	13b
-	mtctr	r7
-	cmpw	r6,r0
-	bdnzf	2,10b
-	tw	31,31,31
-11:	eieio
-	REST_2GPRS(7, r21)
-#endif
-	/* Get PTE (linux-style) and check access */
-	lis	r0,KERNELBASE@h		/* check if kernel address */
-	cmplw	0,r3,r0
-	mfspr	r2,SPRG3		/* current task's THREAD (phys) */
-	lwz	r5,PGDIR(r2)		/* virt page-table root */
-	blt+	112f			/* assume user more likely */
-	lis	r5,swapper_pg_dir@ha	/* if kernel address, use */
-	addi	r5,r5,swapper_pg_dir@l	/* kernel page table */
-112:	tophys(r5,r5)			/* convert to phys addr */
-	rlwimi	r5,r3,12,20,29		/* insert top 10 bits of address */
-	lwz	r5,0(r5)		/* get pmd entry */
-	rlwinm.	r5,r5,0,0,19		/* extract address of pte page */
-#ifdef CONFIG_SMP
-	beq-	hash_page_out		/* return if no mapping */
-#else
-	/* XXX it seems like the 601 will give a machine fault on the
-	   rfi if its alignment is wrong (bottom 4 bits of address are
-	   8 or 0xc) and we have had a not-taken conditional branch
-	   to the address following the rfi. */
-	beqlr-
-#endif
-	tophys(r2,r5)
-	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	ori	r4,r4,1			/* set _PAGE_PRESENT bit in access */
-	rlwinm	r5,r4,5,24,24		/* _PAGE_RW access -> _PAGE_DIRTY */
-	rlwimi	r5,r4,7,22,22		/* _PAGE_RW -> _PAGE_HWWRITE */
-	ori	r5,r5,0x100		/* set _PAGE_ACCESSED */
-retry:
-	lwz	r6,0(r2)		/* get linux-style pte */
-	andc.	r0,r4,r6		/* check access & ~permission */
-#ifdef CONFIG_SMP
-	bne-	hash_page_out		/* return if access not permitted */
-#else
-	bnelr-
-#endif
-	andc.	r0,r5,r6		/* any bits not yet set? */
-	beq	2f
-
-	/* Update the linux PTE atomically */
-	lwarx	r0,0,r2			/* refetch the pte and check */
-	cmpw	0,r0,r6			/* that it hasn't been changed */
-	bne-	retry			/* retry if it has */
-	or	r6,r6,r5		/* set accessed/dirty bits */
-	stwcx.	r6,0,r2			/* attempt to update PTE */
-	bne-	retry			/* retry if someone got there first */
-
-	/* Convert linux-style PTE to low word of PPC-style PTE */
-2:	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r4,r4,0xe04		/* clear out reserved bits */
-	andc	r6,r6,r4		/* PP=2 or 0, when _PAGE_HWWRITE */
-
-#ifdef CONFIG_POWER4
-	/*
-	 * XXX hack hack hack - translate 32-bit "physical" addresses
-	 * in the linux page tables to 42-bit real addresses in such
-	 * a fashion that we can get at the I/O we need to access.
-	 *	-- paulus
-	 */
-	cmpwi	0,r6,0
-	rlwinm	r4,r6,16,16,30
-	bge	57f
-	cmplwi	0,r4,0xfe00
-	li	r5,0x3fd
-	bne	56f
-	li	r5,0x3ff
-56:	sldi	r5,r5,32
-	or	r6,r6,r5
-57:
-#endif
-
-#ifdef CONFIG_PPC64BRIDGE
-	/* Construct the high word of the PPC-style PTE */
-	mfsrin	r5,r3			/* get segment reg for segment */
-	rlwinm	r5,r5,0,5,31
-	sldi	r5,r5,12
-	ori	r5,r5,1			/* set V (valid) bit */
-	rlwimi	r5,r3,16,20,24		/* put in API (abbrev page index) */
-	/* Get the address of the primary PTE group in the hash table */
-	.globl	hash_page_patch_A
-hash_page_patch_A:
-	lis	r4,Hash_base@h		/* base address of hash table */
-	rlwimi	r4,r5,32-5,25-Hash_bits,24	/* (VSID & hash_mask) << 7 */
-	rlwinm	r0,r3,32-5,25-Hash_bits,24	/* (PI & hash_mask) << 7 */
-	xor	r4,r4,r0		/* make primary hash */
-	li	r2,8			/* PTEs/group */
-
-#ifndef CONFIG_SMP
-	/* We don't do this for SMP - another cpu could have put in
-	   the appropriate PTE since we took the exception.  -- paulus. */
-	/* See whether it was a PTE not found exception or a
-	   protection violation. */
-	andis.	r0,r20,0x4000
-	bne	10f			/* no PTE: go look for an empty slot */
-#endif /* CONFIG_SMP */
-	tlbie	r3			/* invalidate TLB entry */
-
-	/* Search the primary PTEG for a PTE whose 1st dword matches r5 */
-	mtctr	r2
-	addi	r3,r4,-16
-1:	ldu	r0,16(r3)		/* get next PTE */
-	cmpd	0,r0,r5
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_slot
-
-	/* Search the secondary PTEG for a matching PTE */
-	ori	r5,r5,0x2		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_B
-hash_page_patch_B:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xff80
-	addi	r3,r3,-16
-	mtctr	r2
-2:	ldu	r0,16(r3)
-	cmpd	0,r0,r5
-	bdnzf	2,2b
-	beq+	found_slot
-	xori	r5,r5,0x2		/* clear H bit again */
-
-	/* Search the primary PTEG for an empty slot */
-10:	mtctr	r2
-	addi	r3,r4,-16		/* search primary PTEG */
-1:	ldu	r0,16(r3)		/* get next PTE */
-	andi.	r0,r0,1
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_empty
-
-	/* Search the secondary PTEG for an empty slot */
-	ori	r5,r5,0x2		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_C
-hash_page_patch_C:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xff80
-	addi	r3,r3,-16
-	mtctr	r2
-2:	ldu	r0,16(r3)
-	andi.	r0,r0,1
-	bdnzf	2,2b
-	beq+	found_empty
-
-	/*
-	 * Choose an arbitrary slot in the primary PTEG to overwrite.
-	 * Since both the primary and secondary PTEGs are full, and we
-	 * have no information that the PTEs in the primary PTEG are
-	 * more important or useful than those in the secondary PTEG,
-	 * and we know there is a definite (although small) speed
-	 * advantage to putting the PTE in the primary PTEG, we always
-	 * put the PTE in the primary PTEG.
-	 */
-	xori	r5,r5,0x2		/* clear H bit again */
-	lis	r3,next_slot@ha
-	tophys(r3,r3)
-	lwz	r2,next_slot@l(r3)
-	addi	r2,r2,16
-	andi.	r2,r2,0x70
-#ifdef CONFIG_POWER4
-	/*
-	 * Since we don't have BATs on POWER4, we rely on always having
-	 * PTEs in the hash table to map the hash table and the code
-	 * that manipulates it in virtual mode, namely flush_hash_page and
-	 * flush_hash_segments.  Otherwise we can get a DSI inside those
-	 * routines which leads to a deadlock on the hash_table_lock on
-	 * SMP machines.  We avoid this by never overwriting the first
-	 * PTE of each PTEG if it is already valid.
-	 *	-- paulus.
-	 */
-	bne	102f
-	li	r2,0x10
-102:
-#endif /* CONFIG_POWER4 */
-	stw	r2,next_slot@l(r3)
-	add	r3,r4,r2
-11:
-	/* update counter of evicted pages */
-	lis	r2,htab_evicts@ha
-	tophys(r2,r2)
-	lwz	r4,htab_evicts@l(r2)
-	addi	r4,r4,1
-	stw	r4,htab_evicts@l(r2)
-
-#ifndef CONFIG_SMP
-	/* Store PTE in PTEG */
-found_empty:
-	std	r5,0(r3)
-found_slot:
-	std	r6,8(r3)
-
-#else /* CONFIG_SMP */
-/*
- * Between the tlbie above and updating the hash table entry below,
- * another CPU could read the hash table entry and put it in its TLB.
- * There are 3 cases:
- * 1. using an empty slot
- * 2. updating an earlier entry to change permissions (i.e. enable write)
- * 3. taking over the PTE for an unrelated address
- *
- * In each case it doesn't really matter if the other CPUs have the old
- * PTE in their TLB.  So we don't need to bother with another tlbie here,
- * which is convenient as we've overwritten the register that had the
- * address. :-)  The tlbie above is mainly to make sure that this CPU comes
- * and gets the new PTE from the hash table.
- *
- * We do however have to make sure that the PTE is never in an invalid
- * state with the V bit set.
- */
-found_empty:
-found_slot:
-	li	r0,1
-	andc	r5,r5,r0	/* clear V (valid) bit in PTE */
-	std	r5,0(r3)
-	sync
-	tlbsync
-	sync
-	std	r6,8(r3)	/* put in correct RPN, WIMG, PP bits */
-	sync
-	ori	r5,r5,1
-	std	r5,0(r3)	/* finally set V bit in PTE */
-#endif /* CONFIG_SMP */
-
-#else /* CONFIG_PPC64BRIDGE */
-
-	/* Construct the high word of the PPC-style PTE */
-	mfsrin	r5,r3			/* get segment reg for segment */
-	rlwinm	r5,r5,7,1,24		/* put VSID in 0x7fffff80 bits */
-	oris	r5,r5,0x8000		/* set V (valid) bit */
-	rlwimi	r5,r3,10,26,31		/* put in API (abbrev page index) */
-	/* Get the address of the primary PTE group in the hash table */
-	.globl	hash_page_patch_A
-hash_page_patch_A:
-	lis	r4,Hash_base@h		/* base address of hash table */
-	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
-	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
-	xor	r4,r4,r0		/* make primary hash */
-	li	r2,8			/* PTEs/group */
-
-#ifndef CONFIG_SMP
-	/* We don't do this for SMP - another cpu could have put in
-	   the appropriate PTE since we took the exception.  -- paulus. */
-	/* See whether it was a PTE not found exception or a
-	   protection violation. */
-	andis.	r0,r20,0x4000
-	bne	10f			/* no PTE: go look for an empty slot */
-#endif /* CONFIG_SMP */
-	tlbie	r3			/* invalidate TLB entry */
-
-	/* Search the primary PTEG for a PTE whose 1st word matches r5 */
-	mtctr	r2
-	addi	r3,r4,-8
-1:	lwzu	r0,8(r3)		/* get next PTE */
-	cmp	0,r0,r5
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_slot
-
-	/* Search the secondary PTEG for a matching PTE */
-	ori	r5,r5,0x40		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_B
-hash_page_patch_B:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xffc0
-	addi	r3,r3,-8
-	mtctr	r2
-2:	lwzu	r0,8(r3)
-	cmp	0,r0,r5
-	bdnzf	2,2b
-	beq+	found_slot
-	xori	r5,r5,0x40		/* clear H bit again */
-
-	/* Search the primary PTEG for an empty slot */
-10:	mtctr	r2
-	addi	r3,r4,-8		/* search primary PTEG */
-1:	lwzu	r0,8(r3)		/* get next PTE */
-	rlwinm.	r0,r0,0,0,0		/* only want to check valid bit */
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_empty
-
-	/* Search the secondary PTEG for an empty slot */
-	ori	r5,r5,0x40		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_C
-hash_page_patch_C:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xffc0
-	addi	r3,r3,-8
-	mtctr	r2
-2:
-	lwzu	r0,8(r3)
-	rlwinm.	r0,r0,0,0,0		/* only want to check valid bit */
-	bdnzf	2,2b
-	beq+	found_empty
-
-	/*
-	 * Choose an arbitrary slot in the primary PTEG to overwrite.
-	 * Since both the primary and secondary PTEGs are full, and we
-	 * have no information that the PTEs in the primary PTEG are
-	 * more important or useful than those in the secondary PTEG,
-	 * and we know there is a definite (although small) speed
-	 * advantage to putting the PTE in the primary PTEG, we always
-	 * put the PTE in the primary PTEG.
-	 */
-	xori	r5,r5,0x40		/* clear H bit again */
-	lis	r3,next_slot@ha
-	tophys(r3,r3)
-	lwz	r2,next_slot@l(r3)
-	addi	r2,r2,8
-	andi.	r2,r2,0x38
-	stw	r2,next_slot@l(r3)
-	add	r3,r4,r2
-11:		
-	/* update counter of evicted pages */
-	lis	r2,htab_evicts@ha
-	tophys(r2,r2)
-	lwz	r4,htab_evicts@l(r2)
-	addi	r4,r4,1
-	stw	r4,htab_evicts@l(r2)
-
-#ifndef CONFIG_SMP
-	/* Store PTE in PTEG */
-found_empty:
-	stw	r5,0(r3)
-found_slot:
-	stw	r6,4(r3)
-
-#else /* CONFIG_SMP */
-/*
- * Between the tlbie above and updating the hash table entry below,
- * another CPU could read the hash table entry and put it in its TLB.
- * There are 3 cases:
- * 1. using an empty slot
- * 2. updating an earlier entry to change permissions (i.e. enable write)
- * 3. taking over the PTE for an unrelated address
- *
- * In each case it doesn't really matter if the other CPUs have the old
- * PTE in their TLB.  So we don't need to bother with another tlbie here,
- * which is convenient as we've overwritten the register that had the
- * address. :-)  The tlbie above is mainly to make sure that this CPU comes
- * and gets the new PTE from the hash table.
- *
- * We do however have to make sure that the PTE is never in an invalid
- * state with the V bit set.
- */
-found_empty:
-found_slot:
-	rlwinm	r5,r5,0,1,31	/* clear V (valid) bit in PTE */
-	stw	r5,0(r3)
-	sync
-	tlbsync
-	sync
-	stw	r6,4(r3)	/* put in correct RPN, WIMG, PP bits */
-	sync
-	oris	r5,r5,0x8000
-	stw	r5,0(r3)	/* finally set V bit in PTE */
-#endif /* CONFIG_SMP */
-#endif /* CONFIG_PPC64BRIDGE */
-
-	sync		/* make sure pte updates get to memory */
-
-/*
- * Update the hash table miss count.  We only want misses here
- * that _are_ valid addresses and have a pte otherwise we don't
- * count it as a reload.  do_page_fault() takes care of bad addrs
- * and entries that need linux-style pte's created.
- *
- * safe to use r2 here since we're not using it as current yet 
- * update the htab misses count
- *   -- Cort
- */
-	lis	r2,htab_reloads@ha
-	tophys(r2,r2)
-	lwz	r3,htab_reloads@l(r2)
-	addi	r3,r3,1
-	stw	r3,htab_reloads@l(r2)
-
-#ifdef CONFIG_SMP
-	lis	r2,hash_table_lock@ha
-	tophys(r2,r2)
-	li	r0,0
-	stw	r0,hash_table_lock@l(r2)
-	eieio
-#endif
-
-	/* Return from the exception */
-	lwz	r3,_CCR(r21)
-	lwz	r4,_LINK(r21)
-	lwz	r5,_CTR(r21)
-	mtcrf	0xff,r3
-	mtlr	r4
-	mtctr	r5
-	lwz	r0,GPR0(r21)
-	lwz	r1,GPR1(r21)
-	lwz	r2,GPR2(r21)
-	lwz	r3,GPR3(r21)
-	lwz	r4,GPR4(r21)
-	lwz	r5,GPR5(r21)
-	lwz	r6,GPR6(r21)
-	/* we haven't used xer */
-	mtspr	SRR1,r23
-	mtspr	SRR0,r22
-	lwz	r20,GPR20(r21)
-	lwz	r22,GPR22(r21)
-	lwz	r23,GPR23(r21)
-	lwz	r21,GPR21(r21)
-	RFI
-	
-#ifdef CONFIG_SMP
-hash_page_out:
-	lis	r2,hash_table_lock@ha
-	tophys(r2,r2)
-	li	r0,0
-	stw	r0,hash_table_lock@l(r2)
-	eieio
-	blr
-
-	.data
-	.globl	hash_table_lock
-hash_table_lock:
-	.long	0
-#endif /* CONFIG_SMP */
-
-	.data
-next_slot:
-	.long	0
-
-	.text
-/*
- * Flush entries from the hash table with VSIDs in the range
- * given.
- */
-_GLOBAL(flush_hash_segments)
-	lis	r5,Hash@ha
-	lwz	r5,Hash@l(r5)		/* base of hash table */
-	cmpwi	0,r5,0
-	bne+	99f
-	tlbia
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-#endif
-	blr
-99:
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	/* Note - we had better not do anything which could generate
-	   a hash table miss while we have the hash table locked,
-	   or we'll get a deadlock.  -paulus */
-	mfmsr	r10
-	SYNC
-	rlwinm	r0,r10,0,17,15	/* clear bit 16 (MSR_EE) */
-	mtmsr	r0
-	SYNC
-#endif
-#ifdef CONFIG_SMP
-	lis	r9,hash_table_lock@h
-	ori	r9,r9,hash_table_lock@l
-	lwz	r8,PROCESSOR(r2)
-	oris	r8,r8,8
-10:	lwarx	r6,0,r9
-	cmpi	0,r6,0
-	bne-	10b
-	stwcx.	r8,0,r9
-	bne-	10b
-	eieio
-#endif
-#ifndef CONFIG_PPC64BRIDGE
-	rlwinm	r3,r3,7,1,24		/* put VSID lower limit in position */
-	oris	r3,r3,0x8000		/* set V bit */
-	rlwinm	r4,r4,7,1,24		/* put VSID upper limit in position */
-	oris	r4,r4,0x8000
-	ori	r4,r4,0x7f
-	lis	r6,Hash_size@ha
-	lwz	r6,Hash_size@l(r6)	/* size in bytes */
-	srwi	r6,r6,3			/* # PTEs */
-	mtctr	r6
-	addi	r5,r5,-8
-	li	r0,0
-1:	lwzu	r6,8(r5)		/* get next tag word */
-	cmplw	0,r6,r3
-	cmplw	1,r6,r4
-	cror	0,0,5			/* set cr0.lt if out of range */
-	blt	2f			/* branch if out of range */
-	stw	r0,0(r5)		/* invalidate entry */
-2:	bdnz	1b			/* continue with loop */
-#else /* CONFIG_PPC64BRIDGE */
-	rldic	r3,r3,12,20		/* put VSID lower limit in position */
-	ori	r3,r3,1			/* set V bit */
-	rldic	r4,r4,12,20		/* put VSID upper limit in position */
-	ori	r4,r4,0xfff		/* set V bit, API etc. */
-	lis	r6,Hash_size@ha
-	lwz	r6,Hash_size@l(r6)	/* size in bytes */
-	srwi	r6,r6,4			/* # PTEs */
-	mtctr	r6
-	addi	r5,r5,-16
-	li	r0,0
-1:	ldu	r6,16(r5)		/* get next tag word */
-	cmpld	0,r6,r3
-	cmpld	1,r6,r4
-	cror	0,0,5			/* set cr0.lt if out of range */
-	blt	2f			/* branch if out of range */
-	std	r0,0(r5)		/* invalidate entry */
-2:	bdnz	1b			/* continue with loop */
-#endif /* CONFIG_PPC64BRIDGE */
-
-	sync
-	tlbia
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-	lis	r3,hash_table_lock@ha
-	stw	r0,hash_table_lock@l(r3)
-#endif
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	mtmsr	r10
-	SYNC
-#endif
-	blr
-
-/*
- * Flush the entry for a particular page from the hash table.
- *
- * flush_hash_page(unsigned context, unsigned long va)
- */
-_GLOBAL(flush_hash_page)
-	lis	r6,Hash@ha
-	lwz	r6,Hash@l(r6)		/* hash table base */
-	cmpwi	0,r6,0			/* hash table in use? */
-	bne+	99f
-	tlbie	r4			/* in hw tlb too */
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-#endif
-	blr
-99:
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	/* Note - we had better not do anything which could generate
-	   a hash table miss while we have the hash table locked,
-	   or we'll get a deadlock.  -paulus */
-	mfmsr	r10
-	SYNC
-	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
-	mtmsr	r0
-	SYNC
-#endif
-#ifdef CONFIG_SMP
-	lis	r9,hash_table_lock@h
-	ori	r9,r9,hash_table_lock@l
-	lwz	r8,PROCESSOR(r2)
-	oris	r8,r8,9
-10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
-	bne-	11f
-	stwcx.	r8,0,r9
-	beq+	12f
-11:	lwz	r7,0(r9)
-	cmpi	0,r7,0
-	beq	10b
-	b	11b
-12:	eieio
-#endif
-#ifndef CONFIG_PPC64BRIDGE
-	rlwinm	r3,r3,11,1,20		/* put context into vsid */
-	rlwimi	r3,r4,11,21,24		/* put top 4 bits of va into vsid */
-	oris	r3,r3,0x8000		/* set V (valid) bit */
-	rlwimi	r3,r4,10,26,31		/* put in API (abbrev page index) */
-	rlwinm	r7,r4,32-6,10,25	/* get page index << 6 */
-	rlwinm	r5,r3,32-1,7,25		/* vsid << 6 */
-	xor	r7,r7,r5		/* primary hash << 6 */
-	lis	r5,Hash_mask@ha
-	lwz	r5,Hash_mask@l(r5)	/* hash mask */
-	slwi	r5,r5,6			/*  << 6 */
-	and	r7,r7,r5
-	add	r6,r6,r7		/* address of primary PTEG */
-	li	r8,8
-	mtctr	r8
-	addi	r7,r6,-8
-1:	lwzu	r0,8(r7)		/* get next PTE */
-	cmpw	0,r0,r3			/* see if tag matches */
-	bdnzf	2,1b			/* while --ctr != 0 && !cr0.eq */
-	beq	3f			/* if we found it */
-	ori	r3,r3,0x40		/* set H (alt. hash) bit */
-	xor	r6,r6,r5		/* address of secondary PTEG */
-	mtctr	r8
-	addi	r7,r6,-8
-2:	lwzu	r0,8(r7)		/* get next PTE */
-	cmpw	0,r0,r3			/* see if tag matches */
-	bdnzf	2,2b			/* while --ctr != 0 && !cr0.eq */
-	bne	4f			/* if we didn't find it */
-3:	li	r0,0
-	stw	r0,0(r7)		/* invalidate entry */
-#else /* CONFIG_PPC64BRIDGE */
-	rldic	r3,r3,16,16		/* put context into vsid (<< 12) */
-	rlwimi	r3,r4,16,16,24		/* top 4 bits of va and API */
-	ori	r3,r3,1			/* set V (valid) bit */
-	rlwinm	r7,r4,32-5,9,24		/* get page index << 7 */
-	srdi	r5,r3,5			/* vsid << 7 */
-	rlwinm	r5,r5,0,1,24		/* vsid << 7 (limited to 24 bits) */
-	xor	r7,r7,r5		/* primary hash << 7 */
-	lis	r5,Hash_mask@ha
-	lwz	r5,Hash_mask@l(r5)	/* hash mask */
-	slwi	r5,r5,7			/*  << 7 */
-	and	r7,r7,r5
-	add	r6,r6,r7		/* address of primary PTEG */
-	li	r8,8
-	mtctr	r8
-	addi	r7,r6,-16
-1:	ldu	r0,16(r7)		/* get next PTE */
-	cmpd	0,r0,r3			/* see if tag matches */
-	bdnzf	2,1b			/* while --ctr != 0 && !cr0.eq */
-	beq	3f			/* if we found it */
-	ori	r3,r3,2			/* set H (alt. hash) bit */
-	xor	r6,r6,r5		/* address of secondary PTEG */
-	mtctr	r8
-	addi	r7,r6,-16
-2:	ldu	r0,16(r7)		/* get next PTE */
-	cmpd	0,r0,r3			/* see if tag matches */
-	bdnzf	2,2b			/* while --ctr != 0 && !cr0.eq */
-	bne	4f			/* if we didn't find it */
-3:	li	r0,0
-	std	r0,0(r7)		/* invalidate entry */
-#endif /* CONFIG_PPC64BRIDGE */
-4:	sync
-	tlbie	r4			/* in hw tlb too */
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-	li	r0,0
-	stw	r0,0(r9)		/* clear hash_table_lock */
-#endif
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	mtmsr	r10
-	SYNC
-#endif
-	blr
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- linux-2.4.6-pre8/arch/ppc/kernel/head.S	Thu May 24 15:03:05 2001
+++ linux/arch/ppc/kernel/head.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.head.S 1.21 05/23/01 00:38:42 cort
+ * BK Id: SCCS/s.head.S 1.23 06/28/01 15:50:16 paulus
  */
 /*
  *  PowerPC version 
@@ -25,11 +25,12 @@
  *	
  */
 
+#include <linux/config.h>
 #include "ppc_asm.h"
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <linux/config.h>
 #include <asm/mmu.h>
+#include <asm/pgtable.h>
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
@@ -177,7 +178,7 @@
 	mtspr	SDR1,r4
 	slbia
 	lis	r5,0x2000		/* set pseudo-segment reg 12 */
-	ori	r5,r5,12
+	ori	r5,r5,0x0ccc
 	mtsr	12,r5
 #endif /* CONFIG_POWER4 */
 
@@ -312,9 +313,8 @@
 	mfspr	r20,DSISR
 	andis.	r0,r20,0xa470		/* weird error? */
 	bne	1f			/* if not, try to put a PTE */
-	mfspr	r3,DAR			/* into the hash table */
-	rlwinm	r4,r23,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	rlwimi	r4,r20,32-23,29,29	/* DSISR_STORE -> _PAGE_RW */
+	mfspr	r4,DAR			/* into the hash table */
+	rlwinm	r3,r20,32-15,21,21	/* DSISR_STORE -> _PAGE_RW */
 	bl	hash_page
 1:	stw	r20,_DSISR(r21)
 	mr	r5,r20
@@ -354,9 +354,8 @@
 #endif /* CONFIG_PPC64BRIDGE */
 	andis.	r0,r23,0x4000		/* no pte found? */
 	beq	1f			/* if so, try to put a PTE */
-	mr	r3,r22			/* into the hash table */
-	rlwinm	r4,r23,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	mr	r20,r23			/* SRR1 has reason bits */
+	li	r3,0			/* into the hash table */
+	mr	r4,r22			/* SRR0 is fault address */
 	bl	hash_page
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	mr	r4,r22
@@ -505,10 +504,13 @@
 	lis	r1,KERNELBASE@h		/* check if kernel address */
 	cmplw	0,r3,r1
 	mfspr	r2,SPRG3
+	li	r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
 	lwz	r2,PGDIR(r2)
 	blt+	112f
 	lis	r2,swapper_pg_dir@ha	/* if kernel address, use */
 	addi	r2,r2,swapper_pg_dir@l	/* kernel page table */
+	mfspr	r1,SRR1			/* and MSR_PR bit from SRR1 */
+	rlwinm	r1,r1,32-12,29,29	/* shift MSR_PR to _PAGE_USER posn */
 112:	tophys(r2,r2)
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -516,21 +518,23 @@
 	beq-	InstructionAddressInvalid	/* return if no mapping */
 	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r1,0(r2)		/* get linux-style pte */
-	/* setup access flags in r3 */
-	mfmsr	r3
-	rlwinm	r3,r3,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	ori	r3,r3,1			/* set _PAGE_PRESENT bit in access */
-	andc.	r3,r3,r1		/* check access & ~permission */
+	lwz	r3,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r3		/* check access & ~permission */
 	bne-	InstructionAddressInvalid /* return if access not permitted */
-	ori	r1,r1,0x100		/* set _PAGE_ACCESSED in pte */
-	stw	r1,0(r2)		/* update PTE (accessed bit) */
+	ori	r3,r3,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
+	/*
+	 * NOTE! We are assuming this is not an SMP system, otherwise
+	 * we would need to update the pte atomically with lwarx/stwcx.
+	 */
+	stw	r3,0(r2)		/* update PTE (accessed bit) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	/* this computation could be done better -- Cort */
-	rlwinm	r3,r1,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r1,r1,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r3,r3,0xe04		/* clear out reserved bits */
-	andc	r1,r1,r3		/* PP=2 or 0, when _PAGE_HWWRITE */
+	rlwinm	r1,r3,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r2,r3,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	and	r1,r1,r2		/* writable if _RW and _DIRTY */
+	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
+	ori	r1,r1,0xe14		/* clear out reserved bits and M */
+	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
 	mtspr	RPA,r1
 	mfspr	r3,IMISS
 	tlbli	r3
@@ -555,7 +559,6 @@
 	mfmsr	r0		/* Restore "normal" registers */
 	xoris	r0,r0,MSR_TGPR>>16
 	mtcrf	0x80,r3		/* Restore CR0 */
-	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	InstructionAccess
 
@@ -576,10 +579,13 @@
 	lis	r1,KERNELBASE@h		/* check if kernel address */
 	cmplw	0,r3,r1
 	mfspr	r2,SPRG3
+	li	r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
 	lwz	r2,PGDIR(r2)
 	blt+	112f
 	lis	r2,swapper_pg_dir@ha	/* if kernel address, use */
 	addi	r2,r2,swapper_pg_dir@l	/* kernel page table */
+	mfspr	r1,SRR1			/* and MSR_PR bit from SRR1 */
+	rlwinm	r1,r1,32-12,29,29	/* shift MSR_PR to _PAGE_USER posn */
 112:	tophys(r2,r2)
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -587,22 +593,23 @@
 	beq-	DataAddressInvalid	/* return if no mapping */
 	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r1,0(r2)		/* get linux-style pte */
-	/* setup access flags in r3 */
-	mfmsr	r3
-	rlwinm	r3,r3,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	ori	r3,r3,1			/* set _PAGE_PRESENT bit in access */
-	/* save r2 and use it as scratch for the andc. */	
-	andc.	r3,r3,r1		/* check access & ~permission */
+	lwz	r3,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r3		/* check access & ~permission */
 	bne-	DataAddressInvalid	/* return if access not permitted */
-	ori	r1,r1,0x100		/* set _PAGE_ACCESSED in pte */
-	stw	r1,0(r2)		/* update PTE (accessed bit) */
+	ori	r3,r3,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
+	/*
+	 * NOTE! We are assuming this is not an SMP system, otherwise
+	 * we would need to update the pte atomically with lwarx/stwcx.
+	 */
+	stw	r3,0(r2)		/* update PTE (accessed bit) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	/* this computation could be done better -- Cort */
-	rlwinm	r3,r1,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r1,r1,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r3,r3,0xe04		/* clear out reserved bits */
-	andc	r1,r1,r3		/* PP=2 or 0, when _PAGE_HWWRITE */
+	rlwinm	r1,r3,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r2,r3,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	and	r1,r1,r2		/* writable if _RW and _DIRTY */
+	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
+	ori	r1,r1,0xe14		/* clear out reserved bits and M */
+	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
 	mtspr	RPA,r1
 	mfspr	r3,DMISS
 	tlbld	r3
@@ -625,7 +632,6 @@
 	mfmsr	r0		/* Restore "normal" registers */
 	xoris	r0,r0,MSR_TGPR>>16
 	mtcrf	0x80,r3		/* Restore CR0 */
-	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	DataAccess
 	
@@ -646,10 +652,13 @@
 	lis	r1,KERNELBASE@h		/* check if kernel address */
 	cmplw	0,r3,r1
 	mfspr	r2,SPRG3
+	li	r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
 	lwz	r2,PGDIR(r2)
 	blt+	112f
 	lis	r2,swapper_pg_dir@ha	/* if kernel address, use */
 	addi	r2,r2,swapper_pg_dir@l	/* kernel page table */
+	mfspr	r1,SRR1			/* and MSR_PR bit from SRR1 */
+	rlwinm	r1,r1,32-12,29,29	/* shift MSR_PR to _PAGE_USER posn */
 112:	tophys(r2,r2)
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -657,22 +666,19 @@
 	beq-	DataAddressInvalid	/* return if no mapping */
 	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r1,0(r2)		/* get linux-style pte */
-	/* setup access flags in r3 */
-	mfmsr	r3
-	rlwinm	r3,r3,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	ori	r3,r3,0x5		/* _PAGE_PRESENT|_PAGE_RW */
-	/* save r2 and use it as scratch for the andc. */	
-	andc.	r3,r3,r1		/* check access & ~permission */
+	lwz	r3,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r3		/* check access & ~permission */
 	bne-	DataAddressInvalid	/* return if access not permitted */
-	ori	r1,r1,0x384		/* set _PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_RW|_PAGE_HWWRITE in pte */
-	stw	r1,0(r2)		/* update PTE (accessed bit) */
+	ori	r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
+	/*
+	 * NOTE! We are assuming this is not an SMP system, otherwise
+	 * we would need to update the pte atomically with lwarx/stwcx.
+	 */
+	stw	r3,0(r2)		/* update PTE (accessed/dirty bits) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	/* this computation could be done better -- Cort */
-	rlwinm	r3,r1,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r1,r1,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r3,r3,0xe04		/* clear out reserved bits */
-	andc	r1,r1,r3		/* PP=2 or 0, when _PAGE_HWWRITE */
+	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	li	r1,0xe15		/* clear out reserved bits and M */
+	andc	r1,r3,r1		/* PP = user? 2: 0 */
 	mtspr	RPA,r1
 	mfspr	r3,DMISS
 	tlbld	r3
@@ -901,7 +907,6 @@
  */
 	mfmsr	r5
 	oris	r5,r5,MSR_VEC@h
-	SYNC
 	mtmsr	r5			/* enable use of AltiVec now */
 	isync
 /*
@@ -1028,6 +1033,7 @@
 	ori	r5,r5,MSR_FP
 	SYNC
 	mtmsr	r5			/* enable use of fpu now */
+	SYNC
 	isync
 	cmpi	0,r3,0
 	beqlr-				/* if no previous owner, done */
@@ -1384,7 +1390,7 @@
 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
 	li	r4,0
 3:	mtsrin	r3,r4
-	addi	r3,r3,1		/* increment VSID */
+	addi	r3,r3,0x111	/* increment VSID */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
 #ifndef CONFIG_POWER4
@@ -1490,7 +1496,8 @@
  * Set up the segment registers for a new context.
  */
 _GLOBAL(set_context)
-	rlwinm	r3,r3,4,8,27	/* VSID = context << 4 */
+	mulli	r3,r3,897	/* multiply context by skew factor */
+	rlwinm	r3,r3,4,8,27	/* VSID = (context & 0xfffff) << 4 */
 	addis	r3,r3,0x6000	/* Set Ks, Ku bits */
 	li	r0,12		/* TASK_SIZE / SEGMENT_SIZE */
 	mtctr	r0
@@ -1500,7 +1507,8 @@
 	slbie	r4
 #endif /* CONFIG_PPC64BRIDGE */
 	mtsrin	r3,r4
-	addi	r3,r3,1		/* next VSID */
+	addi	r3,r3,0x111	/* next VSID */
+	rlwinm	r3,r3,0,8,3	/* clear out any overflow from VSID field */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
 	SYNC
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- linux-2.4.6-pre8/arch/ppc/kernel/head_8xx.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/head_8xx.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.head_8xx.S 1.11 05/21/01 11:50:00 paulus
+ * BK Id: SCCS/s.head_8xx.S 1.14 06/28/01 15:50:16 paulus
  */
 /*
  *  arch/ppc/kernel/except_8xx.S
@@ -500,6 +500,11 @@
 #endif
 	mtspr	MD_TWC, r21
 
+	/* Set PP0 to PP1 (== _PAGE_USER) & ~_PAGE_RW */
+	rlwimi	r20, r20, 32-1, 21, 21
+	rlwinm	r21, r20, 4, 21, 21
+	andc	r20, r20, r21
+
 	/* Set four subpage valid bits (24, 25, 26, and 27).
 	 * Clear bit 28 (which should be in the PTE, but we do this anyway).
 	 */
@@ -602,7 +607,7 @@
 
 	/* Update 'changed', among others.
 	*/
-	ori	r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
+	ori	r20, r20, _PAGE_DIRTY|_PAGE_ACCESSED
 	mfspr	r21, MD_TWC		/* Get pte address again */
 	stw	r20, 0(r21)		/* and update pte in table */
 
@@ -939,6 +944,12 @@
  * ASID compare register with the new "context".
  */
 _GLOBAL(set_context)
+	/* fetch the pgd from the context_mm array */
+	lis	r5, context_mm@ha
+	slwi	r6, r3, 2
+	add	r5, r5, r6
+	lwz	r5, context_mm@l(r5)	/* get the mm */
+	lwz	r4, MM_PGD(r5)		/* get the pgd from the mm */
 #ifdef CONFIG_8xx_CPU6
 	lis	r6, cpu6_errata_word@h
 	ori	r6, r6, cpu6_errata_word@l
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- linux-2.4.6-pre8/arch/ppc/kernel/irq.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/kernel/irq.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.irq.c 1.26 06/06/01 22:33:09 paulus
+ * BK Id: SCCS/s.irq.c 1.28 06/28/01 16:15:56 paulus
  */
 /*
  *  arch/ppc/kernel/irq.c
@@ -531,25 +531,21 @@
 {
 	int cpu = smp_processor_id();
 	int irq;
-        hardirq_enter( cpu );
+        hardirq_enter(cpu);
 
 	/* every arch is required to have a get_irq -- Cort */
-	irq = ppc_md.get_irq( regs );
+	irq = ppc_md.get_irq(regs);
 
-	if ( irq < 0 )
-	{
+	if (irq >= 0) {
+		ppc_irq_dispatch_handler( regs, irq );
+	} else if (irq != -2) {
 		/* -2 means ignore, already handled */
-		if (irq != -2)
-		{
+		if (ppc_spurious_interrupts < 10)
 			printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
 			       irq, regs->nip);
-			/* That's not SMP safe ... but who cares ? */
-			ppc_spurious_interrupts++;
-		}
-		goto out;
+		/* That's not SMP safe ... but who cares ? */
+		ppc_spurious_interrupts++;
 	}
-	ppc_irq_dispatch_handler( regs, irq );
-out:	
         hardirq_exit( cpu );
 
 	if (softirq_pending(cpu))
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- linux-2.4.6-pre8/arch/ppc/kernel/m8xx_setup.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.m8xx_setup.c 1.17 05/18/01 07:54:04 patch
+ * BK Id: SCCS/s.m8xx_setup.c 1.20 06/27/01 14:49:58 trini
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -124,12 +124,6 @@
 extern unsigned long find_available_memory(void);
 extern void m8xx_cpm_reset(uint);
 
-static void ide_interrupt_handler(void* dev_id);
-
-void __init adbdev_init(void)
-{
-}
-
 void __init
 m8xx_setup_arch(void)
 {
@@ -359,6 +353,12 @@
 /*
  * IDE stuff.
  */
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+void ide_interrupt_handler (void *dev)
+{
+}
+#endif
+
 void
 m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns)
 {
@@ -512,12 +512,7 @@
 
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 }
-#endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
-
-
-/* -------------------------------------------------------------------- */
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 
 /* PCMCIA Timing */
@@ -577,13 +572,9 @@
 	if ((reg = pcmp->pcmc_por7 & mask) != 0)
 		pcmp->pcmc_por7 = reg | timing;
 }
-
-void ide_interrupt_handler (void *dev)
-{
-}
-
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 #endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
 /* -------------------------------------------------------------------- */
 
 /*
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- linux-2.4.6-pre8/arch/ppc/kernel/misc.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/misc.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.misc.S 1.16 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.misc.S 1.19 06/15/01 13:56:56 paulus
  */
 /*
  * This file contains miscellaneous low-level functions.
@@ -263,10 +263,13 @@
  * This is a no-op on the 601.
  */
 _GLOBAL(flush_instruction_cache)
-#ifdef CONFIG_8xx
+#if defined(CONFIG_8xx)
 	isync
 	lis	r5, IDC_INVALL@h
 	mtspr	IC_CST, r5
+#elif defined(CONFIG_4xx)
+	lis	r3, KERNELBASE@h
+	iccci	0,r3
 #else
 	mfspr	r3,PVR
 	rlwinm	r3,r3,16,16,31
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
--- linux-2.4.6-pre8/arch/ppc/kernel/mk_defs.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/mk_defs.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.mk_defs.c 1.5 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.mk_defs.c 1.8 06/28/01 15:50:16 paulus
  */
 /*
  * This program is used to generate definitions needed by
@@ -117,5 +117,6 @@
 	DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
 	DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
 	DEFINE(CLONE_VM, CLONE_VM);
+	DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
 	return 0;
 }
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- linux-2.4.6-pre8/arch/ppc/kernel/pci.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/pci.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pci.c 1.21 05/21/01 01:31:30 cort
+ * BK Id: SCCS/s.pci.c 1.26 06/28/01 08:02:41 trini
  */
 /*
  * Common pmac/prep/chrp pci routines. -- Cort
@@ -40,11 +40,10 @@
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
 
-static u8* pci_to_OF_bus_map;
-
 static void pcibios_fixup_resources(struct pci_dev* dev);
 #ifdef CONFIG_ALL_PPC
 static void pcibios_fixup_cardbus(struct pci_dev* dev);
+static u8* pci_to_OF_bus_map;
 #endif
 
 /* By default, we don't re-assign bus numbers. We do this only on
@@ -73,8 +72,13 @@
 	u32 new, check;
 	int reg;
 	struct pci_controller* hose = dev->sysdata;
+	unsigned long io_offset;
 	
 	new = res->start;
+	if (hose && res->flags & IORESOURCE_IO) {
+		io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+		new -= io_offset;
+	}
 	if (hose && res->flags & IORESOURCE_MEM)
 		new -= hose->pci_mem_offset;
 	new |= (res->flags & PCI_REGION_FLAG_MASK);
@@ -98,40 +102,43 @@
 }
 
 static void
-pcibios_fixup_resources(struct pci_dev* dev)
+pcibios_fixup_resources(struct pci_dev *dev)
 {
-	struct pci_controller* hose =
-		(struct pci_controller *)dev->sysdata;
+	struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
 	int i;
+	unsigned long offset;
+
 	if (!hose) {
-		printk("No hose for PCI dev %x.%x !\n", dev->bus->number, dev->devfn >> 3);
+		printk(KERN_ERR "No hose for PCI dev %s!\n", dev->slot_name);
 		return;
 	}
 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
 		struct resource *res = dev->resource + i;
-		if (!res->start)
+		if (!res->start || !res->flags)
 			continue;
-		if ((res->flags & IORESOURCE_MEM) && hose->pci_mem_offset) {
-			res->start += hose->pci_mem_offset;
-			res->end += hose->pci_mem_offset;
+		if (res->end == 0xffffffff) {
+			DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+			    dev->slot_name, i, res->start, res->end);
+			res->end -= res->start;
+			res->start = 0;
+			continue;
+		}
+		offset = 0;
+		if (res->flags & IORESOURCE_MEM) {
+			offset = hose->pci_mem_offset;
+		} else if (res->flags & IORESOURCE_IO) {
+			offset = (unsigned long) hose->io_base_virt
+				- isa_io_base;
+		}
+		if (offset != 0) {
+			res->start += offset;
+			res->end += offset;
 #ifdef DEBUG
-			printk("Fixup mem res, dev: %x.%x, res_start: %lx->%lx\n",
-			       dev->bus->number, dev->devfn>>3, res->start-hose->pci_mem_offset,
-			       res->start);
+			printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+			       i, res->flags, dev->slot_name,
+			       res->start - offset, res->start);
 #endif
 		}
-
-		if ((res->flags & IORESOURCE_IO)
-		    && (unsigned long) hose->io_base_virt != isa_io_base) {
-			unsigned long offs;
-
-			offs = (unsigned long)hose->io_base_virt - isa_io_base;
-			res->start += offs;
-			res->end += offs;
-			printk("Fixup IO res, dev: %x.%x, res_start: %lx->%lx\n",
-			       dev->bus->number, dev->devfn>>3,
-			       res->start - offs, res->start);
-		}
 	}
 }
 
@@ -228,22 +235,27 @@
 {
 	struct list_head *ln;
 	struct pci_bus *bus;
-	struct pci_dev *dev;
-	int idx;
-	struct resource *r, *pr;
+	int i;
+	struct resource *res, *pr;
 
 	/* Depth-First Search on bus tree */
-	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+	for (ln = bus_list->next; ln != bus_list; ln=ln->next) {
 		bus = pci_bus_b(ln);
-		if ((dev = bus->self)) {
-			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
-				r = &dev->resource[idx];
-				if (!r->start)
-					continue;
-				pr = pci_find_parent_resource(dev, r);
-				if (!pr || request_resource(pr, r) < 0)
-					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
-			}
+		for (i = 0; i < 4; ++i) {
+			if ((res = bus->resource[i]) == NULL || !res->flags)
+				continue;
+			if (bus->parent == NULL)
+				pr = (res->flags & IORESOURCE_IO)?
+					&ioport_resource: &iomem_resource;
+			else
+				pr = pci_find_parent_resource(bus->self, res);
+
+			if (pr && request_resource(pr, res) == 0)
+				continue;
+			printk(KERN_ERR "PCI: Cannot allocate resource region "
+			       "%d of PCI bridge %d\n", i, bus->number);
+			DBG("PCI: resource is %lx..%lx (%lx), parent %p\n",
+			    res->start, res->end, res->flags, pr);
 		}
 		pcibios_allocate_bus_resources(&bus->children);
 	}
@@ -253,13 +265,15 @@
 {
 	struct resource *pr, *r = &dev->resource[idx];
 
-	DBG("PCI:%x:%x:%x: Resource %08lx-%08lx (f=%lx)\n",
-	    dev->bus->number, dev->devfn >> 3, dev->devfn & 7,
-	    r->start, r->end, r->flags);
+	DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",
+	    dev->slot_name, idx, r->start, r->end, r->flags);
 	pr = pci_find_parent_resource(dev, r);
 	if (!pr || request_resource(pr, r) < 0) {
 		printk(KERN_ERR "PCI: Cannot allocate resource region %d"
 		       " of device %s\n", idx, dev->slot_name);
+		if (pr)
+			DBG("PCI:  parent is %p: %08lx-%08lx (f=%lx)\n",
+			    pr, pr->start, pr->end, pr->flags);
 		/* We'll assign a new address later */
 		r->end -= r->start;
 		r->start = 0;
@@ -276,20 +290,12 @@
 
 	pci_for_each_dev(dev) {
 		pci_read_config_word(dev, PCI_COMMAND, &command);
-		for(idx = 0; idx < 6; idx++) {
+		for (idx = 0; idx < 6; idx++) {
 			r = &dev->resource[idx];
 			if (r->parent)		/* Already allocated */
 				continue;
 			if (!r->start)		/* Not assigned at all */
 				continue;
-			if (r->end == 0xffffffff) {
-				/* LongTrail OF quirk: unassigned */
-				DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end);
-				r->end -= r->start;
-				r->start = 0;
-				continue;
-			}
-
 			if (r->flags & IORESOURCE_IO)
 				disabled = !(command & PCI_COMMAND_IO);
 			else
@@ -306,7 +312,8 @@
 			DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
 			r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
 			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-			pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+			pci_write_config_dword(dev, dev->rom_base_reg,
+					       reg & ~PCI_ROM_ADDRESS_ENABLE);
 		}
 	}
 }
@@ -325,21 +332,14 @@
 		if (!class || class == PCI_CLASS_BRIDGE_HOST)
 			continue;
 
-		for(idx=0; idx<6; idx++) {
+		for (idx = 0; idx < 6; idx++) {
 			r = &dev->resource[idx];
-#if 0	/* we don't need this PC-ism */
-			/*
-			 *  Don't touch IDE controllers and I/O ports of video cards!
-			 */
-			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
-			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
-				continue;
-#endif
 
 			/*
-			 *  We shall assign a new address to this resource, either because
-			 *  the BIOS (sic) forgot to do so or because we have decided the old
-			 *  address was unusable for some reason.
+			 * We shall assign a new address to this resource,
+			 * either because the BIOS (sic) forgot to do so
+			 * or because we have decided the old address was
+			 * unusable for some reason.
 			 */
 			if (!r->start && r->end &&
 			    (!ppc_md.pcibios_enable_device_hook ||
@@ -347,13 +347,13 @@
 				pci_assign_resource(dev, idx);
 		}
 
-		if (0) { /* don't assign ROMs */
-			r = &dev->resource[PCI_ROM_RESOURCE];
-			r->end -= r->start;
-			r->start = 0;
-			if (r->end)
-				pci_assign_resource(dev, PCI_ROM_RESOURCE);
-		}
+#if 0 /* don't assign ROMs */
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		r->end -= r->start;
+		r->start = 0;
+		if (r->end)
+			pci_assign_resource(dev, PCI_ROM_RESOURCE);
+#endif
 	}
 }
 
@@ -496,10 +496,15 @@
 			&& ((reg[0] >> 16) & 0xff) == bus)
 			return node;
 
-		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		/* For PCI<->PCI bridges or CardBus bridges, we go down
+		 * Note: some OFs create a parent node "multifunc-device" as
+		 * a fake root for all functions of a multi-function device,
+		 * we go down them as well.
+		 */
 		class_code = (unsigned int *) get_property(node, "class-code", 0);
-		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+		if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
+			strcmp(node->name, "multifunc-device"))
 			continue;
 		sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn);
 		if (sub_node)
@@ -682,9 +687,9 @@
 {
 	struct pci_controller *hose;
 	struct pci_bus *bus;
-	int next_busno, i;
+	int next_busno;
 
-	printk("PCI: Probing PCI hardware\n");
+	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
 	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
@@ -692,18 +697,6 @@
 			hose->first_busno = next_busno;
 		hose->last_busno = 0xff;
 		bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
-		if (hose->io_resource.flags) {
-			unsigned long offs;
-
-			offs = (unsigned long)hose->io_base_virt - isa_io_base;
-			hose->io_resource.start += offs;
-			hose->io_resource.end += offs;
-			bus->resource[0] = &hose->io_resource;
-		}
-		for (i = 0; i < 3; ++i)
-			if (hose->mem_resources[i].flags)
-				bus->resource[i+1] = &hose->mem_resources[i];
-		hose->bus = bus;
 		hose->last_busno = bus->subordinate;
 		if (pci_assign_all_busses || next_busno <= hose->last_busno)
 			next_busno = hose->last_busno+1;
@@ -716,7 +709,7 @@
 	 */
 	if (pci_assign_all_busses && have_of)
 		pcibios_make_OF_bus_map();
-		
+
 	/* Call machine dependant fixup */
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
@@ -727,27 +720,7 @@
 	pcibios_allocate_resources(1);
 	pcibios_assign_resources();
 
-#ifdef CONFIG_BLK_DEV_IDE
-	/* OF fails to initialize IDE controllers on macs
-	 * (and maybe other machines)
-	 * 
-	 * 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
-	 * BIOS may have disabled a controller.
-	 * 
-	 * -- BenH
-	 */
-	if (_machine == _MACH_Pmac) {
-		struct pci_dev *dev;
-		pci_for_each_dev(dev)
-		{
-			if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
-				pci_enable_device(dev);
-		}
-	}
-#endif /* CONFIG_BLK_DEV_IDE */
-
+	/* Call machine dependent post-init code */
 	if (ppc_md.pcibios_after_init)
 		ppc_md.pcibios_after_init();
 }
@@ -775,21 +748,62 @@
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+	unsigned long io_offset;
+	struct resource *res;
+	int i;
+
+	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+	if (bus->parent == NULL) {
+		/* This is a host bridge - fill in its resources */
+		hose->bus = bus;
 
-	pci_read_bridge_bases(bus);
+		bus->resource[0] = res = &hose->io_resource;
+		if (!res->flags) {
+			if (io_offset)
+				printk(KERN_ERR "I/O resource not set for host"
+				       " bridge %d\n", hose->index);
+			res->start = 0;
+			res->end = IO_SPACE_LIMIT;
+			res->flags = IORESOURCE_IO;
+		}
+		res->start += io_offset;
+		res->end += io_offset;
 
-	hose = pci_bus_to_hose(bus->number);
+		for (i = 0; i < 3; ++i) {
+			res = &hose->mem_resources[i];
+			if (!res->flags) {
+				if (i > 0)
+					continue;
+				printk(KERN_ERR "Memory resource not set for "
+				       "host bridge %d\n", hose->index);
+				res->start = hose->pci_mem_offset;
+				res->end = ~0U;
+				res->flags = IORESOURCE_MEM;
+			}
+			bus->resource[i+1] = res;
+		}
+	} else {
+		/* This is a subordinate bridge */
+		pci_read_bridge_bases(bus);
 
-	/* Apply pci_mem_offset to bridge mem resource */
-	if (hose->first_busno != bus->number)
-		if (bus->resource[1]->start && (bus->resource[1]->end != -1))
-		{
-			bus->resource[1]->start += hose->pci_mem_offset;
-			bus->resource[1]->end += hose->pci_mem_offset;
+		for (i = 0; i < 4; ++i) {
+			if ((res = bus->resource[i]) == NULL)
+				continue;
+			if (!res->flags)
+				continue;
+			if (io_offset && (res->flags & IORESOURCE_IO)) {
+				res->start += io_offset;
+				res->end += io_offset;
+			} else if (hose->pci_mem_offset
+				   && (res->flags & IORESOURCE_MEM)) {
+				res->start += hose->pci_mem_offset;
+				res->end += hose->pci_mem_offset;
+			}
 		}
+	}
 
-	if ( ppc_md.pcibios_fixup_bus )
+	if (ppc_md.pcibios_fixup_bus)
 		ppc_md.pcibios_fixup_bus(bus);
 }
 
@@ -881,26 +895,17 @@
 	return hose->pci_mem_offset;
 }
 
-#ifdef CONFIG_POWER4
-extern unsigned long pci_address_offset(int, unsigned int);
-#endif /* CONFIG_POWER4 */
-
 unsigned long
 pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
 {
 	/* Hack alert again ! See comments in chrp_pci.c
 	 */
-#ifdef CONFIG_POWER4
-	unsigned long offset = pci_address_offset(pdev->bus->number, res->flags);
-	return res->start - offset;
-#else /* CONFIG_POWER4 */
 	struct pci_controller* hose =
 		(struct pci_controller *)pdev->sysdata;
 	if (hose && res->flags & IORESOURCE_MEM)
 		return res->start - hose->pci_mem_offset;
 	/* We may want to do something with IOs here... */
 	return res->start;
-#endif	
 }
 
 /*
@@ -1072,27 +1077,19 @@
 unsigned long
 pci_phys_to_bus(unsigned long pa, int busnr)
 {
-#ifdef CONFIG_POWER4
-	return pa - pci_address_offset(busnr, IORESOURCE_MEM);
-#else /* CONFIG_POWER4 */
 	struct pci_controller* hose = pci_bus_to_hose(busnr);
 	if (!hose)
 		return pa;
 	return pa - hose->pci_mem_offset;
-#endif
 }
 
 unsigned long
 pci_bus_to_phys(unsigned int ba, int busnr)
 {
-#ifdef CONFIG_POWER4
-	return ba + pci_address_offset(dev->bus->number, IORESOURCE_MEM);
-#else /* CONFIG_POWER4 */
 	struct pci_controller* hose = pci_bus_to_hose(busnr);
 	if (!hose)
 		return ba;
 	return ba + hose->pci_mem_offset;
-#endif
 }
 
 /* Provide information on locations of various I/O regions in physical
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- linux-2.4.6-pre8/arch/ppc/kernel/pmac_pci.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/pmac_pci.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pmac_pci.c 1.14 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.pmac_pci.c 1.18 07/01/01 12:23:31 trini
  */
 /*
  * Support for PCI bridges found on Power Macintoshes.
@@ -42,8 +42,6 @@
 /*
  * Magic constants for enabling cache coherency in the bandit/PSX bridge.
  */
-#define APPLE_VENDID	0x106b
-#define BANDIT_DEVID	1
 #define BANDIT_DEVID_2	8
 #define BANDIT_REVID	3
 
@@ -97,12 +95,17 @@
 }
 
 /*
- * Apple MacRISC (UniNorth, Bandit) PCI controllers.
+ * Apple MacRISC (UniNorth, Bandit, Chaos) PCI controllers.
  * 
  * The "Bandit" version is present in all early PCI PowerMacs,
  * and up to the first ones using Grackle. Some machines may
  * have 2 bandit controllers (2 PCI busses).
  * 
+ * "Chaos" is used in some "Bandit"-type machines as a bridge
+ * for the separate display bus. It is accessed the same
+ * way as bandit, but cannot be probed for devices. It therefore
+ * has its own config access functions.
+ *
  * The "UniNorth" version is present in all Core99 machines
  * (iBook, G4, new IMacs, and all the recent Apple machines).
  * It contains 3 controllers in one ASIC.
@@ -124,10 +127,6 @@
 {
 	unsigned int caddr;
 	
-#ifdef DEBUG
-//	printk("macrisc_config_access(hose: 0x%08lx, bus: 0x%x, devfb: 0x%x, offset: 0x%x)\n",
-//		hose, bus, dev_fn, offset);
-#endif
 	if (bus == hose->first_busno) {
 		if (dev_fn < (11 << 3))
 			return 0;
@@ -189,55 +188,50 @@
 	macrisc_write_config_dword
 };
 
-
 /*
- * Apple "Chaos" PCI controller.
- * 
- * This controller is present on some first generation "PowerSurge"
- * machines (8500, 8600, ...). It's a very weird beast and will die
- * in flames if we try to probe the config space.
- * The long-term solution is to provide a config space "emulation"
- * based on what we find in OF device tree
+ * Verifiy that a specific (bus, dev_fn) exists on chaos
  */
- 
-static int chaos_config_read_byte(struct pci_dev *dev, int offset, u8 *val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_read_word(struct pci_dev *dev, int offset, u16 *val)
+static int __pmac
+chaos_validate_dev(struct pci_dev *dev, int offset)
 {
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_read_dword(struct pci_dev *dev, int offset, u32 *val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_write_byte(struct pci_dev *dev, int offset, u8 val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_write_word(struct pci_dev *dev, int offset, u16 val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
+	if(pci_device_to_OF_node(dev) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) &&
+	    (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+	return PCIBIOS_SUCCESSFUL;
 }
 
-static int chaos_config_write_dword(struct pci_dev *dev, int offset, u32 val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
+#define CHAOS_PCI_OP(rw, size, type)					\
+static int __pmac							\
+chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val)	\
+{									\
+	int result = chaos_validate_dev(dev, off);			\
+	if(result == PCIBIOS_BAD_REGISTER_NUMBER) {			\
+		cfg_##rw##_bad(val, size)				\
+		return PCIBIOS_BAD_REGISTER_NUMBER;			\
+	}								\
+	if(result == PCIBIOS_SUCCESSFUL)				\
+		return macrisc_##rw##_config_##size(dev, off, val);	\
+	return result;							\
+}
+
+CHAOS_PCI_OP(read, byte, u8 *)
+CHAOS_PCI_OP(read, word, u16 *)
+CHAOS_PCI_OP(read, dword, u32 *)
+CHAOS_PCI_OP(write, byte, u8)
+CHAOS_PCI_OP(write, word, u16)
+CHAOS_PCI_OP(write, dword, u32) 
 
 static struct pci_ops chaos_pci_ops =
 {
-	chaos_config_read_byte,
-	chaos_config_read_word,
-	chaos_config_read_dword,
-	chaos_config_write_byte,
-	chaos_config_write_word,
-	chaos_config_write_dword
+	chaos_read_config_byte,
+	chaos_read_config_word,
+	chaos_read_config_dword,
+	chaos_write_config_byte,
+	chaos_write_config_word,
+	chaos_write_config_dword
 };
 
 
@@ -245,7 +239,8 @@
  * For a bandit bridge, turn on cache coherency if necessary.
  * N.B. we could clean this up using the hose ops directly.
  */
-static void __init init_bandit(struct pci_controller *bp)
+static void __init
+init_bandit(struct pci_controller *bp)
 {
 	unsigned int vendev, magic;
 	int rev;
@@ -254,7 +249,8 @@
 	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
 	udelay(2);
 	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
-	if (vendev == (BANDIT_DEVID << 16) + APPLE_VENDID) {
+	if (vendev == (PCI_VENDOR_ID_APPLE_BANDIT << 16) + 
+			PCI_VENDOR_ID_APPLE) {
 		/* read the revision id */
 		out_le32(bp->cfg_addr,
 			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
@@ -264,7 +260,7 @@
 			printk(KERN_WARNING
 			       "Unknown revision %d for bandit at %08lx\n",
 			       rev, bp->io_base_phys);
-	} else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) {
+	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
 		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
 		return;
 	}
@@ -426,7 +422,8 @@
  * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
  * if we have one or more bandit or chaos bridges, we don't have a MPC106.
  */
-static void __init add_bridges(struct device_node *dev)
+static void __init
+add_bridges(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -490,17 +487,11 @@
 	}
 }
 
-static void
+static void __init
 pcibios_fixup_OF_interrupts(void)
 {	
 	struct pci_dev* dev;
 	
-	/*
-	 * FIXME: This is broken: We should not assign IRQ's to IRQless
-	 *	  devices (look at PCI_INTERRUPT_PIN) and we also should
-	 *	  honor the existence of multi-function devices where
-	 *	  different functions have different interrupt pins. [mj]
-	 */
 	pci_for_each_dev(dev)
 	{
 		/*
@@ -533,7 +524,7 @@
 	pcibios_fixup_OF_interrupts();
 }
 
-int
+int __pmac
 pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
 {
 	struct device_node* node;
@@ -563,10 +554,29 @@
 /* We power down some devices after they have been probed. They'll
  * be powered back on later on
  */
-void
+void __init
 pmac_pcibios_after_init(void)
 {
 	struct device_node* nd;
+
+#ifdef CONFIG_BLK_DEV_IDE
+	struct pci_dev *dev;
+
+	/* OF fails to initialize IDE controllers on macs
+	 * (and maybe other machines)
+	 * 
+	 * 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
+	 * BIOS may have disabled a controller.
+	 * 
+	 * -- BenH
+	 */
+	pci_for_each_dev(dev) {
+		if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
+			pci_enable_device(dev);
+	}
+#endif /* CONFIG_BLK_DEV_IDE */
 
 	nd = find_devices("firewire");
 	while (nd) {
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/ppc4xx_pic.h linux/arch/ppc/kernel/ppc4xx_pic.h
--- linux-2.4.6-pre8/arch/ppc/kernel/ppc4xx_pic.h	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/ppc4xx_pic.h	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc4xx_pic.h 1.5 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.ppc4xx_pic.h 1.8 06/15/01 13:56:56 paulus
  */
 /*
  *
@@ -14,12 +14,8 @@
 #ifndef	__PPC4XX_PIC_H__
 #define	__PPC4XX_PIC_H__
 
-#include <asm/ptrace.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <linux/config.h>
+#include "local_irq.h"
 
 /* External Global Variables */
 
@@ -30,10 +26,5 @@
 
 extern void	 ppc4xx_pic_init(void);
 extern int	 ppc4xx_pic_get_irq(struct pt_regs *regs);
-
-
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* __PPC4XX_PIC_H__ */
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- linux-2.4.6-pre8/arch/ppc/kernel/ppc_htab.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/ppc_htab.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc_htab.c 1.8 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.ppc_htab.c 1.11 06/28/01 15:50:16 paulus
  */
 /*
  * PowerPC hash table management proc entry.  Will show information
@@ -41,9 +41,12 @@
 extern unsigned long Hash_size, Hash_mask;
 extern unsigned long _SDR1;
 extern unsigned long htab_reloads;
+extern unsigned long htab_preloads;
 extern unsigned long htab_evicts;
 extern unsigned long pte_misses;
 extern unsigned long pte_errors;
+extern unsigned int primary_pteg_full;
+extern unsigned int htab_hash_searches;
 
 /* these will go into processor.h when I'm done debugging -- Cort */
 #define MMCR0 952
@@ -110,7 +113,7 @@
 {
 	unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
 	int n = 0, valid;
-	unsigned int kptes = 0, overflow = 0, uptes = 0, zombie_ptes = 0;
+	unsigned int kptes = 0, uptes = 0, zombie_ptes = 0;
 	PTE *ptr;
 	struct task_struct *p;
 	char buffer[512];
@@ -150,41 +153,34 @@
 		n += sprintf( buffer + n, "No Hash Table used\n");
 		goto return_string;
 	}
-	
-	/*
-	 * compute user/kernel pte's table this info can be
-	 * misleading since there can be valid (v bit set) entries
-	 * in the table but their vsid is used by no process (mm->context)
-	 * due to the way tlb invalidation is handled on the ppc
-	 * -- Cort
-	 */
+
+#if !defined(CONFIG_8xx) && !defined(CONFIG_4xx)
 	for ( ptr = Hash ; ptr < Hash_end ; ptr++)
 	{
-		if (ptr->v)
-		{
-			/* make sure someone is using this context/vsid */
-			valid = 0;
-			for_each_task(p)
-			{
-				if (p->mm && (ptr->vsid >> 4) == p->mm->context)
-				{
-					valid = 1;
-					break;
-				}
-			}
-			if ( !valid )
-			{
-				zombie_ptes++;
-				continue;
-			}
-			/* user not allowed read or write */
-			if (ptr->pp == PP_RWXX)
-				kptes++;
-			else
+		unsigned int ctx, mctx, vsid;
+
+		if (!ptr->v)
+			continue;
+		/* make sure someone is using this context/vsid */
+		/* first undo the esid skew */
+		vsid = ptr->vsid;
+		mctx = ((vsid - (vsid & 0xf) * 0x111) >> 4) & 0xfffff;
+		if (mctx == 0) {
+			kptes++;
+			continue;
+		}
+		/* now undo the context skew; 801921 * 897 == 1 mod 2^20 */
+		ctx = (mctx * 801921) & 0xfffff;
+		valid = 0;
+		for_each_task(p) {
+			if (p->mm != NULL && ctx == p->mm->context) {
+				valid = 1;
 				uptes++;
-			if (ptr->h == 1)
-				overflow++;
+				break;
+			}
 		}
+		if (!valid)
+			zombie_ptes++;
 	}
 	
 	n += sprintf( buffer + n,
@@ -195,29 +191,32 @@
 		      "Entries\t\t: %lu\n"
 		      "User ptes\t: %u\n"
 		      "Kernel ptes\t: %u\n"
-		      "Overflows\t: %u\n"
 		      "Zombies\t\t: %u\n"
-		      "Percent full\t: %%%lu\n",
+		      "Percent full\t: %lu%%\n",
                       (unsigned long)(Hash_size>>10),
 		      (Hash_size/(sizeof(PTE)*8)),
 		      (unsigned long)Hash,
 		      Hash_size/sizeof(PTE),
                       uptes,
 		      kptes,
-		      overflow,
 		      zombie_ptes,
 		      ((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
 		);
 
 	n += sprintf( buffer + n,
-		      "Reloads\t\t: %08lx\n"
-		      "Evicts\t\t: %08lx\n",
-		      htab_reloads, htab_evicts);
+		      "Reloads\t\t: %lu\n"
+		      "Preloads\t: %lu\n"
+		      "Searches\t: %u\n"
+		      "Overflows\t: %u\n"
+		      "Evicts\t\t: %lu\n",
+		      htab_reloads, htab_preloads, htab_hash_searches,
+		      primary_pteg_full, htab_evicts);
+#endif /* !8xx && !4xx */
 	
 return_string:
 	n += sprintf( buffer + n,
-		      "Non-error misses: %08lx\n"
-		      "Error misses\t: %08lx\n",
+		      "Non-error misses: %lu\n"
+		      "Error misses\t: %lu\n",
 		      pte_misses, pte_errors);
 	if (*ppos >= strlen(buffer))
 		return 0;
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.4.6-pre8/arch/ppc/kernel/ppc_ksyms.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc_ksyms.c 1.34 06/09/01 22:38:13 paulus
+ * BK Id: SCCS/s.ppc_ksyms.c 1.36 06/28/01 15:50:16 paulus
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -359,11 +359,10 @@
 EXPORT_SYMBOL(ret_to_user_hook);
 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)
+EXPORT_SYMBOL(flush_hash_page); /* For MOL */
 extern long *intercept_table;
 EXPORT_SYMBOL(intercept_table);
 #endif
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- linux-2.4.6-pre8/arch/ppc/kernel/process.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/process.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.process.c 1.15 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.process.c 1.19 06/15/01 13:56:56 paulus
  */
 /*
  *  linux/arch/ppc/kernel/process.c
@@ -267,6 +267,15 @@
 	printk("Last syscall: %ld ", current->thread.last_syscall);
 	printk("\nlast math %p last altivec %p", last_task_used_math,
 	       last_task_used_altivec);
+
+#ifdef CONFIG_4xx
+	printk("\nPLB0: bear= 0x%8.8x acr=   0x%8.8x besr=  0x%8.8x\n",
+	    mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_PLB0_ACR),
+	    mfdcr(DCRN_PLB0_BESR));
+	printk("PLB0 to OPB: bear= 0x%8.8x besr0= 0x%8.8x besr1= 0x%8.8x\n",
+	    mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_POB0_BESR0),
+	    mfdcr(DCRN_POB0_BESR1));
+#endif
 	
 #ifdef CONFIG_SMP
 	printk(" CPU: %d", current->processor);
@@ -289,7 +298,8 @@
 			printk("\n");
 		}
 	}
-out: ;
+out:
+	print_backtrace((unsigned long *)regs->gpr[1]);
 }
 
 void exit_thread(void)
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- linux-2.4.6-pre8/arch/ppc/kernel/prom.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/kernel/prom.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.prom.c 1.23 06/06/01 22:49:01 paulus
+ * BK Id: SCCS/s.prom.c 1.26 06/28/01 15:50:16 paulus
  */
 /*
  * Procedures for interfacing to the Open Firmware PROM on
@@ -174,7 +174,6 @@
 #endif
 
 extern void enter_rtas(void *);
-extern unsigned long reloc_offset(void);
 void phys_call_rtas(int, int, int, ...);
 
 extern char cmd_line[512];	/* XXX */
@@ -192,6 +191,14 @@
 #define BOOT_INFO_IS_V2_COMPATIBLE(bi)	((bi)->version >= 2)
 #define BOOT_INFO_IS_V4_COMPATIBLE(bi)	((bi)->version >= 4)
 
+/*
+ * Note that prom_init() and anything called from prom_init() must
+ * use the RELOC/PTRRELOC macros to access any static data in
+ * memory, since the kernel may be running at an address that is
+ * different from the address that it was linked at.
+ * (Note that strings count as static variables.)
+ */
+
 __init
 static void
 prom_exit()
@@ -480,13 +487,14 @@
 			    unsigned int va, unsigned int pa, int mode)
 {
 	unsigned int *pteg;
-	unsigned int hash, i;
+	unsigned int hash, i, vsid;
 
-	hash = ((va >> 5) ^ (va >> 21)) & 0x7fff80;
+	vsid = ((va >> 28) * 0x111) << 12;
+	hash = ((va ^ vsid) >> 5) & 0x7fff80;
 	pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
 	for (i = 0; i < 8; ++i, pteg += 4) {
 		if ((pteg[1] & 1) == 0) {
-			pteg[1] = ((va >> 16) & 0xff80) | 1;
+			pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
 			pteg[3] = pa | mode;
 			break;
 		}
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux-2.4.6-pre8/arch/ppc/kernel/setup.c	Thu May 24 15:03:05 2001
+++ linux/arch/ppc/kernel/setup.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.setup.c 1.32 05/23/01 00:38:42 cort
+ * BK Id: SCCS/s.setup.c 1.44 06/28/01 08:01:06 trini
  */
 /*
  * Common prep/pmac/chrp boot and setup code.
@@ -36,16 +36,16 @@
 #include <asm/mpc8260.h>
 #include <asm/immap_8260.h>
 #endif
+#ifdef CONFIG_4xx
+#include <asm/ppc4xx.h>
+#endif
 #include <asm/bootx.h>
 #include <asm/machdep.h>
 #include <asm/feature.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_OAK
-#include "oak_setup.h"
-#endif /* CONFIG_OAK */
 
-extern void pmac_init(unsigned long r3,
+extern void apus_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
@@ -57,7 +57,7 @@
                       unsigned long r6,
                       unsigned long r7);
 
-extern void prep_init(unsigned long r3,
+extern void gemini_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
@@ -69,19 +69,24 @@
 		     unsigned long r6,
 		     unsigned long r7);
 
-extern void apus_init(unsigned long r3,
+extern void m8260_init(unsigned long r3,
+		     unsigned long r4,
+		     unsigned long r5,
+		     unsigned long r6,
+		     unsigned long r7);
+
+extern void pmac_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
                       unsigned long r7);
 
-extern void gemini_init(unsigned long r3,
+extern void prep_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);
 
@@ -332,7 +337,7 @@
 		 * Assume here that all clock rates are the same in a
 		 * smp system.  -- Cort
 		 */
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
+#if defined(CONFIG_ALL_PPC)
 		if ( have_of )
 		{
 			struct device_node *cpu_node;
@@ -356,7 +361,7 @@
 			len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
 				       *fp / 1000000);
 		}
-#endif /* !CONFIG_4xx && !CONFIG_8xx */
+#endif /* CONFIG_ALL_PPC */
 
 		if (ppc_md.setup_residual != NULL)
 		{
@@ -379,11 +384,12 @@
 			break;
 		}
 
-		len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min);
+		len += sprintf(len+buffer, "revision\t: %hd.%hd (pvr %04x %04x)\n", 
+				maj, min, PVR_VER(pvr), PVR_REV(pvr));
 
 		len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
-			       (CD(loops_per_jiffy)+2500)/(500000/HZ),
-			       (CD(loops_per_jiffy)+2500)/(5000/HZ) % 100);
+			       CD(loops_per_jiffy)/(500000/HZ),
+			       CD(loops_per_jiffy)/(5000/HZ) % 100);
 		bogosum += CD(loops_per_jiffy);
 	}
 
@@ -391,8 +397,8 @@
 	if ( i )
 		len += sprintf(buffer+len, "\n");
 	len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
-		       (bogosum+2500)/(500000/HZ),
-		       (bogosum+2500)/(5000/HZ) % 100);
+		       bogosum/(500000/HZ),
+		       bogosum/(5000/HZ) % 100);
 #endif /* CONFIG_SMP */
 
 	/*
@@ -441,11 +447,15 @@
 }
 #endif /* CONFIG_ALL_PPC */
 
-#ifdef CONFIG_6xx
+#if defined(CONFIG_6xx) || defined(CONFIG_PPC64BRIDGE)
 /*
  * 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>
+ *
+ * Note that the kernel may be running at an address which is different
+ * from the address that it was linked at, so we must use RELOC/PTRRELOC
+ * to access static data (including strings).  -- paulus
  */
 __init
 unsigned long
@@ -454,65 +464,36 @@
 	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);
+	memset_io(PTRRELOC(&__bss_start), 0, &_end - &__bss_start);
 
-#if defined(CONFIG_ALL_PPC) || defined(CONFIG_GEMINI)
+#if defined(CONFIG_ALL_PPC)
 	/* 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>
+
+	/* 
+	 * for now, don't use bootinfo because it breaks yaboot 0.5
+	 * and assume that if we didn't find a magic number, we have OF
 	 */
-	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];
-			}
-		}
-	}
+	phys = prom_init(r3, r4, (prom_entry)r5);
+#endif
 
-	if ( local_have_of )
-		phys = prom_init( r3, r4, (prom_entry)r5);
-#endif	
-	
 	return phys;
 }
-#endif /* CONFIG_6xx */
+#endif /* CONFIG_6xx || CONFIG_PPC64BRIDGE */
 
 /*
  * Find out what kind of machine we're on and save any data we need
@@ -522,6 +503,10 @@
 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
 		 unsigned long r6, unsigned long r7)
 {
+#ifdef CONFIG_CMDLINE
+	strcpy(cmd_line, CONFIG_CMDLINE);
+#endif /* CONFIG_CMDLINE */
+
 	parse_bootinfo();
 
 	if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
@@ -809,7 +794,7 @@
 	ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && defined(CONFIG_ALL_PPC)
 	/* We create the "pci-OF-bus-map" property now so it appear in the
 	 * /proc device tree
 	 */
@@ -825,7 +810,7 @@
 			prom_add_property(find_path_device("/"), of_prop);
 		}
 	}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI && CONFIG_ALL_PPC */
 
 	paging_init();
 	sort_exception_table();
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S
--- linux-2.4.6-pre8/arch/ppc/kernel/sleep.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/sleep.S	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.sleep.S 1.7 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.sleep.S 1.10 06/28/01 15:50:17 paulus
  */
 /*
  * This file contains sleep low-level functions for PowerBook G3.
@@ -194,7 +194,7 @@
 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
 	li	r4,0
 3:	mtsrin	r3,r4
-	addi	r3,r3,1		/* increment VSID */
+	addi	r3,r3,0x111	/* increment VSID */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
 	
diff -urN linux-2.4.6-pre8/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- linux-2.4.6-pre8/arch/ppc/kernel/traps.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/traps.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.traps.c 1.11 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.traps.c 1.14 06/15/01 13:00:20 paulus
  */
 /*
  *  linux/arch/ppc/kernel/traps.c
@@ -82,7 +82,6 @@
 	spin_lock_irq(&oops_lock);
 	printk("Oops: %s, sig: %ld\n", str, err);
 	show_regs(fp);
-	print_backtrace((unsigned long *)fp->gpr[1]);
 	spin_unlock_irq(&oops_lock);
 	/* do_exit() should take care of panic'ing from an interrupt
 	 * context so we don't handle it here
@@ -186,7 +185,6 @@
 	}
 #endif
 	show_regs(regs);
-	print_backtrace((unsigned long *)regs->gpr[1]);
 	panic("System Management Interrupt");
 }
 
@@ -334,7 +332,6 @@
 	debugger(regs);
 #endif
 	show_regs(regs);
-	print_backtrace((unsigned long *)regs->gpr[1]);
 	panic("kernel stack overflow");
 }
 
diff -urN linux-2.4.6-pre8/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile
--- linux-2.4.6-pre8/arch/ppc/mm/Makefile	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/mm/Makefile	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+# BK Id: SCCS/s.Makefile 1.6 06/28/01 15:50:17 paulus
 #
 #
 # Makefile for the linux ppc-specific parts of the memory manager.
@@ -9,8 +9,20 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+USE_STANDARD_AS_RULE	:= true
+
+ifdef CONFIG_PPC64BRIDGE
+EXTRA_AFLAGS		:= -Wa,-mppc64bridge
+endif
+
 O_TARGET		:= mm.o
 obj-y			:= fault.o init.o mem_pieces.o extable.o
+
+ifneq ($(CONFIG_8xx),y)
+ifneq ($(CONFIG_4xx),y)
+obj-y			+= hashtable.o
+endif
+endif
 
 obj-$(CONFIG_4xx)	+= 4xx_tlb.o
 
diff -urN linux-2.4.6-pre8/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- linux-2.4.6-pre8/arch/ppc/mm/fault.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/mm/fault.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.fault.c 1.10 05/17/01 18:14:23 cort
+ * BK Id: SCCS/s.fault.c 1.13 06/28/01 15:50:17 paulus
  */
 /*
  *  arch/ppc/mm/fault.c
@@ -44,11 +44,12 @@
 int debugger_kernel_faults = 1;
 #endif
 
-unsigned long htab_reloads = 0; /* updated by head.S:hash_page() */
-unsigned long htab_evicts = 0;  /* updated by head.S:hash_page() */
-unsigned long pte_misses = 0; /* updated by do_page_fault() */
-unsigned long pte_errors = 0; /* updated by do_page_fault() */
-unsigned int probingmem = 0;
+unsigned long htab_reloads;	/* updated by hashtable.S:hash_page() */
+unsigned long htab_evicts; 	/* updated by hashtable.S:hash_page() */
+unsigned long htab_preloads;	/* updated by hashtable.S:add_hash_page() */
+unsigned long pte_misses;	/* updated by do_page_fault() */
+unsigned long pte_errors;	/* updated by do_page_fault() */
+unsigned int probingmem;
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
 void bad_page_fault(struct pt_regs *, unsigned long, int sig);
diff -urN linux-2.4.6-pre8/arch/ppc/mm/hashtable.S linux/arch/ppc/mm/hashtable.S
--- linux-2.4.6-pre8/arch/ppc/mm/hashtable.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mm/hashtable.S	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,627 @@
+/*
+ * BK Id: SCCS/s.hashtable.S 1.16 06/29/01 08:51:52 paulus
+ */
+/*
+ *  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
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *  Adapted for Power Macintosh by Paul Mackerras.
+ *  Low-level exception handlers and MMU support
+ *  rewritten by Paul Mackerras.
+ *    Copyright (C) 1996 Paul Mackerras.
+ *
+ *  This file contains low-level assembler routines for managing
+ *  the PowerPC MMU hash table.  (PPC 8xx processors don't use a
+ *  hash table, so this file is not used on them.)
+ *
+ *  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.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_SMP
+	.comm	hash_table_lock,4
+#endif /* CONFIG_SMP */
+
+/*
+ * Load a PTE into the hash table, if possible.
+ * The address is in r4, and r3 contains an access flag:
+ * _PAGE_RW (0x400) if a write.
+ * r23 contains the SRR1 value, from which we use the MSR_PR bit.
+ * SPRG3 contains the physical address of the current task's thread.
+ *
+ * Returns to the caller if the access is illegal or there is no
+ * mapping for the address.  Otherwise it places an appropriate PTE
+ * in the hash table and returns from the exception.
+ * Uses r0, r2 - r7, ctr, lr.
+ */
+	.text
+	.globl	hash_page
+hash_page:
+#ifdef CONFIG_PPC64BRIDGE
+	mfmsr	r0
+	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
+	MTMSRD(r0)
+	isync
+#endif
+	tophys(r7,0)			/* gets -KERNELBASE into r7 */
+#ifdef CONFIG_SMP
+	addis	r2,r7,hash_table_lock@h
+	ori	r2,r2,hash_table_lock@l
+	mfspr	r5,SPRG3
+	lwz	r0,PROCESSOR-THREAD(r5)
+	oris	r0,r0,0x0fff
+	b	10f
+11:	lwz	r6,0(r2)
+	cmpwi	0,r6,0
+	bne	11b
+10:	lwarx	r6,0,r2
+	cmpwi	0,r6,0
+	bne-	11b
+	stwcx.	r0,0,r2
+	bne-	10b
+	isync
+#endif
+	/* Get PTE (linux-style) and check access */
+	lis	r0,KERNELBASE@h		/* check if kernel address */
+	cmplw	0,r4,r0
+	mfspr	r2,SPRG3		/* current task's THREAD (phys) */
+	ori	r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
+	lwz	r5,PGDIR(r2)		/* virt page-table root */
+	blt+	112f			/* assume user more likely */
+	lis	r5,swapper_pg_dir@ha	/* if kernel address, use */
+	addi	r5,r5,swapper_pg_dir@l	/* kernel page table */
+	rlwimi	r3,r23,32-12,29,29	/* MSR_PR -> _PAGE_USER */
+112:	add	r5,r5,r7		/* convert to phys addr */
+	rlwimi	r5,r4,12,20,29		/* insert top 10 bits of address */
+	lwz	r5,0(r5)		/* get pmd entry */
+	rlwinm.	r5,r5,0,0,19		/* extract address of pte page */
+#ifdef CONFIG_SMP
+	beq-	hash_page_out		/* return if no mapping */
+#else
+	/* XXX it seems like the 601 will give a machine fault on the
+	   rfi if its alignment is wrong (bottom 4 bits of address are
+	   8 or 0xc) and we have had a not-taken conditional branch
+	   to the address following the rfi. */
+	beqlr-
+#endif
+	add	r2,r5,r7		/* convert to phys addr */
+	rlwimi	r2,r4,22,20,29		/* insert next 10 bits of address */
+	rlwinm	r0,r3,32-3,24,24	/* _PAGE_RW access -> _PAGE_DIRTY */
+	ori	r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
+
+	/*
+	 * Update the linux PTE atomically.  We do the lwarx up-front
+	 * because almost always, there won't be a permission violation
+	 * and there won't already be an HPTE, and thus we will have
+	 * to update the PTE to set _PAGE_HASHPTE.  -- paulus.
+	 */
+retry:
+	lwarx	r6,0,r2			/* get linux-style pte */
+	andc.	r5,r3,r6		/* check access & ~permission */
+#ifdef CONFIG_SMP
+	bne-	hash_page_out		/* return if access not permitted */
+#else
+	bnelr-
+#endif
+	or	r5,r0,r6		/* set accessed/dirty bits */
+	stwcx.	r5,0,r2			/* attempt to update PTE */
+	bne-	retry			/* retry if someone got there first */
+
+	mfsrin	r3,r4			/* get segment reg for segment */
+	mr	r2,r8			/* we have saved r2 but not r8 */
+	bl	create_hpte		/* add the hash table entry */
+	mr	r8,r2
+
+/*
+ * htab_reloads counts the number of times we have to fault an
+ * HPTE into the hash table.  This should only happen after a
+ * fork (because fork does a flush_tlb_mm) or a vmalloc or ioremap.
+ * Where a page is faulted into a process's address space,
+ * update_mmu_cache gets called to put the HPTE into the hash table
+ * and those are counted as preloads rather than reloads.
+ */
+	addis	r2,r7,htab_reloads@ha
+	lwz	r3,htab_reloads@l(r2)
+	addi	r3,r3,1
+	stw	r3,htab_reloads@l(r2)
+
+#ifdef CONFIG_SMP
+	eieio
+	addis	r2,r7,hash_table_lock@ha
+	li	r0,0
+	stw	r0,hash_table_lock@l(r2)
+#endif
+
+	/* Return from the exception */
+	lwz	r3,_CCR(r21)
+	lwz	r4,_LINK(r21)
+	lwz	r5,_CTR(r21)
+	mtcrf	0xff,r3
+	mtlr	r4
+	mtctr	r5
+	lwz	r0,GPR0(r21)
+	lwz	r1,GPR1(r21)
+	lwz	r2,GPR2(r21)
+	lwz	r3,GPR3(r21)
+	lwz	r4,GPR4(r21)
+	lwz	r5,GPR5(r21)
+	lwz	r6,GPR6(r21)
+	lwz	r7,GPR7(r21)
+	/* we haven't used xer */
+	mtspr	SRR1,r23
+	mtspr	SRR0,r22
+	lwz	r20,GPR20(r21)
+	lwz	r22,GPR22(r21)
+	lwz	r23,GPR23(r21)
+	lwz	r21,GPR21(r21)
+	RFI
+	
+#ifdef CONFIG_SMP
+hash_page_out:
+	eieio
+	addis	r2,r7,hash_table_lock@ha
+	li	r0,0
+	stw	r0,hash_table_lock@l(r2)
+	blr
+#endif /* CONFIG_SMP */
+
+/*
+ * Add an entry for a particular page to the hash table.
+ *
+ * add_hash_page(unsigned context, unsigned long va, pte_t pte)
+ *
+ * We assume any necessary modifications to the pte (e.g. setting
+ * the accessed bit) have already been done and that there is actually
+ * a hash table in use (i.e. we're not on a 603).
+ */
+_GLOBAL(add_hash_page)
+	mflr	r0
+	stw	r0,4(r1)
+
+	/* Convert context and va to VSID */
+	mulli	r3,r3,897*16		/* multiply context by context skew */
+	rlwinm	r0,r4,4,28,31		/* get ESID (top 4 bits of va) */
+	mulli	r0,r0,0x111		/* multiply by ESID skew */
+	add	r3,r3,r0		/* note create_hpte trims to 24 bits */
+
+	/*
+	 * We disable interrupts here, even on UP, because we don't
+	 * want to race with hash_page, and because we want the
+	 * _PAGE_HASHPTE bit to be a reliable indication of whether
+	 * the HPTE exists (or at least whether one did once).  -- paulus
+	 */
+	mfmsr	r10
+	SYNC
+	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
+	mtmsr	r0
+	SYNC
+
+#ifdef CONFIG_SMP
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+	lwz	r8,PROCESSOR(r2)
+	oris	r8,r8,10
+10:	lwarx	r7,0,r9
+	cmpi	0,r7,0
+	bne-	11f
+	stwcx.	r8,0,r9
+	beq+	12f
+11:	lwz	r7,0(r9)
+	cmpi	0,r7,0
+	beq	10b
+	b	11b
+12:	isync
+#endif
+
+	/*
+	 * Fetch the linux pte and test and set _PAGE_HASHPTE atomically.
+	 * If _PAGE_HASHPTE was already set, we don't replace the existing
+	 * HPTE, so we just unlock and return.
+	 */
+	mr	r7,r5
+1:	lwarx	r6,0,r7
+	andi.	r0,r6,_PAGE_HASHPTE
+	bne	9f			/* if HASHPTE already set, done */
+	ori	r5,r6,_PAGE_ACCESSED|_PAGE_HASHPTE
+	stwcx.	r5,0,r7
+	bne-	1b
+
+	li	r7,0			/* no address offset needed */
+	bl	create_hpte
+
+	lis	r8,htab_preloads@ha
+	lwz	r3,htab_preloads@l(r8)
+	addi	r3,r3,1
+	stw	r3,htab_preloads@l(r8)
+
+9:
+#ifdef CONFIG_SMP
+	eieio
+	li	r0,0
+	stw	r0,0(r9)		/* clear hash_table_lock */
+#endif
+
+	lwz	r0,4(r1)
+	mtlr	r0
+
+	/* reenable interrupts */
+	mtmsr	r10
+	SYNC
+	blr
+
+/*
+ * This routine adds a hardware PTE to the hash table.
+ * It is designed to be called with the MMU either on or off.
+ * r3 contains the VSID, r4 contains the virtual address,
+ * r5 contains the linux PTE, r6 contains the old value of the
+ * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
+ * offset to be added to addresses (0 if the MMU is on,
+ * -KERNELBASE if it is off).
+ * On SMP, the caller should have the hash_table_lock held.
+ * We assume that the caller has (or will) set the _PAGE_HASHPTE
+ * bit in the linux PTE in memory.  The value passed in r6 should
+ * be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set
+ * this routine will skip the search for an existing HPTE.
+ * This procedure modifies r0, r3 - r6, r8, cr0.
+ *  -- paulus.
+ *
+ * For speed, 4 of the instructions get patched once the size and
+ * physical address of the hash table are known.  These definitions
+ * of Hash_base and Hash_bits below are just an example.
+ */
+Hash_base = 0xc0180000
+Hash_bits = 12				/* e.g. 256kB hash table */
+Hash_msk = (((1 << Hash_bits) - 1) * 64)
+
+#ifndef CONFIG_PPC64BRIDGE
+/* defines for the PTE format for 32-bit PPCs */
+#define PTE_SIZE	8
+#define PTEG_SIZE	64
+#define LG_PTEG_SIZE	6
+#define LDPTEu		lwzu
+#define STPTE		stw
+#define CMPPTE		cmpw
+#define PTE_H		0x40
+#define PTE_V		0x80000000
+#define TST_V(r)	rlwinm. r,r,0,0,0
+#define SET_V(r)	oris r,r,PTE_V@h
+#define CLR_V(r,t)	rlwinm r,r,0,1,31
+
+#else
+/* defines for the PTE format for 64-bit PPCs */
+#define PTE_SIZE	16
+#define PTEG_SIZE	128
+#define LG_PTEG_SIZE	7
+#define LDPTEu		ldu
+#define STPTE		std
+#define CMPPTE		cmpd
+#define PTE_H		2
+#define PTE_V		1
+#define TST_V(r)	andi. r,r,PTE_V
+#define SET_V(r)	ori r,r,PTE_V
+#define CLR_V(r,t)	li t,PTE_V; andc r,r,t
+#endif /* CONFIG_PPC64BRIDGE */
+
+#define HASH_LEFT	31-(LG_PTEG_SIZE+Hash_bits-1)
+#define HASH_RIGHT	31-LG_PTEG_SIZE
+
+_GLOBAL(create_hpte)
+	/* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
+	rlwinm	r8,r5,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r0,r5,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	and	r8,r8,r0		/* writable if _RW & _DIRTY */
+	rlwimi	r5,r5,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r5,r5,32-2,31,31	/* _PAGE_USER -> PP lsb */
+	ori	r8,r8,0xe14		/* clear out reserved bits and M */
+	andc	r8,r5,r8		/* PP = user? (rw&dirty? 2: 3): 0 */
+#ifdef CONFIG_SMP
+	ori	r8,r8,_PAGE_COHERENT	/* set M (coherence required) */
+#endif
+
+#ifdef CONFIG_POWER4
+	/*
+	 * XXX hack hack hack - translate 32-bit "physical" addresses
+	 * in the linux page tables to 42-bit real addresses in such
+	 * a fashion that we can get at the I/O we need to access.
+	 *	-- paulus
+	 */
+	cmpwi	r8,0
+	rlwinm	r0,r8,16,16,30
+	bge	57f
+	cmplwi	r0,0xfe00
+	li	r0,0x3fd
+	bne	56f
+	li	r0,0x3ff
+56:	sldi	r0,r0,32
+	or	r8,r8,r0
+57:
+#endif
+
+	/* Construct the high word of the PPC-style PTE (r5) */
+#ifndef CONFIG_PPC64BRIDGE
+	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
+	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
+	sldi	r5,r3,12		/* shift vsid into position */
+	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+	SET_V(r5)			/* set V (valid) bit */
+
+	/* Get the address of the primary PTE group in the hash table (r3) */
+	.globl	hash_page_patch_A
+hash_page_patch_A:
+	addis	r0,r7,Hash_base@h	/* base address of hash table */
+	rlwimi	r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
+	rlwinm	r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+	xor	r3,r3,r0		/* make primary hash */
+	li	r0,8			/* PTEs/group */
+
+	/*
+	 * Test the _PAGE_HASHPTE bit in the old linux PTE, and skip the search
+	 * if it is clear, meaning that the HPTE isn't there already...
+	 */
+	andi.	r6,r6,_PAGE_HASHPTE
+	beq+	10f			/* no PTE: go look for an empty slot */
+	tlbie	r4
+
+	addis	r4,r7,htab_hash_searches@ha
+	lwz	r6,htab_hash_searches@l(r4)
+	addi	r6,r6,1			/* count how many searches we do */
+	stw	r6,htab_hash_searches@l(r4)
+
+	/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
+	mtctr	r0
+	addi	r4,r3,-PTE_SIZE
+1:	LDPTEu	r6,PTE_SIZE(r4)		/* get next PTE */
+	CMPPTE	0,r6,r5
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	found_slot
+
+	/* Search the secondary PTEG for a matching PTE */
+	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
+	.globl	hash_page_patch_B
+hash_page_patch_B:
+	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
+	xori	r4,r4,(-PTEG_SIZE & 0xffff)
+	addi	r4,r4,-PTE_SIZE
+	mtctr	r0
+2:	LDPTEu	r6,PTE_SIZE(r4)
+	CMPPTE	0,r6,r5
+	bdnzf	2,2b
+	beq+	found_slot
+	xori	r5,r5,PTE_H		/* clear H bit again */
+
+	/* Search the primary PTEG for an empty slot */
+10:	mtctr	r0
+	addi	r4,r3,-PTE_SIZE		/* search primary PTEG */
+1:	LDPTEu	r6,PTE_SIZE(r4)		/* get next PTE */
+	TST_V(r6)			/* test valid bit */
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	found_empty
+
+	/* update counter of times that the primary PTEG is full */
+	addis	r4,r7,primary_pteg_full@ha
+	lwz	r6,primary_pteg_full@l(r4)
+	addi	r6,r6,1
+	stw	r6,primary_pteg_full@l(r4)
+
+	/* Search the secondary PTEG for an empty slot */
+	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
+	.globl	hash_page_patch_C
+hash_page_patch_C:
+	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
+	xori	r4,r4,(-PTEG_SIZE & 0xffff)
+	addi	r4,r4,-PTE_SIZE
+	mtctr	r0
+2:	LDPTEu	r6,PTE_SIZE(r4)
+	TST_V(r6)
+	bdnzf	2,2b
+	beq+	found_empty
+	xori	r5,r5,PTE_H		/* clear H bit again */
+
+	/*
+	 * Choose an arbitrary slot in the primary PTEG to overwrite.
+	 * Since both the primary and secondary PTEGs are full, and we
+	 * have no information that the PTEs in the primary PTEG are
+	 * more important or useful than those in the secondary PTEG,
+	 * and we know there is a definite (although small) speed
+	 * advantage to putting the PTE in the primary PTEG, we always
+	 * put the PTE in the primary PTEG.
+	 */
+	addis	r4,r7,next_slot@ha
+	lwz	r6,next_slot@l(r4)
+	addi	r6,r6,PTE_SIZE
+	andi.	r6,r6,7*PTE_SIZE
+#ifdef CONFIG_POWER4
+	/*
+	 * Since we don't have BATs on POWER4, we rely on always having
+	 * PTEs in the hash table to map the hash table and the code
+	 * that manipulates it in virtual mode, namely flush_hash_page and
+	 * flush_hash_segments.  Otherwise we can get a DSI inside those
+	 * routines which leads to a deadlock on the hash_table_lock on
+	 * SMP machines.  We avoid this by never overwriting the first
+	 * PTE of each PTEG if it is already valid.
+	 *	-- paulus.
+	 */
+	bne	102f
+	li	r6,PTE_SIZE
+102:
+#endif /* CONFIG_POWER4 */
+	stw	r6,next_slot@l(r4)
+	add	r4,r3,r6
+
+	/* update counter of evicted pages */
+	addis	r6,r7,htab_evicts@ha
+	lwz	r3,htab_evicts@l(r6)
+	addi	r3,r3,1
+	stw	r3,htab_evicts@l(r6)
+
+#ifndef CONFIG_SMP
+	/* Store PTE in PTEG */
+found_empty:
+	STPTE	r5,0(r4)
+found_slot:
+	STPTE	r8,PTE_SIZE/2(r4)
+
+#else /* CONFIG_SMP */
+/*
+ * Between the tlbie above and updating the hash table entry below,
+ * another CPU could read the hash table entry and put it in its TLB.
+ * There are 3 cases:
+ * 1. using an empty slot
+ * 2. updating an earlier entry to change permissions (i.e. enable write)
+ * 3. taking over the PTE for an unrelated address
+ *
+ * In each case it doesn't really matter if the other CPUs have the old
+ * PTE in their TLB.  So we don't need to bother with another tlbie here,
+ * which is convenient as we've overwritten the register that had the
+ * address. :-)  The tlbie above is mainly to make sure that this CPU comes
+ * and gets the new PTE from the hash table.
+ *
+ * We do however have to make sure that the PTE is never in an invalid
+ * state with the V bit set.
+ */
+found_empty:
+found_slot:
+	CLR_V(r5,r0)		/* clear V (valid) bit in PTE */
+	STPTE	r5,0(r4)
+	sync
+	TLBSYNC
+	STPTE	r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
+	sync
+	SET_V(r5)
+	STPTE	r5,0(r4)	/* finally set V bit in PTE */
+#endif /* CONFIG_SMP */
+
+	sync		/* make sure pte updates get to memory */
+	blr
+
+	.comm	next_slot,4
+	.comm	primary_pteg_full,4
+	.comm	htab_hash_searches,4
+
+/*
+ * Flush the entry for a particular page from the hash table.
+ *
+ * flush_hash_page(unsigned context, unsigned long va, pte_t *ptep)
+ *
+ * We assume that there is a hash table in use (Hash != 0).
+ */
+_GLOBAL(flush_hash_page)
+	/* Convert context and va to VSID */
+	mulli	r3,r3,897*16		/* multiply context by context skew */
+	rlwinm	r0,r4,4,28,31		/* get ESID (top 4 bits of va) */
+	mulli	r0,r0,0x111		/* multiply by ESID skew */
+	add	r3,r3,r0		/* note code below trims to 24 bits */
+
+	/*
+	 * We disable interrupts here, even on UP, because we want
+	 * the _PAGE_HASHPTE bit to be a reliable indication of
+	 * whether the HPTE exists.  -- paulus
+	 */
+	mfmsr	r10
+	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
+	SYNC
+	mtmsr	r0
+	SYNC
+
+#ifdef CONFIG_SMP
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+	lwz	r8,PROCESSOR(r2)
+	oris	r8,r8,9
+10:	lwarx	r7,0,r9
+	cmpi	0,r7,0
+	bne-	11f
+	stwcx.	r8,0,r9
+	beq+	12f
+11:	lwz	r7,0(r9)
+	cmpi	0,r7,0
+	beq	10b
+	b	11b
+12:	isync
+#endif
+
+	/*
+	 * Check the _PAGE_HASHPTE bit in the linux PTE.  If it is
+	 * already clear, we're done.  If not, clear it (atomically)
+	 * and proceed.  -- paulus.
+	 */
+1:	lwarx	r6,0,r5			/* fetch the pte */
+	andi.	r0,r6,_PAGE_HASHPTE
+	beq	9f			/* done if HASHPTE is already clear */
+	rlwinm	r6,r6,0,31,29		/* clear HASHPTE bit */
+	stwcx.	r6,0,r5			/* update the pte */
+	bne-	1b
+
+	/* Construct the high word of the PPC-style PTE (r5) */
+#ifndef CONFIG_PPC64BRIDGE
+	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
+	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
+	sldi	r5,r3,12		/* shift vsid into position */
+	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+	SET_V(r5)			/* set V (valid) bit */
+
+	/* Get the address of the primary PTE group in the hash table (r3) */
+	.globl	flush_hash_patch_A
+flush_hash_patch_A:
+	lis	r8,Hash_base@h		/* base address of hash table */
+	rlwimi	r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
+	rlwinm	r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+	xor	r3,r3,r8		/* make primary hash */
+	li	r8,8			/* PTEs/group */
+
+	/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
+	mtctr	r8
+	addi	r7,r3,-PTE_SIZE
+1:	LDPTEu	r0,PTE_SIZE(r7)		/* get next PTE */
+	CMPPTE	0,r0,r5
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	3f
+
+	/* Search the secondary PTEG for a matching PTE */
+	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
+	.globl	flush_hash_patch_B
+flush_hash_patch_B:
+	xoris	r7,r3,Hash_msk>>16	/* compute secondary hash */
+	xori	r7,r7,(-PTEG_SIZE & 0xffff)
+	addi	r7,r7,-PTE_SIZE
+	mtctr	r8
+2:	LDPTEu	r0,PTE_SIZE(r7)
+	CMPPTE	0,r0,r5
+	bdnzf	2,2b
+	bne-	4f			/* should never fail to find it */
+
+3:	li	r0,0
+	STPTE	r0,0(r7)		/* invalidate entry */
+4:	sync
+	tlbie	r4			/* in hw tlb too */
+	sync
+
+#ifdef CONFIG_SMP
+	TLBSYNC
+9:	li	r0,0
+	stw	r0,0(r9)		/* clear hash_table_lock */
+#endif
+
+9:	mtmsr	r10
+	SYNC
+	blr
diff -urN linux-2.4.6-pre8/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- linux-2.4.6-pre8/arch/ppc/mm/init.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/mm/init.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.init.c 1.22 05/17/01 18:14:23 cort
+ * BK Id: SCCS/s.init.c 1.27 06/28/01 15:50:17 paulus
  */
 /*
  *  PowerPC version 
@@ -73,9 +73,15 @@
 
 #define	PGTOKB(pages)	(((pages) * PAGE_SIZE) >> 10)
 
+mm_context_t next_mmu_context;
+unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+#ifdef FEW_CONTEXTS
+atomic_t nr_free_contexts;
+struct mm_struct *context_mm[LAST_CONTEXT+1];
+void steal_context(void);
+#endif /* FEW_CONTEXTS */
+
 int prom_trashed;
-atomic_t next_mmu_context;
-rwlock_t context_overflow_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
 unsigned long *end_of_DRAM;
 unsigned long total_memory;
 unsigned long total_lowmem;
@@ -187,12 +193,6 @@
 /* max amount of low RAM to map in */
 unsigned long __max_low_memory = MAX_LOW_MEM;
 
-void __bad_pte(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_val(*pmd) = (unsigned long) BAD_PAGETABLE;
-}
-
 int do_check_pgt_cache(int low, int high)
 {
 	int freed = 0;
@@ -211,35 +211,6 @@
 	return freed;
 }
 
-/*
- * 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..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-pte_t *empty_bad_page_table;
-
-pte_t * __bad_pagetable(void)
-{
-	clear_page(empty_bad_page_table);
-	return empty_bad_page_table;
-}
-
-void *empty_bad_page;
-
-pte_t __bad_page(void)
-{
-	clear_page(empty_bad_page);
-	return pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED));
-}
-
 void show_mem(void)
 {
 	int i,free = 0,total = 0,reserved = 0;
@@ -319,21 +290,10 @@
 
 void si_meminfo(struct sysinfo *val)
 {
-	int i;
-
-	i = max_mapnr;
-	val->totalram = 0;
+	val->totalram = totalram_pages;
 	val->sharedram = 0;
 	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
-	while (i-- > 0)  {
-		if (PageReserved(mem_map+i))
-			continue;
-		val->totalram++;
-		if (!atomic_read(&mem_map[i].count))
-			continue;
-		val->sharedram += atomic_read(&mem_map[i].count) - 1;
-	}
 	val->totalhigh = totalhigh_pages;
 	val->freehigh = nr_free_highpages();
 	val->mem_unit = PAGE_SIZE;
@@ -482,14 +442,16 @@
 	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);
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+		if (mem_init_done && Hash != 0)
+			flush_hash_page(0, va, pg);
+#endif /* !4xx && !8xx */
 	}
 	spin_unlock(&init_mm.page_table_lock);
 	return err;
 }
 
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 /*
  * TLB flushing:
  *
@@ -510,19 +472,14 @@
 void
 local_flush_tlb_all(void)
 {
-#ifdef CONFIG_PPC64BRIDGE
-	/* XXX this assumes that the vmalloc arena starts no lower than
-	 * 0xd0000000 on 64-bit machines. */
-	flush_hash_segments(0xd, 0xffffff);
-#else
-	/* this could cause problems on SMP with nobats  -- paulus */
-	/* XXX no hash_table_lock?  interesting  -- paulus */
-	__clear_user(Hash, Hash_size);
-	_tlbia();
+	/* aargh!!! */
+	/* just flush the kernel part of the address space, that's
+	   all that the current callers of this require.  -- paulus. */
+	local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL);
+
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif /* CONFIG_SMP */
-#endif /* CONFIG_PPC64BRIDGE */
 }
 
 /*
@@ -533,30 +490,18 @@
 void
 local_flush_tlb_mm(struct mm_struct *mm)
 {
-	if (mm->context == 0) {
-		/* don't try to reassign a new context to the kernel */
-		/*
-		 * This could cause problems on SMP if we aren't using
-		 * the BATs (e.g. on POWER4 or if the nobats option is used).
-		 * The problem scenario is that one cpu is doing
-		 * flush_hash_page or similar when another cpu clears
-		 * out the HPTEs which map the flush_hash_page text
-		 * and the hash table.  hash_page will then deadlock.
-		 * We need some way to have "protected" HPTEs or else
-		 * do all hash-table manipulation with the MMU off.
-		 *  -- paulus.
-		 */
-#ifdef CONFIG_PPC64BRIDGE
-		flush_hash_segments(0xd, 0xf);
-#else
-		flush_hash_segments(0xc, 0xf);
-#endif CONFIG_PPC64BRIDGE
+	if (Hash == 0) {
 		_tlbia();
 		return;
 	}
-	mm->context = NO_CONTEXT;
-	if (mm == current->mm)
-		activate_mm(mm, mm);
+
+	if (mm->map_count) {
+		struct vm_area_struct *mp;
+		for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
+			local_flush_tlb_range(mm, mp->vm_start, mp->vm_end);
+	} else
+		local_flush_tlb_range(mm, 0, TASK_SIZE);
+
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif	
@@ -565,10 +510,21 @@
 void
 local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
-	if (vmaddr < TASK_SIZE)
-		flush_hash_page(vma->vm_mm->context, vmaddr);
-	else
-		flush_hash_page(0, vmaddr);
+	struct mm_struct *mm;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (Hash == 0) {
+		_tlbie(vmaddr);
+		return;
+	}
+	mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
+	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
+	if (!pmd_none(*pmd)) {
+		pte = pte_offset(pmd, vmaddr);
+		if (pte_val(*pte) & _PAGE_HASHPTE)
+			flush_hash_page(mm->context, vmaddr, pte);
+	}
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif	
@@ -576,28 +532,43 @@
 
 
 /*
- * for each page addr in the range, call MMU_invalidate_page()
- * if the range is very large and the hash table is small it might be
- * faster to do a search of the hash table and just invalidate pages
- * that are in the range but that's for study later.
- * -- Cort
+ * For each address in the range, find the pte for the address
+ * and check _PAGE_HASHPTE bit; if it is set, find and destroy
+ * the corresponding HPTE.
  */
 void
 local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
 {
-	start &= PAGE_MASK;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long pmd_end;
+	unsigned int ctx = mm->context;
 
-	if (mm->context != 0) {
-		if (end > TASK_SIZE)
-			end = TASK_SIZE;
-		if (end - start > 20 * PAGE_SIZE) {
-			flush_tlb_mm(mm);
-			return;
-		}
+	if (Hash == 0) {
+		_tlbia();
+		return;
 	}
-
-	for (; start < end; start += PAGE_SIZE)
-		flush_hash_page(mm->context, start);
+	start &= PAGE_MASK;
+	if (start >= end)
+		return;
+	pmd = pmd_offset(pgd_offset(mm, start), start);
+	do {
+		pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK;
+		if (!pmd_none(*pmd)) {
+			if (!pmd_end || pmd_end > end)
+				pmd_end = end;
+			pte = pte_offset(pmd, start);
+			do {
+				if ((pte_val(*pte) & _PAGE_HASHPTE) != 0)
+					flush_hash_page(ctx, start, pte);
+				start += PAGE_SIZE;
+				++pte;
+			} while (start && start < pmd_end);
+		} else {
+			start = pmd_end;
+		}
+		++pmd;
+	} while (start && start < end);
 
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
@@ -605,59 +576,6 @@
 }
 
 /*
- * The context counter has overflowed.
- * We set mm->context to NO_CONTEXT for all mm's in the system.
- * We assume we can get to all mm's by looking as tsk->mm for
- * all tasks in the system.
- */
-void
-mmu_context_overflow(void)
-{
-	struct task_struct *tsk;
-
-	printk(KERN_DEBUG "mmu_context_overflow\n");
-	/* acquire the write lock for context overflow */
-	write_lock (&context_overflow_lock);
-	/* recheck if overflow still exists */
-	if (atomic_read(&next_mmu_context) == LAST_CONTEXT) {
-		read_lock(&tasklist_lock);
-		for_each_task(tsk) {
-			if (tsk->mm)
-				tsk->mm->context = NO_CONTEXT;
-		}
-		read_unlock(&tasklist_lock);
-		flush_hash_segments(0x10, 0xffffff);
-#ifdef CONFIG_SMP
-		smp_send_tlb_invalidate(0);
-#endif	
-		atomic_set(&next_mmu_context, 0);
-	}
-	write_unlock (&context_overflow_lock);
-	/* make sure current always has a context */
-	/* need to check to assure current task has an mm */
-	/*   - idle thread does not have an MM */
-	if (current->mm) {
-		current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
-		set_context(current->mm->context, current->mm->pgd);
-	}
-}
-#else /* CONFIG_8xx */
-void
-mmu_context_overflow(void)
-{
-	atomic_set(&next_mmu_context, -1);
-}
-#endif /* CONFIG_8xx */
-
-void flush_page_to_ram(struct page *page)
-{
-	unsigned long vaddr = (unsigned long) kmap(page);
-	__flush_page_to_ram(vaddr);
-	kunmap(page);
-}
-
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-/*
  * 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
  * of 2 between 128k and 256M.
@@ -717,8 +635,6 @@
 /*
  * Map in all of physical memory starting at KERNELBASE.
  */
-#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-
 static void __init mapin_ram(void)
 {
 	unsigned long v, p, s, f;
@@ -768,10 +684,10 @@
 		f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
 		/* Allows stub to set breakpoints everywhere */
-		f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+		f |= _PAGE_RW | _PAGE_DIRTY;
 #else
 		if ((char *) v < _stext || (char *) v >= etext)
-			f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+			f |= _PAGE_RW | _PAGE_DIRTY;
 #ifndef CONFIG_8xx
 		else
 			/* On the powerpc (not 8xx), no user access
@@ -839,16 +755,59 @@
 #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
 
+/*
+ * Initialize the context management stuff.
+ */
+static void mmu_context_init(void)
+{
+	context_map[0] = 1;	/* init_mm uses context 0 */
+	next_mmu_context = 1;
+#ifdef FEW_CONTEXTS
+	atomic_set(&nr_free_contexts, LAST_CONTEXT);
+	context_mm[0] = &init_mm;
+#endif /* FEW_CONTEXTS */
+}
+
+#ifdef FEW_CONTEXTS
+/*
+ * Steal a context from a task that has one at the moment.
+ * This is only used on 8xx and 4xx and we presently assume that
+ * they don't do SMP.  If they do then this will have to check
+ * whether the MM we steal is in use.
+ * We also assume that this is only used on systems that don't
+ * use an MMU hash table - this is true for 8xx and 4xx.
+ * This isn't an LRU system, it just frees up each context in
+ * turn (sort-of pseudo-random replacement :).  This would be the
+ * place to implement an LRU scheme if anyone was motivated to do it.
+ *  -- paulus
+ */
+void steal_context(void)
+{
+	struct mm_struct *mm;
+
+	/* free up context `next_mmu_context' */
+	/* if we shouldn't free context 0, don't... */
+#ifdef CONFIG_4xx
+	if (next_mmu_context == 0)
+		next_mmu_context = 1;
+#endif /* CONFIG_4xx */
+	mm = context_mm[next_mmu_context];
+	flush_tlb_mm(mm);
+	destroy_context(mm);
+}
+#endif /* FEW_CONTEXTS */
+
 extern boot_infos_t *disp_bi;
 
 /*
@@ -903,6 +862,8 @@
 
         mtspr(SPRN_DCCR, 0x80000000);	/* 128 MB of data space at 0x0. */
         mtspr(SPRN_ICCR, 0x80000000);	/* 128 MB of instr. space at 0x0. */
+
+	mmu_context_init();
 }
 
 #else /* !CONFIG_4xx */
@@ -938,11 +899,7 @@
 	/* Map in all of RAM starting at KERNELBASE */
 	mapin_ram();
 
-#if defined(CONFIG_POWER4)
-	ioremap_base = ioremap_bot = 0xfffff000;
-	isa_io_base = (unsigned long) ioremap(0xffd00000, 0x200000) + 0x100000;
-
-#elif defined(CONFIG_8xx)
+#if 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
@@ -974,7 +931,7 @@
 #ifdef CONFIG_PCI
         ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
 #endif
-#else /* !CONFIG_POWER4 && !CONFIG_8xx */
+#else /* !CONFIG_8xx */
 	/*
 	 * Setup the bat mappings we're going to load that cover
 	 * the io areas.  RAM was mapped by mapin_ram().
@@ -1024,7 +981,7 @@
 		break;
 	}
 	ioremap_bot = ioremap_base;
-#endif /* CONFIG_POWER4 || CONFIG_8xx */
+#endif /* CONFIG_8xx */
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 #ifdef CONFIG_BOOTX_TEXT
@@ -1032,6 +989,8 @@
 	if (_machine == _MACH_Pmac || _machine == _MACH_chrp)
 		map_bootx_text();
 #endif
+
+	mmu_context_init();
 }
 #endif /* CONFIG_4xx */
 
@@ -1095,12 +1054,6 @@
 #endif /* CONFIG_HIGHMEM */
 
 	/*
-	 * Grab some memory for bad_page and bad_pagetable to use.
-	 */
-	empty_bad_page = alloc_bootmem_pages(PAGE_SIZE);
-	empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE);
-
-	/*
 	 * All pages are DMA-able so we put them all in the DMA zone.
 	 */
 	zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
@@ -1128,7 +1081,6 @@
 	highmem_mapnr = total_lowmem >> PAGE_SHIFT;
 	highmem_start_page = mem_map + highmem_mapnr;
 	max_mapnr = total_memory >> PAGE_SHIFT;
-	totalram_pages += max_mapnr - highmem_mapnr;
 #else
 	max_mapnr = max_low_pfn;
 #endif /* CONFIG_HIGHMEM */
@@ -1201,15 +1153,17 @@
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 /*
- * Initialize the hash table and patch the instructions in head.S.
+ * Initialize the hash table and patch the instructions in hashtable.S.
  */
 static void __init hash_init(void)
 {
 	int Hash_bits, mb, mb2;
 	unsigned int hmask, h;
 
-	extern unsigned int hash_page_patch_A[], hash_page_patch_B[],
-		hash_page_patch_C[], hash_page[];
+	extern unsigned int hash_page_patch_A[];
+	extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
+	extern unsigned int hash_page[];
+	extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
 
 #ifdef CONFIG_PPC64BRIDGE
 	/* The hash table has already been allocated and initialized
@@ -1259,6 +1213,7 @@
 	if ( Hash_size ) {
 		Hash = mem_pieces_find(Hash_size, Hash_size);
 		cacheable_memzero(Hash, Hash_size);
+		_SDR1 = __pa(Hash) | (Hash_mask >> 10);
 	} else
 		Hash = 0;
 #endif /* CONFIG_PPC64BRIDGE */
@@ -1271,10 +1226,10 @@
 		Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
 
 		/*
-		 * Patch up the instructions in head.S:hash_page
+		 * Patch up the instructions in hashtable.S:create_hpte
 		 */
 		hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
-			| (__pa(Hash) >> 16);
+			| ((unsigned int)(Hash) >> 16);
 		hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0)
 			| (mb << 6);
 		hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0)
@@ -1283,10 +1238,6 @@
 			| hmask;
 		hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff)
 			| hmask;
-#if 0	/* see hash_page in head.S, note also patch_C ref below */
-		hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff)
-			| hmask;
-#endif
 		/*
 		 * Ensure that the locations we've patched have been written
 		 * out from the data cache and invalidated in the instruction
@@ -1294,6 +1245,19 @@
 		 */
 		flush_icache_range((unsigned long) &hash_page_patch_A[0],
 				   (unsigned long) &hash_page_patch_C[1]);
+		/*
+		 * Patch up the instructions in hashtable.S:flush_hash_page
+		 */
+		flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
+			| ((unsigned int)(Hash) >> 16);
+		flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0)
+			| (mb << 6);
+		flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0)
+			| (mb2 << 6);
+		flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff)
+			| hmask;
+		flush_icache_range((unsigned long) &flush_hash_patch_A[0],
+				   (unsigned long) &flush_hash_patch_B[1]);
 	}
 	else {
 		Hash_end = 0;
@@ -1306,6 +1270,7 @@
 		flush_icache_range((unsigned long) &hash_page[0],
 				   (unsigned long) &hash_page[1]);
 	}
+
 	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
 #endif /* !CONFIG_4xx && !CONFIG_8xx */
@@ -1320,7 +1285,7 @@
 	unsigned long kstart, ksize;
 
 	/*
-	 * Initially, available phyiscal memory is equivalent to all
+	 * Initially, available physical memory is equivalent to all
 	 * physical memory.
 	 */
 
@@ -1356,4 +1321,51 @@
 	if (Hash)
 		mem_pieces_remove(&phys_avail, __pa(Hash), Hash_size, 1);
 #endif /* CONFIG_PPC64BRIDGE */
+}
+
+void flush_page_to_ram(struct page *page)
+{
+	unsigned long vaddr = (unsigned long) kmap(page);
+	__flush_page_to_ram(vaddr);
+	kunmap(page);
+}
+
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+/*
+ * This is called at the end of handling a user page fault, when the
+ * fault has been handled by updating a PTE in the linux page tables.
+ * We use it to preload an HPTE into the hash table corresponding to
+ * the updated linux PTE.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
+		      pte_t pte)
+{
+	struct mm_struct *mm;
+	pmd_t *pmd;
+	pte_t *ptep;
+	static int nopreload;
+
+	if (Hash == 0 || nopreload)
+		return;
+	mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
+	pmd = pmd_offset(pgd_offset(mm, address), address);
+	if (!pmd_none(*pmd)) {
+		ptep = pte_offset(pmd, address);
+		add_hash_page(mm->context, address, ptep);
+	}
+}
+#endif /* !4xx && !8xx */
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ * On machines which use an MMU hash table we avoid changing the
+ * _PAGE_HASHPTE bit.
+ */
+void set_pte(pte_t *ptep, pte_t pte)
+{
+#if _PAGE_HASHPTE != 0
+	pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
+#else
+	*ptep = pte;
+#endif
 }
diff -urN linux-2.4.6-pre8/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds
--- linux-2.4.6-pre8/arch/ppc/vmlinux.lds	Fri Aug  4 11:23:37 2000
+++ linux/arch/ppc/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -39,6 +39,7 @@
   .rodata    :
   {
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
   }
   .kstrtab   : { *(.kstrtab) }
diff -urN linux-2.4.6-pre8/arch/ppc/xmon/Makefile linux/arch/ppc/xmon/Makefile
--- linux-2.4.6-pre8/arch/ppc/xmon/Makefile	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/xmon/Makefile	Mon Dec  3 22:50:37 2001
@@ -1,13 +1,14 @@
-# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+# BK Id: SCCS/s.Makefile 1.6 06/27/01 14:49:58 trini
 #
 # Makefile for xmon
 
 O_TARGET	:= x.o
 
-ifeq ($(CONFIG_8xx),y)
-obj-y		:= start_8xx.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+ifdef CONFIG_8xx
+obj-y		:= start_8xx.o
 else
-obj-y		:= start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+obj-y		:= start.o
 endif
+obj-y		+= xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.6-pre8/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- linux-2.4.6-pre8/arch/ppc/xmon/xmon.c	Mon Dec  3 22:50:27 2001
+++ linux/arch/ppc/xmon/xmon.c	Mon Dec  3 22:50:37 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.xmon.c 1.12 06/09/01 22:18:05 paulus
+ * BK Id: SCCS/s.xmon.c 1.14 06/28/01 15:50:17 paulus
  */
 /*
  * Routines providing a simple monitor for use on the PowerMac.
@@ -1017,7 +1017,8 @@
 		seg_end = (seg << 28) | 0x0ffff000;
 		if (seg_end > hash_end)
 			seg_end = hash_end;
-		dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
+		dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
+				    seg_start, seg_end);
 		seg_start = seg_end + 0x1000;
 	}
 }
diff -urN linux-2.4.6-pre8/arch/s390/vmlinux.lds linux/arch/s390/vmlinux.lds
--- linux-2.4.6-pre8/arch/s390/vmlinux.lds	Tue Feb 13 14:13:44 2001
+++ linux/arch/s390/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -14,7 +14,7 @@
 	*(.gnu.warning)
 	} = 0x0700
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -urN linux-2.4.6-pre8/arch/s390x/vmlinux.lds linux/arch/s390x/vmlinux.lds
--- linux-2.4.6-pre8/arch/s390x/vmlinux.lds	Wed Apr 11 19:02:29 2001
+++ linux/arch/s390x/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -14,7 +14,7 @@
 	*(.gnu.warning)
 	} = 0x0700
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -urN linux-2.4.6-pre8/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S
--- linux-2.4.6-pre8/arch/sh/vmlinux.lds.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/sh/vmlinux.lds.S	Mon Dec  3 22:50:37 2001
@@ -24,7 +24,7 @@
 	*(.gnu.warning)
 	} = 0x0009
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -urN linux-2.4.6-pre8/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds
--- linux-2.4.6-pre8/arch/sparc/vmlinux.lds	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -12,7 +12,7 @@
   } =0
   _etext = .;
   PROVIDE (etext = .);
-  .rodata    : { *(.rodata)  }
+  .rodata    : { *(.rodata) *(.rodata.*) }
   .rodata1   : { *(.rodata1) }
   .data    :
   {
diff -urN linux-2.4.6-pre8/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds
--- linux-2.4.6-pre8/arch/sparc64/vmlinux.lds	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc64/vmlinux.lds	Mon Dec  3 22:50:37 2001
@@ -16,7 +16,7 @@
   } =0
   _etext = .;
   PROVIDE (etext = .);
-  .rodata    : { *(.rodata)  }
+  .rodata    : { *(.rodata) *(.rodata.*) }
   .rodata1   : { *(.rodata1) }
   .data    :
   {
diff -urN linux-2.4.6-pre8/drivers/block/cciss.c linux/drivers/block/cciss.c
--- linux-2.4.6-pre8/drivers/block/cciss.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/block/cciss.c	Mon Dec  3 22:50:37 2001
@@ -63,6 +63,7 @@
                         0x0E11, 0x4080, 0, 0, 0},
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
                         0x0E11, 0x4082, 0, 0, 0},
+	{0,}
 };
 MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
 
diff -urN linux-2.4.6-pre8/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.4.6-pre8/drivers/char/Config.in	Tue Mar  6 19:44:34 2001
+++ linux/drivers/char/Config.in	Mon Dec  3 22:50:37 2001
@@ -186,6 +186,7 @@
    bool '  AMD Irongate support' CONFIG_AGP_AMD
    bool '  Generic SiS support' CONFIG_AGP_SIS
    bool '  ALI chipset support' CONFIG_AGP_ALI
+   bool '  Severworks LE/HE support' CONFIG_AGP_SWORKS
 fi
 
 source drivers/char/drm/Config.in
diff -urN linux-2.4.6-pre8/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h
--- linux-2.4.6-pre8/drivers/char/agp/agp.h	Mon Dec  3 22:50:27 2001
+++ linux/drivers/char/agp/agp.h	Mon Dec  3 22:50:37 2001
@@ -123,11 +123,11 @@
 
 #define OUTREG32(mmap, addr, val)   __raw_writel((val), (mmap)+(addr))
 #define OUTREG16(mmap, addr, val)   __raw_writew((val), (mmap)+(addr))
-#define OUTREG8 (mmap, addr, val)   __raw_writeb((val), (mmap)+(addr))
+#define OUTREG8(mmap, addr, val)   __raw_writeb((val), (mmap)+(addr))
 
 #define INREG32(mmap, addr)         __raw_readl((mmap)+(addr))
 #define INREG16(mmap, addr)         __raw_readw((mmap)+(addr))
-#define INREG8 (mmap, addr)         __raw_readb((mmap)+(addr))
+#define INREG8(mmap, addr)         __raw_readb((mmap)+(addr))
 
 #define CACHE_FLUSH	agp_bridge.cache_flush
 #define A_SIZE_8(x)	((aper_size_info_8 *) x)
@@ -291,5 +291,24 @@
 #define ALI_CACHE_FLUSH_CTRL	0xD0
 #define ALI_CACHE_FLUSH_ADDR_MASK	0xFFFFF000
 #define ALI_CACHE_FLUSH_EN	0x100
+
+/* Serverworks Registers */
+#define SVWRKS_APSIZE 0x10
+#define SVWRKS_SIZE_MASK 0xfe000000
+
+#define SVWRKS_MMBASE 0x14
+#define SVWRKS_CACHING 0x4b
+#define SVWRKS_FEATURE 0x68
+
+/* func 1 registers */
+#define SVWRKS_AGP_ENABLE 0x60
+#define SVWRKS_COMMAND 0x04
+
+/* Memory mapped registers */
+#define SVWRKS_GART_CACHE 0x02
+#define SVWRKS_GATTBASE   0x04
+#define SVWRKS_TLBFLUSH   0x10
+#define SVWRKS_POSTFLUSH  0x14
+#define SVWRKS_DIRFLUSH   0x0c
 
 #endif				/* _AGP_BACKEND_PRIV_H */
diff -urN linux-2.4.6-pre8/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- linux-2.4.6-pre8/drivers/char/agp/agpgart_be.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/char/agp/agpgart_be.c	Mon Dec  3 22:50:37 2001
@@ -2189,6 +2189,621 @@
 
 #endif /* CONFIG_AGP_ALI */
 
+#ifdef CONFIG_AGP_SWORKS
+typedef struct _serverworks_page_map {
+	unsigned long *real;
+	unsigned long *remapped;
+} serverworks_page_map;
+
+static struct _serverworks_private {
+	struct pci_dev *svrwrks_dev;	/* device one */
+	volatile u8 *registers;
+	serverworks_page_map **gatt_pages;
+	int num_tables;
+	serverworks_page_map scratch_dir;
+
+	int gart_addr_ofs;
+	int mm_addr_ofs;
+} serverworks_private;
+
+static int serverworks_create_page_map(serverworks_page_map *page_map)
+{
+	int i;
+
+	page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);
+	if (page_map->real == NULL) {
+		return -ENOMEM;
+	}
+	set_bit(PG_reserved, &virt_to_page(page_map->real)->flags);
+	CACHE_FLUSH();
+	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), 
+					    PAGE_SIZE);
+	if (page_map->remapped == NULL) {
+		clear_bit(PG_reserved, 
+			  &virt_to_page(page_map->real)->flags);
+		free_page((unsigned long) page_map->real);
+		page_map->real = NULL;
+		return -ENOMEM;
+	}
+	CACHE_FLUSH();
+
+	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
+		page_map->remapped[i] = agp_bridge.scratch_page;
+	}
+
+	return 0;
+}
+
+static void serverworks_free_page_map(serverworks_page_map *page_map)
+{
+	iounmap(page_map->remapped);
+	clear_bit(PG_reserved, 
+		  &virt_to_page(page_map->real)->flags);
+	free_page((unsigned long) page_map->real);
+}
+
+static void serverworks_free_gatt_pages(void)
+{
+	int i;
+	serverworks_page_map **tables;
+	serverworks_page_map *entry;
+
+	tables = serverworks_private.gatt_pages;
+	for(i = 0; i < serverworks_private.num_tables; i++) {
+		entry = tables[i];
+		if (entry != NULL) {
+			if (entry->real != NULL) {
+				serverworks_free_page_map(entry);
+			}
+			kfree(entry);
+		}
+	}
+	kfree(tables);
+}
+
+static int serverworks_create_gatt_pages(int nr_tables)
+{
+	serverworks_page_map **tables;
+	serverworks_page_map *entry;
+	int retval = 0;
+	int i;
+
+	tables = kmalloc((nr_tables + 1) * sizeof(serverworks_page_map *), 
+			 GFP_KERNEL);
+	if (tables == NULL) {
+		return -ENOMEM;
+	}
+	memset(tables, 0, sizeof(serverworks_page_map *) * (nr_tables + 1));
+	for (i = 0; i < nr_tables; i++) {
+		entry = kmalloc(sizeof(serverworks_page_map), GFP_KERNEL);
+		if (entry == NULL) {
+			retval = -ENOMEM;
+			break;
+		}
+		memset(entry, 0, sizeof(serverworks_page_map));
+		tables[i] = entry;
+		retval = serverworks_create_page_map(entry);
+		if (retval != 0) break;
+	}
+	serverworks_private.num_tables = nr_tables;
+	serverworks_private.gatt_pages = tables;
+
+	if (retval != 0) serverworks_free_gatt_pages();
+
+	return retval;
+}
+
+#define SVRWRKS_GET_GATT(addr) (serverworks_private.gatt_pages[\
+	GET_PAGE_DIR_IDX(addr)]->remapped)
+
+#ifndef GET_PAGE_DIR_OFF
+#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
+#endif
+
+#ifndef GET_PAGE_DIR_IDX
+#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
+	GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr))
+#endif
+
+#ifndef GET_GATT_OFF
+#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
+#endif
+
+static int serverworks_create_gatt_table(void)
+{
+	aper_size_info_lvl2 *value;
+	serverworks_page_map page_dir;
+	int retval;
+	u32 temp;
+	int i;
+
+	value = A_SIZE_LVL2(agp_bridge.current_size);
+	retval = serverworks_create_page_map(&page_dir);
+	if (retval != 0) {
+		return retval;
+	}
+	retval = serverworks_create_page_map(&serverworks_private.scratch_dir);
+	if (retval != 0) {
+		serverworks_free_page_map(&page_dir);
+		return retval;
+	}
+	/* Create a fake scratch directory */
+	for(i = 0; i < 1024; i++) {
+		serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge.scratch_page;
+		page_dir.remapped[i] =
+			virt_to_bus(serverworks_private.scratch_dir.real);
+		page_dir.remapped[i] |= 0x00000001;
+	}
+
+	retval = serverworks_create_gatt_pages(value->num_entries / 1024);
+	if (retval != 0) {
+		serverworks_free_page_map(&page_dir);
+		return retval;
+	}
+
+	agp_bridge.gatt_table_real = page_dir.real;
+	agp_bridge.gatt_table = page_dir.remapped;
+	agp_bridge.gatt_bus_addr = virt_to_bus(page_dir.real);
+
+	/* Get the address for the gart region.
+	 * This is a bus address even on the alpha, b/c its
+	 * used to program the agp master not the cpu
+	 */
+
+	pci_read_config_dword(agp_bridge.dev,
+			      serverworks_private.gart_addr_ofs,
+			      &temp);
+	agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+	/* Calculate the agp offset */	
+
+	for(i = 0; i < value->num_entries / 1024; i++) {
+		page_dir.remapped[i] =
+			virt_to_bus(serverworks_private.gatt_pages[i]->real);
+		page_dir.remapped[i] |= 0x00000001;
+	}
+
+	return 0;
+}
+
+static int serverworks_free_gatt_table(void)
+{
+	serverworks_page_map page_dir;
+   
+	page_dir.real = agp_bridge.gatt_table_real;
+	page_dir.remapped = agp_bridge.gatt_table;
+
+	serverworks_free_gatt_pages();
+	serverworks_free_page_map(&page_dir);
+	return 0;
+}
+
+static int serverworks_fetch_size(void)
+{
+	int i;
+	u32 temp;
+	u32 temp2;
+	aper_size_info_lvl2 *values;
+
+	values = A_SIZE_LVL2(agp_bridge.aperture_sizes);
+	pci_read_config_dword(agp_bridge.dev,
+			      serverworks_private.gart_addr_ofs,
+			      &temp);
+	pci_write_config_dword(agp_bridge.dev,
+			       serverworks_private.gart_addr_ofs,
+			       0xfe000000);
+	pci_read_config_dword(agp_bridge.dev,
+			      serverworks_private.gart_addr_ofs,
+			      &temp2);
+	pci_write_config_dword(agp_bridge.dev,
+			       serverworks_private.gart_addr_ofs,
+			       temp);
+	temp2 &= SVWRKS_SIZE_MASK;
+
+	for (i = 0; i < agp_bridge.num_aperture_sizes; i++) {
+		if (temp2 == values[i].size_value) {
+			agp_bridge.previous_size =
+			    agp_bridge.current_size = (void *) (values + i);
+
+			agp_bridge.aperture_size_idx = i;
+			return values[i].size;
+		}
+	}
+
+	return 0;
+}
+
+static int serverworks_configure(void)
+{
+	aper_size_info_lvl2 *current_size;
+	u32 temp;
+	u8 enable_reg;
+	u8 cap_ptr;
+	u32 cap_id;
+	u16 cap_reg;
+
+	current_size = A_SIZE_LVL2(agp_bridge.current_size);
+
+	/* Get the memory mapped registers */
+	pci_read_config_dword(agp_bridge.dev,
+			      serverworks_private.mm_addr_ofs,
+			      &temp);
+	temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+	serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096);
+
+	OUTREG8(serverworks_private.registers, SVWRKS_GART_CACHE, 0x0a);
+
+	OUTREG32(serverworks_private.registers, SVWRKS_GATTBASE, 
+		 agp_bridge.gatt_bus_addr);
+
+	cap_reg = INREG16(serverworks_private.registers, SVWRKS_COMMAND);
+	cap_reg &= ~0x0007;
+	cap_reg |= 0x4;
+	OUTREG16(serverworks_private.registers, SVWRKS_COMMAND, cap_reg);
+
+	pci_read_config_byte(serverworks_private.svrwrks_dev,
+			     SVWRKS_AGP_ENABLE, &enable_reg);
+	enable_reg |= 0x1; /* Agp Enable bit */
+	pci_write_config_byte(serverworks_private.svrwrks_dev,
+			      SVWRKS_AGP_ENABLE, enable_reg);
+	agp_bridge.tlb_flush(NULL);
+
+	pci_read_config_byte(serverworks_private.svrwrks_dev, 0x34, &cap_ptr);
+	if (cap_ptr != 0x00) {
+		do {
+			pci_read_config_dword(serverworks_private.svrwrks_dev,
+					      cap_ptr, &cap_id);
+
+			if ((cap_id & 0xff) != 0x02)
+				cap_ptr = (cap_id >> 8) & 0xff;
+		}
+		while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
+	}
+	agp_bridge.capndx = cap_ptr;
+
+	/* Fill in the mode register */
+	pci_read_config_dword(serverworks_private.svrwrks_dev,
+			      agp_bridge.capndx + 4,
+			      &agp_bridge.mode);
+
+	pci_read_config_byte(agp_bridge.dev,
+			     SVWRKS_CACHING,
+			     &enable_reg);
+	enable_reg &= ~0x3;
+	pci_write_config_byte(agp_bridge.dev,
+			      SVWRKS_CACHING,
+			      enable_reg);
+
+	pci_read_config_byte(agp_bridge.dev,
+			     SVWRKS_FEATURE,
+			     &enable_reg);
+	enable_reg |= (1<<6);
+	pci_write_config_byte(agp_bridge.dev,
+			      SVWRKS_FEATURE,
+			      enable_reg);
+
+	return 0;
+}
+
+static void serverworks_cleanup(void)
+{
+	iounmap((void *) serverworks_private.registers);
+}
+
+/*
+ * This routine could be implemented by taking the addresses
+ * written to the GATT, and flushing them individually.  However
+ * currently it just flushes the whole table.  Which is probably
+ * more efficent, since agp_memory blocks can be a large number of
+ * entries.
+ */
+
+static void serverworks_tlbflush(agp_memory * temp)
+{
+	unsigned long end;
+
+	OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01);
+	end = jiffies + 3*HZ;
+	while(INREG8(serverworks_private.registers, 
+		     SVWRKS_POSTFLUSH) == 0x01) {
+		if((signed)(end - jiffies) <= 0) {
+			printk(KERN_ERR "Posted write buffer flush took more"
+			       "then 3 seconds\n");
+		}
+	}
+	OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001);
+	end = jiffies + 3*HZ;
+	while(INREG32(serverworks_private.registers, 
+		     SVWRKS_DIRFLUSH) == 0x00000001) {
+		if((signed)(end - jiffies) <= 0) {
+			printk(KERN_ERR "TLB flush took more"
+			       "then 3 seconds\n");
+		}
+	}
+}
+
+static unsigned long serverworks_mask_memory(unsigned long addr, int type)
+{
+	/* Only type 0 is supported by the serverworks chipsets */
+
+	return addr | agp_bridge.masks[0].mask;
+}
+
+static int serverworks_insert_memory(agp_memory * mem,
+			     off_t pg_start, int type)
+{
+	int i, j, num_entries;
+	unsigned long *cur_gatt;
+	unsigned long addr;
+
+	num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries;
+
+	if (type != 0 || mem->type != 0) {
+		return -EINVAL;
+	}
+	if ((pg_start + mem->page_count) > num_entries) {
+		return -EINVAL;
+	}
+
+	j = pg_start;
+	while (j < (pg_start + mem->page_count)) {
+		addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr;
+		cur_gatt = SVRWRKS_GET_GATT(addr);
+		if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) {
+			return -EBUSY;
+		}
+		j++;
+	}
+
+	if (mem->is_flushed == FALSE) {
+		CACHE_FLUSH();
+		mem->is_flushed = TRUE;
+	}
+
+	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
+		addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr;
+		cur_gatt = SVRWRKS_GET_GATT(addr);
+		cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i];
+	}
+	agp_bridge.tlb_flush(mem);
+	return 0;
+}
+
+static int serverworks_remove_memory(agp_memory * mem, off_t pg_start,
+			     int type)
+{
+	int i;
+	unsigned long *cur_gatt;
+	unsigned long addr;
+
+	if (type != 0 || mem->type != 0) {
+		return -EINVAL;
+	}
+
+	CACHE_FLUSH();
+	agp_bridge.tlb_flush(mem);
+
+	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
+		addr = (i * PAGE_SIZE) + agp_bridge.gart_bus_addr;
+		cur_gatt = SVRWRKS_GET_GATT(addr);
+		cur_gatt[GET_GATT_OFF(addr)] = 
+			(unsigned long) agp_bridge.scratch_page;
+	}
+
+	agp_bridge.tlb_flush(mem);
+	return 0;
+}
+
+static gatt_mask serverworks_masks[] =
+{
+	{0x00000001, 0}
+};
+
+static aper_size_info_lvl2 serverworks_sizes[7] =
+{
+	{2048, 524288, 0x80000000},
+	{1024, 262144, 0xc0000000},
+	{512, 131072, 0xe0000000},
+	{256, 65536, 0xf0000000},
+	{128, 32768, 0xf8000000},
+	{64, 16384, 0xfc000000},
+	{32, 8192, 0xfe000000}
+};
+
+static void serverworks_agp_enable(u32 mode)
+{
+	struct pci_dev *device = NULL;
+	u32 command, scratch, cap_id;
+	u8 cap_ptr;
+
+	pci_read_config_dword(serverworks_private.svrwrks_dev,
+			      agp_bridge.capndx + 4,
+			      &command);
+
+	/*
+	 * PASS1: go throu all devices that claim to be
+	 *        AGP devices and collect their data.
+	 */
+
+	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
+					device)) != NULL) {
+		pci_read_config_dword(device, 0x04, &scratch);
+
+		if (!(scratch & 0x00100000))
+			continue;
+
+		pci_read_config_byte(device, 0x34, &cap_ptr);
+
+		if (cap_ptr != 0x00) {
+			do {
+				pci_read_config_dword(device,
+						      cap_ptr, &cap_id);
+
+				if ((cap_id & 0xff) != 0x02)
+					cap_ptr = (cap_id >> 8) & 0xff;
+			}
+			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
+		}
+		if (cap_ptr != 0x00) {
+			/*
+			 * Ok, here we have a AGP device. Disable impossible 
+			 * settings, and adjust the readqueue to the minimum.
+			 */
+
+			pci_read_config_dword(device, cap_ptr + 4, &scratch);
+
+			/* adjust RQ depth */
+			command =
+			    ((command & ~0xff000000) |
+			     min((mode & 0xff000000),
+				 min((command & 0xff000000),
+				     (scratch & 0xff000000))));
+
+			/* disable SBA if it's not supported */
+			if (!((command & 0x00000200) &&
+			      (scratch & 0x00000200) &&
+			      (mode & 0x00000200)))
+				command &= ~0x00000200;
+
+			/* disable FW */
+			command &= ~0x00000010;
+
+			command &= ~0x00000008;
+
+			if (!((command & 4) &&
+			      (scratch & 4) &&
+			      (mode & 4)))
+				command &= ~0x00000004;
+
+			if (!((command & 2) &&
+			      (scratch & 2) &&
+			      (mode & 2)))
+				command &= ~0x00000002;
+
+			if (!((command & 1) &&
+			      (scratch & 1) &&
+			      (mode & 1)))
+				command &= ~0x00000001;
+		}
+	}
+	/*
+	 * PASS2: Figure out the 4X/2X/1X setting and enable the
+	 *        target (our motherboard chipset).
+	 */
+
+	if (command & 4) {
+		command &= ~3;	/* 4X */
+	}
+	if (command & 2) {
+		command &= ~5;	/* 2X */
+	}
+	if (command & 1) {
+		command &= ~6;	/* 1X */
+	}
+	command |= 0x00000100;
+
+	pci_write_config_dword(serverworks_private.svrwrks_dev,
+			       agp_bridge.capndx + 8,
+			       command);
+
+	/*
+	 * PASS3: Go throu all AGP devices and update the
+	 *        command registers.
+	 */
+
+	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
+					device)) != NULL) {
+		pci_read_config_dword(device, 0x04, &scratch);
+
+		if (!(scratch & 0x00100000))
+			continue;
+
+		pci_read_config_byte(device, 0x34, &cap_ptr);
+
+		if (cap_ptr != 0x00) {
+			do {
+				pci_read_config_dword(device,
+						      cap_ptr, &cap_id);
+
+				if ((cap_id & 0xff) != 0x02)
+					cap_ptr = (cap_id >> 8) & 0xff;
+			}
+			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
+		}
+		if (cap_ptr != 0x00)
+			pci_write_config_dword(device, cap_ptr + 8, command);
+	}
+}
+
+static int __init serverworks_setup (struct pci_dev *pdev)
+{
+	u32 temp;
+	u32 temp2;
+
+	serverworks_private.svrwrks_dev = pdev;
+
+	agp_bridge.masks = serverworks_masks;
+	agp_bridge.num_of_masks = 1;
+	agp_bridge.aperture_sizes = (void *) serverworks_sizes;
+	agp_bridge.size_type = LVL2_APER_SIZE;
+	agp_bridge.num_aperture_sizes = 7;
+	agp_bridge.dev_private_data = (void *) &serverworks_private;
+	agp_bridge.needs_scratch_page = TRUE;
+	agp_bridge.configure = serverworks_configure;
+	agp_bridge.fetch_size = serverworks_fetch_size;
+	agp_bridge.cleanup = serverworks_cleanup;
+	agp_bridge.tlb_flush = serverworks_tlbflush;
+	agp_bridge.mask_memory = serverworks_mask_memory;
+	agp_bridge.agp_enable = serverworks_agp_enable;
+	agp_bridge.cache_flush = global_cache_flush;
+	agp_bridge.create_gatt_table = serverworks_create_gatt_table;
+	agp_bridge.free_gatt_table = serverworks_free_gatt_table;
+	agp_bridge.insert_memory = serverworks_insert_memory;
+	agp_bridge.remove_memory = serverworks_remove_memory;
+	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+
+	pci_read_config_dword(agp_bridge.dev,
+			      SVWRKS_APSIZE,
+			      &temp);
+
+	serverworks_private.gart_addr_ofs = 0x10;
+
+	if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+		pci_read_config_dword(agp_bridge.dev,
+				      SVWRKS_APSIZE + 4,
+				      &temp2);
+		if(temp2 != 0) {
+			printk("Detected 64 bit aperture address, but top "
+			       "bits are not zero.  Disabling agp\n");
+			return -ENODEV;
+		}
+		serverworks_private.mm_addr_ofs = 0x18;
+	} else {
+		serverworks_private.mm_addr_ofs = 0x14;
+	}
+
+	pci_read_config_dword(agp_bridge.dev,
+			      serverworks_private.mm_addr_ofs,
+			      &temp);
+	if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+		pci_read_config_dword(agp_bridge.dev,
+				      serverworks_private.mm_addr_ofs + 4,
+				      &temp2);
+		if(temp2 != 0) {
+			printk("Detected 64 bit MMIO address, but top "
+			       "bits are not zero.  Disabling agp\n");
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_AGP_SWORKS */
+
 
 /* per-chipset initialization data.
  * note -- all chipsets for a single vendor MUST be grouped together
@@ -2585,6 +3200,41 @@
 		}
 	}
 #endif /* CONFIG_AGP_I810 */
+
+#ifdef CONFIG_AGP_SWORKS
+	/* Everything is on func 1 here so we are hardcoding function one */
+	if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS) {
+		struct pci_dev *bridge_dev;
+
+		bridge_dev = pci_find_slot ((unsigned int)dev->bus->number, 
+					    PCI_DEVFN(0, 1));
+		if(bridge_dev == NULL) {
+			printk(KERN_INFO PFX "agpgart: Detected a Serverworks "
+			       "Chipset, but could not find the secondary "
+			       "device.\n");
+			return -ENODEV;
+		}
+
+		switch (dev->device) {
+		case PCI_DEVICE_ID_SERVERWORKS_HE:
+			agp_bridge.type = SVWRKS_HE;
+			return serverworks_setup(bridge_dev);
+
+		case PCI_DEVICE_ID_SERVERWORKS_LE:
+		case 0x0007:
+			agp_bridge.type = SVWRKS_LE;
+			return serverworks_setup(bridge_dev);
+
+		default:
+			if(agp_try_unsupported) {
+				agp_bridge.type = SVWRKS_GENERIC;
+				return serverworks_setup(bridge_dev);
+			}
+			break;
+		}
+	}
+
+#endif	/* CONFIG_AGP_SWORKS */
 
 	/* find capndx */
 	pci_read_config_dword(dev, 0x04, &scratch);
diff -urN linux-2.4.6-pre8/drivers/char/drm/agpsupport.c linux/drivers/char/drm/agpsupport.c
--- linux-2.4.6-pre8/drivers/char/drm/agpsupport.c	Thu Nov 16 14:05:49 2000
+++ linux/drivers/char/drm/agpsupport.c	Mon Dec  3 22:50:37 2001
@@ -284,6 +284,17 @@
 		case AMD_IRONGATE:	head->chipset = "AMD Irongate";  break;
 		case ALI_GENERIC:	head->chipset = "ALi";           break;
 		case ALI_M1541: 	head->chipset = "ALi M1541";     break;
+		case ALI_M1621: 	head->chipset = "ALi M1621";	 break;
+		case ALI_M1631: 	head->chipset = "ALi M1631";	 break;
+		case ALI_M1632: 	head->chipset = "ALi M1632";	 break;
+		case ALI_M1641: 	head->chipset = "ALi M1641";	 break;
+		case ALI_M1647: 	head->chipset = "ALi M1647";	 break;
+		case ALI_M1651: 	head->chipset = "ALi M1651";	 break;
+		case SVWRKS_GENERIC:	head->chipset = "Serverworks Generic";
+			break;
+		case SVWRKS_HE: 	head->chipset = "Serverworks HE";
+		case SVWRKS_LE: 	head->chipset = "Serverworks LE";
+
 		default:		head->chipset = "Unknown";       break;
 		}
 		DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n",
diff -urN linux-2.4.6-pre8/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- linux-2.4.6-pre8/drivers/char/i810-tco.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/char/i810-tco.c	Mon Dec  3 22:50:37 2001
@@ -289,7 +289,7 @@
 			pci_write_config_byte (i810tco_pci, 0xd4, val1);
 			pci_read_config_byte (i810tco_pci, 0xd4, &val1);
 			if (val1 & 0x02) {
-				printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag\n");
+				printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
 				return 0;	/* Cannot reset NO_REBOOT bit */
 			}
 		}
diff -urN linux-2.4.6-pre8/drivers/char/random.c linux/drivers/char/random.c
--- linux-2.4.6-pre8/drivers/char/random.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/char/random.c	Mon Dec  3 22:50:37 2001
@@ -712,8 +712,7 @@
 #if defined (__i386__)
 	if ( test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability) ) {
 		__u32 high;
-		__asm__(".byte 0x0f,0x31"
-			:"=a" (time), "=d" (high));
+		rdtsc(time, high);
 		num ^= high;
 	} else {
 		time = jiffies;
diff -urN linux-2.4.6-pre8/drivers/char/rocket.c linux/drivers/char/rocket.c
--- linux-2.4.6-pre8/drivers/char/rocket.c	Sun Mar 25 18:24:31 2001
+++ linux/drivers/char/rocket.c	Mon Dec  3 22:50:37 2001
@@ -485,14 +485,10 @@
 	unsigned char CtlMask, AiopMask;
 
 #ifdef TIME_STAT
-	unsigned long low=0, high=0, loop_time;
+	unsigned long loop_time;
 	unsigned long long time_stat_tmp=0, time_stat_tmp2=0;
 
-	__asm__(".byte 0x0f,0x31"
-		:"=a" (low), "=d" (high));
-	time_stat_tmp = high;
-	time_stat_tmp <<= 32;
-	time_stat_tmp += low;
+	rdtscll(time_stat_tmp);
 #endif /* TIME_STAT */
 
 	for (ctrl=0; ctrl < max_board; ctrl++) {
@@ -532,11 +528,7 @@
 		mod_timer(&rocket_timer, jiffies + 1);
 	}
 #ifdef TIME_STAT
-	__asm__(".byte 0x0f,0x31"
-		:"=a" (low), "=d" (high));
-	time_stat_tmp2 = high;
-	time_stat_tmp2 <<= 32;
-	time_stat_tmp2 += low;
+	rdtscll(time_stat_tmp2);
 	time_stat_tmp2 -= time_stat_tmp;
 	time_stat += time_stat_tmp2;
 	if (time_counter == 0) 
diff -urN linux-2.4.6-pre8/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.4.6-pre8/drivers/char/tty_io.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/char/tty_io.c	Mon Dec  3 22:50:37 2001
@@ -1872,6 +1872,8 @@
  */
 void do_SAK(struct tty_struct *tty)
 {
+	if (!tty)
+		return;
 	PREPARE_TQUEUE(&tty->SAK_tq, __do_SAK, tty);
 	schedule_task(&tty->SAK_tq);
 }
diff -urN linux-2.4.6-pre8/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- linux-2.4.6-pre8/drivers/isdn/Config.in	Thu Apr 19 22:30:16 2001
+++ linux/drivers/isdn/Config.in	Mon Dec  3 22:50:37 2001
@@ -105,6 +105,10 @@
    fi
 fi
 
+if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+   dep_tristate    'Auvertech TurboPAM support' CONFIG_ISDN_DRV_TPAM $CONFIG_ISDN $CONFIG_PCI
+fi
+
 # CAPI subsystem
 
 tristate           'CAPI2.0 support' CONFIG_ISDN_CAPI
diff -urN linux-2.4.6-pre8/drivers/isdn/Makefile linux/drivers/isdn/Makefile
--- linux-2.4.6-pre8/drivers/isdn/Makefile	Fri Mar  2 11:12:10 2001
+++ linux/drivers/isdn/Makefile	Mon Dec  3 22:50:37 2001
@@ -43,6 +43,7 @@
 subdir-$(CONFIG_ISDN_DRV_ACT2000)	+= act2000
 subdir-$(CONFIG_ISDN_DRV_EICON)		+= eicon
 subdir-$(CONFIG_HYSDN)			+= hysdn
+subdir-$(CONFIG_ISDN_DRV_TPAM)		+= tpam
 
 obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y))
 
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/amd7930.c linux/drivers/isdn/hisax/amd7930.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/amd7930.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/amd7930.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.5.6.1 2001/02/16 16:43:25 kai Exp $
+/* $Id: amd7930.c,v 1.5.6.3 2001/06/11 22:08:37 kai Exp $
  *
  * HiSax ISDN driver - chip specific routines for AMD 7930
  *
@@ -94,7 +94,7 @@
 #include "rawhdlc.h"
 #include <linux/interrupt.h>
 
-static const char *amd7930_revision = "$Revision: 1.5.6.1 $";
+static const char *amd7930_revision = "$Revision: 1.5.6.3 $";
 
 #define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
 #define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
@@ -362,12 +362,8 @@
 	amd7930_bclose(0, bcs->channel);
 
 	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 	}
 	test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
 }
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/avm_pci.c linux/drivers/isdn/hisax/avm_pci.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/avm_pci.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/avm_pci.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: avm_pci.c,v 1.22.6.4 2001/02/16 16:43:25 kai Exp $
+/* $Id: avm_pci.c,v 1.22.6.5 2001/06/09 15:14:16 kai Exp $
  *
  * avm_pci.c    low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
  *              Thanks to AVM, Berlin for informations
@@ -18,7 +18,7 @@
 #include <linux/interrupt.h>
 
 extern const char *CardType[];
-static const char *avm_pci_rev = "$Revision: 1.22.6.4 $";
+static const char *avm_pci_rev = "$Revision: 1.22.6.5 $";
 
 #define  AVM_FRITZ_PCI		1
 #define  AVM_FRITZ_PNP		2
@@ -591,8 +591,8 @@
 			kfree(bcs->blog);
 			bcs->blog = NULL;
 		}
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/callc.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/callc.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: callc.c,v 2.51.6.3 2001/05/26 15:19:57 kai Exp $
+/* $Id: callc.c,v 2.51.6.4 2001/06/09 15:14:17 kai Exp $
  *
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -20,7 +20,7 @@
 #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
 #endif	/* MODULE */
 
-const char *lli_revision = "$Revision: 2.51.6.3 $";
+const char *lli_revision = "$Revision: 2.51.6.4 $";
 
 extern struct IsdnCard cards[];
 extern int nrcards;
@@ -64,19 +64,6 @@
 			if (cards[i].cs->myid == driverid)
 				return (cards[i].cs);
 	return (struct IsdnCardState *) 0;
-}
-
-int
-discard_queue(struct sk_buff_head *q)
-{
-	struct sk_buff *skb;
-	int ret=0;
-
-	while ((skb = skb_dequeue(q))) {
-		dev_kfree_skb(skb);
-		ret++;
-	}
-	return(ret);
 }
 
 static void
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/config.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/config.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 2.57.6.14 2001/05/26 15:19:57 kai Exp $
+/* $Id: config.c,v 2.57.6.15 2001/06/09 15:14:17 kai Exp $
  *
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -837,8 +837,8 @@
 		csta->bcs->BC_Close(csta->bcs);
 	}
 
-	discard_queue(&csta->rq);
-	discard_queue(&csta->sq);
+	skb_queue_purge(&csta->rq);
+	skb_queue_purge(&csta->sq);
 	if (csta->rcvbuf) {
 		kfree(csta->rcvbuf);
 		csta->rcvbuf = NULL;
@@ -1333,7 +1333,7 @@
 static int __init HiSax_init(void)
 {
 	int i, retval;
-#ifdef MODULE
+#ifdef MODULE 
 	int j;
 	int nzproto = 0;
 #endif
@@ -1505,7 +1505,7 @@
 		retval = -EIO;
 		goto out_isdnl1;
 	}
-
+	
 	return 0;
 
  out_isdnl1:
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/elsa_ser.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/elsa_ser.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: elsa_ser.c,v 2.10.6.1 2001/02/16 16:43:26 kai Exp $
+/* $Id: elsa_ser.c,v 2.10.6.2 2001/06/09 15:14:17 kai Exp $
  *
  * stuff for the serial modem on ELSA cards
  *
@@ -439,8 +439,6 @@
 void
 close_elsastate(struct BCState *bcs)
 {
-	struct sk_buff *skb;
-
 	modehscx(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
 		if (bcs->hw.hscx.rcvbuf) {
@@ -448,12 +446,8 @@
 				kfree(bcs->hw.hscx.rcvbuf);
 			bcs->hw.hscx.rcvbuf = NULL;
 		}
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb_any(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb_any(skb);
-		}
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/hfc_2bds0.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/hfc_2bds0.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.15.6.1 2001/02/16 16:43:26 kai Exp $
+/* $Id: hfc_2bds0.c,v 1.15.6.2 2001/06/09 15:14:17 kai Exp $
  *
  *  specific routines for CCD's HFC 2BDS0
  *
@@ -568,8 +568,8 @@
 {
 	mode_2bs0(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/hfc_2bs0.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/hfc_2bs0.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bs0.c,v 1.17.6.1 2001/02/16 16:43:27 kai Exp $
+/* $Id: hfc_2bs0.c,v 1.17.6.2 2001/06/09 15:14:17 kai Exp $
  *
  *  specific routines for CCD's HFC 2BS0
  *
@@ -532,8 +532,8 @@
 {
 	mode_hfc(bcs, 0, bcs->channel);
 	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/hfc_pci.c	Wed Apr 18 11:49:13 2001
+++ linux/drivers/isdn/hisax/hfc_pci.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.34.6.5 2001/04/08 19:32:26 kai Exp $
+/* $Id: hfc_pci.c,v 1.34.6.6 2001/06/09 15:14:17 kai Exp $
 
  * hfc_pci.c     low level driver for CCD´s hfc-pci based cards
  *
@@ -35,7 +35,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcpci_revision = "$Revision: 1.34.6.5 $";
+static const char *hfcpci_revision = "$Revision: 1.34.6.6 $";
 
 /* table entry in the PCI devices list */
 typedef struct {
@@ -1497,8 +1497,8 @@
 {
 	mode_hfcpci(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/hfc_sx.c linux/drivers/isdn/hisax/hfc_sx.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/hfc_sx.c	Tue Nov 28 21:43:13 2000
+++ linux/drivers/isdn/hisax/hfc_sx.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: hfc_sx.c,v 1.9 2000/11/24 17:05:37 kai Exp $
+/* $Id: hfc_sx.c,v 1.9.6.1 2001/06/09 15:14:17 kai Exp $
 
  * hfc_sx.c     low level driver for CCD´s hfc-s+/sp based cards
  *
@@ -32,7 +32,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcsx_revision = "$Revision: 1.9 $";
+static const char *hfcsx_revision = "$Revision: 1.9.6.1 $";
 
 /***************************************/
 /* IRQ-table for CCDs demo board       */
@@ -1288,8 +1288,8 @@
 {
 	mode_hfcsx(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- linux-2.4.6-pre8/drivers/isdn/hisax/hisax.h	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/hisax.h	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: hisax.h,v 2.52.6.5 2001/05/26 15:19:57 kai Exp $
+/* $Id: hisax.h,v 2.52.6.6 2001/06/09 15:14:17 kai Exp $
  *
  *   Basic declarations, defines and prototypes
  *
@@ -1325,7 +1325,6 @@
 void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
 void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
 void iecpy(u_char * dest, u_char * iestart, int ieoffset);
-int discard_queue(struct sk_buff_head *q);
 #ifdef ISDN_CHIP_ISAC
 void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
 #endif	/* ISDN_CHIP_ISAC */
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/hscx.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/hscx.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: hscx.c,v 1.21.6.1 2001/02/16 16:43:27 kai Exp $
+/* $Id: hscx.c,v 1.21.6.2 2001/06/09 15:14:17 kai Exp $
  *
  * hscx.c   HSCX specific routines
  *
@@ -166,8 +166,8 @@
 			kfree(bcs->blog);
 			bcs->blog = NULL;
 		}
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/icc.c linux/drivers/isdn/hisax/icc.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/icc.c	Mon Mar 26 15:38:19 2001
+++ linux/drivers/isdn/hisax/icc.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-// $Id: icc.c,v 1.5.6.2 2001/03/13 16:17:08 kai Exp $
+// $Id: icc.c,v 1.5.6.3 2001/06/09 15:14:17 kai Exp $
 //-----------------------------------------------------------------------------
 //
 // ICC specific routines
@@ -551,8 +551,8 @@
 			}
 			break;
 		case (HW_DEACTIVATE | RESPONSE):
-			discard_queue(&cs->rq);
-			discard_queue(&cs->sq);
+			skb_queue_purge(&cs->rq);
+			skb_queue_purge(&cs->sq);
 			if (cs->tx_skb) {
 				dev_kfree_skb_any(cs->tx_skb);
 				cs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/isac.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/hisax/isac.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isac.c,v 1.28.6.1 2001/02/16 16:43:27 kai Exp $
+/* $Id: isac.c,v 1.28.6.2 2001/06/09 15:14:17 kai Exp $
  *
  * isac.c   ISAC specific routines
  *
@@ -549,8 +549,8 @@
 			}
 			break;
 		case (HW_DEACTIVATE | RESPONSE):
-			discard_queue(&cs->rq);
-			discard_queue(&cs->sq);
+			skb_queue_purge(&cs->rq);
+			skb_queue_purge(&cs->sq);
 			if (cs->tx_skb) {
 				dev_kfree_skb_any(cs->tx_skb);
 				cs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/isar.c	Wed Apr 18 11:49:14 2001
+++ linux/drivers/isdn/hisax/isar.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.17.6.2 2001/04/08 17:51:42 kai Exp $
+/* $Id: isar.c,v 1.17.6.3 2001/06/09 15:14:17 kai Exp $
  *
  * isar.c   ISAR (Siemens PSB 7110) specific routines
  *
@@ -1650,8 +1650,8 @@
 			kfree(bcs->hw.isar.rcvbuf);
 			bcs->hw.isar.rcvbuf = NULL;
 		}
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/isdnl1.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/isdnl1.c	Mon Dec  3 22:50:37 2001
@@ -736,7 +736,7 @@
 
 #define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
 
-int __init
+int __init 
 Isdnl1New(void)
 {
 	int retval;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/isdnl2.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/isdnl2.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnl2.c,v 2.25.6.2 2001/05/26 15:19:57 kai Exp $
+/* $Id: isdnl2.c,v 2.25.6.3 2001/06/09 15:14:17 kai Exp $
  *
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -16,7 +16,7 @@
 #include "hisax.h"
 #include "isdnl2.h"
 
-const char *l2_revision = "$Revision: 2.25.6.2 $";
+const char *l2_revision = "$Revision: 2.25.6.3 $";
 
 static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
 
@@ -649,7 +649,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.i_queue);
 	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
 	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
 }
@@ -659,7 +659,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.i_queue);
 	establishlink(fi);
 	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
 }
@@ -685,7 +685,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.i_queue);
 	freewin(st);
 	FsmChangeState(fi, ST_L2_6);
 	st->l2.rc = 0;
@@ -745,7 +745,7 @@
 	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
 
 	if (st->l2.vs != st->l2.va) {
-		discard_queue(&st->l2.i_queue);
+		skb_queue_purge(&st->l2.i_queue);
 		est = 1;
 	}
 
@@ -778,7 +778,7 @@
 
 	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
 
-	discard_queue(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.i_queue);
 	freewin(st);
 	lapb_dl_release_l2l3(st, INDICATION);
 }
@@ -802,7 +802,7 @@
 	if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
 		pr = DL_ESTABLISH | CONFIRM;
 	} else if (st->l2.vs != st->l2.va) {
-		discard_queue(&st->l2.i_queue);
+		skb_queue_purge(&st->l2.i_queue);
 		pr = DL_ESTABLISH | INDICATION;
 	}
 
@@ -860,7 +860,7 @@
 	if (get_PollFlagFree(st, skb)) {
 		stop_t200(st, 7);
 	 	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
-			discard_queue(&st->l2.i_queue);
+			skb_queue_purge(&st->l2.i_queue);
 		if (test_bit(FLG_LAPB, &st->l2.flag))
 			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
 		st5_dl_release_l2l3(st);
@@ -1156,7 +1156,7 @@
 	} else if (st->l2.rc == st->l2.N200) {
 		FsmChangeState(fi, ST_L2_4);
 		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
-		discard_queue(&st->l2.i_queue);
+		skb_queue_purge(&st->l2.i_queue);
 		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
 		if (test_bit(FLG_LAPB, &st->l2.flag))
 			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
@@ -1388,7 +1388,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	st->l2.tei = -1;
 	FsmChangeState(fi, ST_L2_1);
 }
@@ -1398,7 +1398,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	st->l2.tei = -1;
 	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 	FsmChangeState(fi, ST_L2_1);
@@ -1409,8 +1409,8 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	freewin(st);
 	st->l2.tei = -1;
 	stop_t200(st, 17);
@@ -1423,7 +1423,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	st->l2.tei = -1;
 	stop_t200(st, 18);
 	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
@@ -1435,8 +1435,8 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	freewin(st);
 	st->l2.tei = -1;
 	stop_t200(st, 17);
@@ -1450,8 +1450,8 @@
 {
 	struct PStack *st = fi->userdata;
 	
-	discard_queue(&st->l2.i_queue);
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
 		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 }
@@ -1461,8 +1461,8 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	freewin(st);
 	stop_t200(st, 19);
 	st5_dl_release_l2l3(st);
@@ -1474,7 +1474,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	stop_t200(st, 20);
 	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
 	FsmChangeState(fi, ST_L2_4);
@@ -1485,8 +1485,8 @@
 {
 	struct PStack *st = fi->userdata;
 
-	discard_queue(&st->l2.i_queue);
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	freewin(st);
 	stop_t200(st, 19);
 	FsmDelTimer(&st->l2.t203, 19);
@@ -1761,8 +1761,8 @@
 {
 	FsmDelTimer(&st->l2.t200, 21);
 	FsmDelTimer(&st->l2.t203, 16);
-	discard_queue(&st->l2.i_queue);
-	discard_queue(&st->l2.ui_queue);
+	skb_queue_purge(&st->l2.i_queue);
+	skb_queue_purge(&st->l2.ui_queue);
 	ReleaseWin(&st->l2);
 }
 
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/isdnl3.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/isdnl3.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnl3.c,v 2.17.6.3 2001/05/26 15:19:57 kai Exp $
+/* $Id: isdnl3.c,v 2.17.6.4 2001/06/09 15:14:17 kai Exp $
  *
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -18,7 +18,7 @@
 #include "isdnl3.h"
 #include <linux/config.h>
 
-const char *l3_revision = "$Revision: 2.17.6.3 $";
+const char *l3_revision = "$Revision: 2.17.6.4 $";
 
 static struct Fsm l3fsm;
 
@@ -404,7 +404,7 @@
 		st->l3.global = NULL;
 	}
 	FsmDelTimer(&st->l3.l3m_timer, 54);
-	discard_queue(&st->l3.squeue);
+	skb_queue_purge(&st->l3.squeue);
 }
 
 void
@@ -520,7 +520,7 @@
 
 	FsmDelTimer(&st->l3.l3m_timer, 52);
 	FsmChangeState(fi, ST_L3_LC_REL);
-	discard_queue(&st->l3.squeue);
+	skb_queue_purge(&st->l3.squeue);
 	l3ml3p(st, DL_RELEASE | INDICATION);
 }
 
@@ -530,7 +530,7 @@
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L3_LC_REL);
-	discard_queue(&st->l3.squeue);
+	skb_queue_purge(&st->l3.squeue);
 	l3ml3p(st, DL_RELEASE | CONFIRM);
 }
 
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/jade.c linux/drivers/isdn/hisax/jade.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/jade.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/hisax/jade.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: jade.c,v 1.6.6.1 2001/02/16 16:43:27 kai Exp $
+/* $Id: jade.c,v 1.6.6.2 2001/06/09 15:14:18 kai Exp $
  *
  * jade.c   JADE stuff (derived from original hscx.c)
  *
@@ -209,8 +209,8 @@
 		kfree(bcs->blog);
 		bcs->blog = NULL;
 	}
-	discard_queue(&bcs->rqueue);
-	discard_queue(&bcs->squeue);
+	skb_queue_purge(&bcs->rqueue);
+	skb_queue_purge(&bcs->squeue);
 	if (bcs->tx_skb) {
 		dev_kfree_skb_any(bcs->tx_skb);
 		bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/md linux/drivers/isdn/hisax/md
--- linux-2.4.6-pre8/drivers/isdn/hisax/md	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/md	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,12 @@
+6f9433a8b696076562562d090e3c420f  isac.c
+13c3eed869f5139f44c563e3a8fea1f5  isdnl1.c
+addcff863b0ff1e366c0f2ae9fa6e81e  isdnl2.c
+7076deb94a363945c21ea27aca4a720a  isdnl3.c
+51c603829b6cc4f8421f744ad657ceff  tei.c
+669050ab5079f02887ed0239d86e5474  callc.c
+e592db58630c1f1029cc064110108156  cert.c
+fadeb3b85bb23bc1ac48470c0848d6fa  l3dss1.c
+cf7dec9fac6283716904d26b99188476  l3_1tr6.c
+65d9e5471bc129624f858ebcf0743525  elsa.c
+b4cf8a4dceed9ea6dcba65a85b4eecc7  diva.c
+99e67bea8f6945fa0d4e0aded5bf0fa0  sedlbauer.c
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc
--- linux-2.4.6-pre8/drivers/isdn/hisax/md5sums.asc	Mon Dec  3 22:50:27 2001
+++ linux/drivers/isdn/hisax/md5sums.asc	Mon Dec  3 22:50:37 2001
@@ -7,12 +7,12 @@
 # cards in the moment.
 # Read ../../../Documentation/isdn/HiSax.cert for more informations.
 # 
-9663cc9f4374c361197d394f6d27c459  isac.c
+6f9433a8b696076562562d090e3c420f  isac.c
 13c3eed869f5139f44c563e3a8fea1f5  isdnl1.c
-64dcc220ae42fe9e4bbc664c9525bd0a  isdnl2.c
-700aa997e04f5e7e0d32f0d60c8e7fa9  isdnl3.c
+addcff863b0ff1e366c0f2ae9fa6e81e  isdnl2.c
+7076deb94a363945c21ea27aca4a720a  isdnl3.c
 51c603829b6cc4f8421f744ad657ceff  tei.c
-144d646162d83bb5b99095917d131865  callc.c
+669050ab5079f02887ed0239d86e5474  callc.c
 e592db58630c1f1029cc064110108156  cert.c
 fadeb3b85bb23bc1ac48470c0848d6fa  l3dss1.c
 cf7dec9fac6283716904d26b99188476  l3_1tr6.c
@@ -21,13 +21,3 @@
 99e67bea8f6945fa0d4e0aded5bf0fa0  sedlbauer.c
 # end of md5sums
 
------BEGIN PGP SIGNATURE-----
-Version: 2.6.3in
-Charset: noconv
-
-iQCVAwUBOxFX6zpxHvX/mS9tAQE+bgP7B5FFxU+RQ3l8fBvZoMbu/Mslo9+XgtLg
-gK8Xwnp4Ij909fa2i6i2bvFPkzHULMqp2PRdtxBTn9CdhwSZyRByhCvZvDHitsv2
-ZEIRn2Bd1jhhgWcr5KCbjKUaIwcFY7RdSQJw/yCyGsodg1fLI+g+QrnMkICI/RTa
-AtYLLWgwEqo=
-=3IMV
------END PGP SIGNATURE-----
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/netjet.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/hisax/netjet.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: netjet.c,v 1.24.6.4 2001/02/16 16:43:28 kai Exp $
+/* $Id: netjet.c,v 1.24.6.5 2001/06/09 15:14:18 kai Exp $
  *
  * netjet.c     low level stuff for Traverse Technologie NETJet ISDN cards
  *
@@ -22,7 +22,7 @@
 #include <asm/io.h>
 #include "netjet.h"
 
-const char *NETjet_revision = "$Revision: 1.24.6.4 $";
+const char *NETjet_revision = "$Revision: 1.24.6.5 $";
 
 /* Interface functions */
 
@@ -880,8 +880,8 @@
 			kfree(bcs->hw.tiger.sendbuf);
 			bcs->hw.tiger.sendbuf = NULL;
 		}
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/hisax/w6692.c linux/drivers/isdn/hisax/w6692.c
--- linux-2.4.6-pre8/drivers/isdn/hisax/w6692.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/hisax/w6692.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: w6692.c,v 1.12.6.4 2001/02/16 16:43:29 kai Exp $
+/* $Id: w6692.c,v 1.12.6.5 2001/06/09 15:14:18 kai Exp $
  *
  * w6692.c   Winbond W6692 specific routines
  *
@@ -35,7 +35,7 @@
 
 extern const char *CardType[];
 
-const char *w6692_revision = "$Revision: 1.12.6.4 $";
+const char *w6692_revision = "$Revision: 1.12.6.5 $";
 
 #define DBUSY_TIMER_VALUE 80
 
@@ -641,8 +641,8 @@
 			/* !!! not implemented yet */
 			break;
 		case (HW_DEACTIVATE | RESPONSE):
-			discard_queue(&cs->rq);
-			discard_queue(&cs->sq);
+			skb_queue_purge(&cs->rq);
+			skb_queue_purge(&cs->sq);
 			if (cs->tx_skb) {
 				dev_kfree_skb_any(cs->tx_skb);
 				cs->tx_skb = NULL;
@@ -805,8 +805,8 @@
 			kfree(bcs->blog);
 			bcs->blog = NULL;
 		}
-		discard_queue(&bcs->rqueue);
-		discard_queue(&bcs->squeue);
+		skb_queue_purge(&bcs->rqueue);
+		skb_queue_purge(&bcs->squeue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
diff -urN linux-2.4.6-pre8/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- linux-2.4.6-pre8/drivers/isdn/icn/icn.c	Thu Apr 19 22:30:23 2001
+++ linux/drivers/isdn/icn/icn.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.65.6.4 2001/04/20 02:42:01 keil Exp $
+/* $Id: icn.c,v 1.65.6.5 2001/06/09 15:14:19 kai Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -34,7 +34,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.65.6.4 $";
+*revision = "$Revision: 1.65.6.5 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -51,8 +51,7 @@
 	struct sk_buff *skb;
 	unsigned long flags;
 
-	while ((skb = skb_dequeue(queue)))
-		dev_kfree_skb(skb);
+	skb_queue_purge(queue);
 	save_flags(flags);
 	cli();
 	card->xlen[channel] = 0;
diff -urN linux-2.4.6-pre8/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.4.6-pre8/drivers/isdn/isdn_common.c	Sat May 19 17:54:14 2001
+++ linux/drivers/isdn/isdn_common.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.114.6.11 2001/04/20 02:41:58 keil Exp $
+/* $Id: isdn_common.c,v 1.114.6.12 2001/06/09 15:14:15 kai Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -51,7 +51,7 @@
 
 isdn_dev *dev;
 
-static char *isdn_revision = "$Revision: 1.114.6.11 $";
+static char *isdn_revision = "$Revision: 1.114.6.12 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -233,20 +233,6 @@
 	return isdn_wildmat( TmpMsn1, TmpMsn2 );
 }
 
-static void
-isdn_free_queue(struct sk_buff_head *queue)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	if (skb_queue_len(queue))
-		while ((skb = skb_dequeue(queue)))
-			dev_kfree_skb(skb);
-	restore_flags(flags);
-}
-
 int
 isdn_dc2minor(int di, int ch)
 {
@@ -739,7 +725,7 @@
 			kfree(dev->drv[di]->rcverr);
 			kfree(dev->drv[di]->rcvcount);
 			for (i = 0; i < dev->drv[di]->channels; i++)
-				isdn_free_queue(&dev->drv[di]->rpqueue[i]);
+				skb_queue_purge(&dev->drv[di]->rpqueue[i]);
 			kfree(dev->drv[di]->rpqueue);
 			kfree(dev->drv[di]->rcv_waitq);
 			kfree(dev->drv[di]);
@@ -1873,7 +1859,7 @@
 			dev->v110[i] = NULL;
 // 20.10.99 JIM, try to reinitialize v110 !
 			isdn_info_update();
-			isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
+			skb_queue_purge(&dev->drv[di]->rpqueue[ch]);
 		}
 	restore_flags(flags);
 }
@@ -2036,7 +2022,7 @@
 
 	if ((adding) && (d->rpqueue)) {
 		for (j = 0; j < d->channels; j++)
-			isdn_free_queue(&d->rpqueue[j]);
+			skb_queue_purge(&d->rpqueue[j]);
 		kfree(d->rpqueue);
 	}
 	if (!(d->rpqueue =
diff -urN linux-2.4.6-pre8/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- linux-2.4.6-pre8/drivers/isdn/isdn_net.c	Sat May 19 17:54:14 2001
+++ linux/drivers/isdn/isdn_net.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.140.6.4 2001/04/20 02:41:58 keil Exp $
+/* $Id: isdn_net.c,v 1.140.6.6 2001/06/11 22:08:37 kai 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.140.6.4 $";
+char *isdn_net_revision = "$Revision: 1.140.6.6 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -301,13 +301,11 @@
 isdn_net_unbind_channel(isdn_net_local * lp)
 {
 	ulong flags;
-	struct sk_buff *skb;
 
 	save_flags(flags);
 	cli();
-	while ((skb = skb_dequeue(&lp->super_tx_queue))) {
-		kfree_skb(skb);
-	}
+	skb_queue_purge(&lp->super_tx_queue);
+
 	if (!lp->master) {	/* reset only master device */
 		/* Moral equivalent of dev_purge_queues():
 		   BEWARE! This chunk of code cannot be called from hardware
diff -urN linux-2.4.6-pre8/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- linux-2.4.6-pre8/drivers/isdn/isdn_tty.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/isdn_tty.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.94.6.1 2001/02/16 16:43:22 kai Exp $
+/* $Id: isdn_tty.c,v 1.94.6.2 2001/06/09 15:14:15 kai Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -66,7 +66,7 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.94.6.1 $";
+char *isdn_tty_revision = "$Revision: 1.94.6.2 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -307,18 +307,13 @@
 void
 isdn_tty_cleanup_xmit(modem_info * info)
 {
-	struct sk_buff *skb;
 	unsigned long flags;
 
 	save_flags(flags);
 	cli();
-	if (skb_queue_len(&info->xmit_queue))
-		while ((skb = skb_dequeue(&info->xmit_queue)))
-			kfree_skb(skb);
-#ifdef CONFIG_ISDN_AUDIO
-	if (skb_queue_len(&info->dtmf_queue))
-		while ((skb = skb_dequeue(&info->dtmf_queue)))
-			kfree_skb(skb);
+	skb_queue_purge(&info->xmit_queue);
+#ifdef CONFIG_ISDN_AUDIO
+	skb_queue_purge(&info->dtmf_queue);
 #endif
 	restore_flags(flags);
 }
diff -urN linux-2.4.6-pre8/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c
--- linux-2.4.6-pre8/drivers/isdn/isdnloop/isdnloop.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/isdnloop/isdnloop.c	Mon Dec  3 22:50:37 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.11.6.2 2001/02/16 16:43:32 kai Exp $
+/* $Id: isdnloop.c,v 1.11.6.3 2001/06/09 15:14:19 kai Exp $
 
  * ISDN low-level module implementing a dummy loop driver.
  *
@@ -26,7 +26,7 @@
 #include "isdnloop.h"
 
 static char
-*revision = "$Revision: 1.11.6.2 $";
+*revision = "$Revision: 1.11.6.3 $";
 
 static int isdnloop_addcard(char *);
 
@@ -41,10 +41,8 @@
 isdnloop_free_queue(isdnloop_card * card, int channel)
 {
 	struct sk_buff_head *queue = &card->bqueue[channel];
-	struct sk_buff *skb;
 
-	while ((skb = skb_dequeue(queue)))
-		dev_kfree_skb(skb);
+	skb_queue_purge(queue);
 	card->sndcount[channel] = 0;
 }
 
@@ -1574,11 +1572,8 @@
 	}
 	card = cards;
 	while (card) {
-		struct sk_buff *skb;
-
 		last = card;
-		while ((skb = skb_dequeue(&card->dqueue)))
-			dev_kfree_skb(skb);
+		skb_queue_purge(&card->dqueue);
 		card = card->next;
 		kfree(last);
 	}
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/Makefile linux/drivers/isdn/tpam/Makefile
--- linux-2.4.6-pre8/drivers/isdn/tpam/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/Makefile	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,21 @@
+# Makefile for the TurboPAM ISDN device driver
+
+# The target object and module list name.
+
+O_TARGET	:= vmlinux-obj.o
+
+# Multipart objects.
+
+list-multi	:= tpam.o
+tpam-objs	:= tpam_main.o tpam_nco.o tpam_memory.o tpam_commands.o tpam_queues.o tpam_hdlc.o tpam_crcpc.o
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_ISDN_DRV_TPAM)	+= tpam.o
+
+include $(TOPDIR)/Rules.make
+
+# Link rules for multi-part drivers.
+
+tpam.o: $(tpam-objs)
+	$(LD) -r -o $@ $(tpam-objs)
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam.h linux/drivers/isdn/tpam/tpam.h
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam.h	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,246 @@
+/* $Id: tpam.h,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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.
+ *
+ */
+
+#ifndef _TPAM_PRIV_H_
+#define _TPAM_PRIV_H_
+
+#include <linux/module.h>
+#include <linux/isdnif.h>
+#include <linux/init.h>
+
+/* Maximum number of channels for this board */
+#define TPAM_NBCHANNEL		30
+/* Maximum size of data */
+#define TPAM_MAXBUFSIZE		2032
+/* Size of a page of board memory */
+#define TPAM_PAGE_SIZE		0x003ffffc	/* 4 MB */
+/* Magic number present if the board was successfully started */
+#define TPAM_MAGICNUMBER	0x2a343242
+
+/* Registers in the PCI BAR0 */
+#define TPAM_PAGE_REGISTER	0x00400000	/* Select page */
+#define TPAM_DSPINT_REGISTER	0x00400004	/* Interrupt board */
+#define TPAM_RESETPAM_REGISTER	0x00400008	/* Reset board */
+#define TPAM_HINTACK_REGISTER	0x0040000c	/* Ack interrupt */
+#define TPAM_HPIC_REGISTER	0x00400014	/* Board ready */
+
+/* Registers in the board memory */
+#define TPAM_MAGICNUMBER_REGISTER	0x80008000 /* Magic number */
+#define TPAM_EXID_REGISTER		0x80008004 /* EXID - not used */
+#define TPAM_UPLOADPTR_REGISTER		0x80008008 /* Upload data ptr */
+#define TPAM_DOWNLOADPTR_REGISTER	0x8000800c /* Download data ptr */
+#define TPAM_ACKUPLOAD_REGISTER		0x80008010 /* Ack upload */
+#define TPAM_ACKDOWNLOAD_REGISTER	0x80008014 /* Ack download */
+#define TPAM_INTERRUPTACK_REGISTER	0x80008018 /* Ack interrupt */
+
+/* Reserved areas in the board memory */
+#define	TPAM_RESERVEDAREA1_START	0x00000000
+#define TPAM_RESERVEDAREA1_END		0x003FFFFF
+#define TPAM_RESERVEDAREA2_START	0x01C00000
+#define TPAM_RESERVEDAREA2_END		0x01FFFFFF
+#define TPAM_RESERVEDAREA3_START	0x04000000
+#define TPAM_RESERVEDAREA3_END		0x7FFFFFFF
+#define TPAM_RESERVEDAREA4_START	0x80010000
+#define TPAM_RESERVEDAREA4_END		0xFFFFFFFF
+
+/* NCO ID invalid */
+#define TPAM_NCOID_INVALID	0xffff
+/* channel number invalid */
+#define TPAM_CHANNEL_INVALID	0xffff
+
+/* Channel structure */
+typedef struct tpam_channel {
+	int num;			/* channel number */
+	struct tpam_card *card;		/* channel's card */
+	u32 ncoid;			/* ncoid */
+	u8  hdlc;			/* hdlc mode (set by user level) */
+	u8  realhdlc;			/* hdlc mode (negociated with peer) */
+	u32 hdlcshift;			/* hdlc shift */
+	u8  readytoreceive;		/* channel ready to receive data */
+	struct sk_buff_head sendq;	/* Send queue */
+} tpam_channel;
+
+/* Card structure */
+typedef struct tpam_card {
+	struct tpam_card *next;		/* next card in list */
+	unsigned int irq;		/* IRQ used by this board */
+	unsigned long bar0;		/* ioremapped bar0 */
+	int id;				/* id of the board */
+	isdn_if interface;		/* isdn link-level pointer */
+	int channels_used;		/* number of channels actually used */
+	int channels_tested;		/* number of channels being tested */
+	u8 loopmode;			/* board in looptest mode */
+	tpam_channel channels[TPAM_NBCHANNEL];/* channels tab */
+	int running;			/* card is running */
+	int busy;			/* waiting for ack from card */
+	int roundrobin;			/* round robin between channels */
+	struct sk_buff_head sendq;	/* send queue */
+	struct sk_buff_head recvq;	/* receive queue */
+	struct tq_struct send_tq;	/* send task queue */
+	struct tq_struct recv_tq;	/* receive task queue */
+	spinlock_t lock;		/* lock for the card */
+} tpam_card;
+
+/* Timeout waiting for signature to become available */
+#define SIGNATURE_TIMEOUT	(5*HZ)
+/* Timeout waiting for receiving all the ACreateNCOCnf */
+#define NCOCREATE_TIMEOUT	(30*HZ)
+
+/* Maximum size of the TLV block */
+#define MPB_MAXIMUMBLOCKTLVSIZE	 128
+/* Maximum size of the data block */
+#define MPB_MAXIMUMDATASIZE	4904
+/* Maximum size of a phone number */
+#define PHONE_MAXIMUMSIZE	  32
+
+/* Header for a sk_buff structure */
+typedef struct skb_header {
+	u16 size;		/* size of pci_mpb block + size of tlv block */
+	u16 data_size;		/* size of the data block */
+	u16 ack;		/* packet needs to send ack upon send */
+	u16 ack_size;		/* size of data to be acknowledged upon send */
+} skb_header;
+
+/* PCI message header structure */
+typedef struct pci_mpb {
+	u16 exID;			/* exID - not used */
+	u16 flags;			/* flags - not used */
+	u32 errorCode;			/* errorCode - not used */
+	u16 messageID;			/* message ID - one of ID_XXX */
+	u16 maximumBlockTLVSize;	/* MPB_MAXIMUMBLOCKTLVSIZE */
+	u16 actualBlockTLVSize;		/* size of the tlv block */
+	u16 maximumDataSize;		/* MPB_MAXIMUMDATASIZE */
+	u16 actualDataSize;		/* size of the data block */
+	u16 dummy;			/* padding */
+} pci_mpb;
+
+/* Types of PCI messages */
+#define ID_ACreateNCOReq	101
+#define ID_ACreateNCOCnf	102
+#define ID_ADestroyNCOReq	103
+#define ID_ADestroyNCOCnf	104
+#define ID_CConnectReq		203
+#define ID_CConnectInd		204
+#define ID_CConnectRsp		205
+#define ID_CConnectCnf		206
+#define ID_CDisconnectReq	207
+#define ID_CDisconnectInd	208
+#define ID_CDisconnectRsp	209
+#define ID_CDisconnectCnf	210
+#define ID_U3DataReq		307
+#define ID_U3DataInd		308
+#define ID_U3ReadyToReceiveInd	318
+
+/* Parameters for the PCI message TLV block */
+#define PAR_BearerCap		3
+#define PAR_CalledNumber	7
+#define PAR_CallingNumber	11
+#define PAR_CauseToPUF		15
+#define PAR_Cdirection		16
+#define PAR_CompletionStatus	19
+#define PAR_Facility		30
+#define PAR_HLC			34
+#define PAR_NCOID		49
+#define PAR_NCOType		50
+#define PAR_ReadyFlag		55
+#define PAR_U3Protocol		62
+#define PAR_Udirection		64
+
+/* Delayed statcallb structure */
+typedef struct tpam_statcallb_data {
+	tpam_card *card;		/* card issuing the statcallb */
+	struct timer_list *timer;	/* timer launching the statcallb */
+	isdn_ctrl ctrl;			/* isdn command */
+} tpam_statcallb_data;
+
+/* Function prototypes from tpam_main.c */
+extern tpam_card *tpam_findcard(int);
+extern u32 tpam_findchannel(tpam_card *, u32);
+
+/* Function prototypes from tpam_memory.c */
+extern void copy_to_pam_dword(tpam_card *, const void *, u32);
+extern void copy_to_pam(tpam_card *, void *, const void *, u32);
+extern u32 copy_from_pam_dword(tpam_card *, const void *);
+extern void copy_from_pam(tpam_card *, void *, const void *, u32);
+extern int copy_from_pam_to_user(tpam_card *, void *, const void *, u32);
+extern int copy_from_user_to_pam(tpam_card *, void *, const void *, u32);
+extern int tpam_verify_area(u32, u32);
+
+/* Function prototypes from tpam_nco.c */
+extern struct sk_buff *build_ACreateNCOReq(const u8 *);
+extern struct sk_buff *build_ADestroyNCOReq(u32);
+extern struct sk_buff *build_CConnectReq(u32, const u8 *, u8);
+extern struct sk_buff *build_CConnectRsp(u32);
+extern struct sk_buff *build_CDisconnectReq(u32);
+extern struct sk_buff *build_CDisconnectRsp(u32);
+extern struct sk_buff *build_U3DataReq(u32, void *, u16, u16, u16);
+extern int parse_ACreateNCOCnf(struct sk_buff *, u8 *, u32 *);
+extern int parse_ADestroyNCOCnf(struct sk_buff *, u8 *, u32 *);
+extern int parse_CConnectCnf(struct sk_buff *, u32 *);
+extern int parse_CConnectInd(struct sk_buff *, u32 *, u8 *, u8 *, 
+			     u8 *, u8 *, u8 *);
+extern int parse_CDisconnectCnf(struct sk_buff *, u32 *, u32 *);
+extern int parse_CDisconnectInd(struct sk_buff *, u32 *, u32 *);
+extern int parse_U3ReadyToReceiveInd(struct sk_buff *, u32 *, u8 *);
+extern int parse_U3DataInd(struct sk_buff *, u32 *, u8 **, u16 *);
+
+/* Function prototypes from tpam_queues.c */
+extern void tpam_enqueue(tpam_card *, struct sk_buff *);
+extern void tpam_enqueue_data(tpam_channel *, struct sk_buff *);
+extern void tpam_irq(int, void *, struct pt_regs *);
+extern void tpam_recv_tq(tpam_card *);
+extern void tpam_send_tq(tpam_card *);
+
+/* Function prototypes from tpam_commands.c */
+extern int tpam_command(isdn_ctrl *);
+extern int tpam_writebuf_skb(int, int, int, struct sk_buff *);
+extern void tpam_recv_ACreateNCOCnf(tpam_card *, struct sk_buff *);
+extern void tpam_recv_ADestroyNCOCnf(tpam_card *, struct sk_buff *);
+extern void tpam_recv_CConnectCnf(tpam_card *, struct sk_buff *);
+extern void tpam_recv_CConnectInd(tpam_card *, struct sk_buff *);
+extern void tpam_recv_CDisconnectInd(tpam_card *, struct sk_buff *);
+extern void tpam_recv_CDisconnectCnf(tpam_card *, struct sk_buff *);
+extern void tpam_recv_U3DataInd(tpam_card *, struct sk_buff *);
+extern void tpam_recv_U3ReadyToReceiveInd(tpam_card *, struct sk_buff *);
+
+/* Function prototypes from tpam_hdlc.c */
+extern u32 hdlc_encode(u8 *, u8 *, u32 *, u32);
+extern u32 hdlc_decode(u8 *, u8 *, u32);
+
+/* Function prototypes from tpam_crcpc.c */
+extern void init_CRC(void);
+extern void hdlc_encode_modem(u8 *, u32, u8 *, u32 *);
+extern void hdlc_no_accm_encode(u8 *, u32, u8 *, u32 *);
+extern u32 hdlc_no_accm_decode(u8 *, u32);
+
+/* Define this to enable debug tracing prints */
+#undef DEBUG
+
+#ifdef DEBUG
+#define dprintk printk
+#else
+#define dprintk while(0) printk
+#endif
+
+#endif /* _TPAM_H_ */
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_commands.c linux/drivers/isdn/tpam/tpam_commands.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_commands.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_commands.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,1035 @@
+/* $Id: tpam_commands.c,v 1.1.2.2 2001/06/08 08:23:46 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include <linux/isdn/tpam.h>
+#include "tpam.h"
+
+/* Local functions prototypes */
+static int tpam_command_ioctl_dspload(tpam_card *, u32);
+static int tpam_command_ioctl_dspsave(tpam_card *, u32);
+static int tpam_command_ioctl_dsprun(tpam_card *);
+static int tpam_command_ioctl_loopmode(tpam_card *, u8);
+static int tpam_command_dial(tpam_card *, u32, u8 *);
+static int tpam_command_setl2(tpam_card *, u32, u8);
+static int tpam_command_getl2(tpam_card *, u32);
+static int tpam_command_acceptd(tpam_card *, u32);
+static int tpam_command_acceptb(tpam_card *, u32);
+static int tpam_command_hangup(tpam_card *, u32);
+static int tpam_command_proceed(tpam_card *, u32);
+static void tpam_statcallb_run(unsigned long);
+static void tpam_statcallb(tpam_card *, isdn_ctrl);
+
+/*
+ * Function called when the ISDN link level send a command to the driver.
+ *
+ * 	c: ISDN command.
+ *
+ * Return: 0 if OK, <0 on errors.
+ */
+int tpam_command(isdn_ctrl *c) {
+	tpam_card *card;
+	unsigned long argp;
+
+	dprintk("TurboPAM(tpam_command) card=%d, command=%d\n", 
+		c->driver, c->command);	
+
+	/* search for the board */
+	if (!(card = tpam_findcard(c->driver))) {
+		printk(KERN_ERR "TurboPAM(tpam_command): invalid driverId %d\n",
+		       c->driver);	
+		return -ENODEV;
+	}
+
+	/* dispatch the command */
+	switch (c->command) {
+		case ISDN_CMD_IOCTL:
+			argp = c->parm.userdata;
+			switch (c->arg) {
+				case TPAM_CMD_DSPLOAD:
+					return tpam_command_ioctl_dspload(card,
+									  argp);
+				case TPAM_CMD_DSPSAVE:
+					return tpam_command_ioctl_dspsave(card,
+									  argp);
+				case TPAM_CMD_DSPRUN:
+					return tpam_command_ioctl_dsprun(card);
+				case TPAM_CMD_LOOPMODEON:
+					return tpam_command_ioctl_loopmode(card,
+									   1);
+				case TPAM_CMD_LOOPMODEOFF:
+					return tpam_command_ioctl_loopmode(card,
+									   0);
+				default:
+					dprintk("TurboPAM(tpam_command): "
+						"invalid tpam ioctl %ld\n", 
+						c->arg);	
+					return -EINVAL;
+			}
+		case ISDN_CMD_DIAL:
+			return tpam_command_dial(card, c->arg, 
+						 c->parm.setup.phone);
+		case ISDN_CMD_ACCEPTD:
+			return tpam_command_acceptd(card, c->arg);
+		case ISDN_CMD_ACCEPTB:
+			return tpam_command_acceptb(card, c->arg);
+		case ISDN_CMD_HANGUP:
+			return tpam_command_hangup(card, c->arg);
+		case ISDN_CMD_SETL2:
+			return tpam_command_setl2(card, c->arg & 0xff, 
+						  c->arg >> 8);
+		case ISDN_CMD_GETL2:
+			return tpam_command_getl2(card, c->arg);
+		case ISDN_CMD_LOCK:
+			MOD_INC_USE_COUNT;
+			return 0;
+		case ISDN_CMD_UNLOCK:
+			MOD_DEC_USE_COUNT;
+			return 0;
+		case ISDN_CMD_PROCEED:
+			return tpam_command_proceed(card, c->arg);
+		default:
+			dprintk("TurboPAM(tpam_command): "
+				"unknown or unused isdn ioctl %d\n", 
+				c->command);	
+			return -EINVAL;
+	}
+
+	/* not reached */
+	return -EINVAL;
+}
+
+/*
+ * Load some data into the board's memory.
+ *
+ * 	card: the board
+ * 	arg: IOCTL argument containing the user space address of 
+ * 		the tpam_dsp_ioctl structure describing the IOCTL.
+ *
+ * Return: 0 if OK, <0 on errors.
+ */
+static int tpam_command_ioctl_dspload(tpam_card *card, u32 arg) {
+	tpam_dsp_ioctl tdl;
+	int ret;
+
+	dprintk("TurboPAM(tpam_command_ioctl_dspload): card=%d\n", card->id);
+
+	/* get the IOCTL parameter from userspace */
+	if (copy_from_user(&tdl, (void *)arg, sizeof(tpam_dsp_ioctl)))
+		return -EFAULT;
+
+	/* if the board's firmware was started, protect against writes
+	 * to unallowed memory areas. If the board's firmware wasn't started,
+	 * all is allowed. */
+	if (card->running && tpam_verify_area(tdl.address, tdl.data_len)) 
+		return -EPERM;
+
+	/* write the data in the board's memory */
+	ret = copy_from_user_to_pam(card, (void *)tdl.address, 
+				    (void *)arg + sizeof(tpam_dsp_ioctl), 
+				    tdl.data_len);
+	return 0;
+}
+
+/*
+ * Extract some data from the board's memory.
+ *
+ * 	card: the board
+ * 	arg: IOCTL argument containing the user space address of 
+ * 		the tpam_dsp_ioctl structure describing the IOCTL.
+ *
+ * Return: 0 if OK, <0 on errors.
+ */
+static int tpam_command_ioctl_dspsave(tpam_card *card, u32 arg) {
+	tpam_dsp_ioctl tdl;
+	int ret;
+
+	dprintk("TurboPAM(tpam_command_ioctl_dspsave): card=%d\n", card->id);
+
+	/* get the IOCTL parameter from userspace */
+	if (copy_from_user(&tdl, (void *)arg, sizeof(tpam_dsp_ioctl)))
+		return -EFAULT;
+
+	/* protect against read from unallowed memory areas */
+	if (tpam_verify_area(tdl.address, tdl.data_len)) 
+		return -EPERM;
+
+	/* read the data from the board's memory */
+	ret = copy_from_pam_to_user(card, (void *)arg + sizeof(tpam_dsp_ioctl),
+				    (void *)tdl.address, tdl.data_len);
+	return ret;
+}
+
+/*
+ * Launch the board's firmware. This function must be called after the 
+ * firmware was loaded into the board's memory using TPAM_CMD_DSPLOAD 
+ * IOCTL commands. After launching the firmware, this function creates
+ * the NCOs and waits for their creation.
+ *
+ * 	card: the board
+ *
+ * Return: 0 if OK, <0 on errors.
+ */
+static int tpam_command_ioctl_dsprun(tpam_card *card) {
+	u32 signature = 0, timeout, i;
+	isdn_ctrl ctrl;
+	struct sk_buff *skb;
+
+	dprintk("TurboPAM(tpam_command_ioctl_dsprun): card=%d\n", card->id);
+
+	/* board must _not_ be running */
+	if (card->running)
+		return -EBUSY;
+
+	/* reset the board */
+	spin_lock_irq(&card->lock);
+	copy_to_pam_dword(card, (void *)TPAM_MAGICNUMBER_REGISTER, 0xdeadface);
+	readl(card->bar0 + TPAM_DSPINT_REGISTER);
+	readl(card->bar0 + TPAM_HINTACK_REGISTER);
+	spin_unlock_irq(&card->lock);
+	
+	/* wait for the board signature */
+	timeout = jiffies + SIGNATURE_TIMEOUT;
+	while (timeout > jiffies) {
+		spin_lock_irq(&card->lock);
+		signature = copy_from_pam_dword(card, 
+						(void *)TPAM_MAGICNUMBER_REGISTER);
+		spin_unlock_irq(&card->lock);
+		if (signature == TPAM_MAGICNUMBER)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(2);
+	}
+
+	/* signature not present -> board not started */
+	if (signature != TPAM_MAGICNUMBER) {
+		printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
+		       "card=%d, signature 0x%lx, expected 0x%lx\n", 
+		       card->id, (unsigned long)signature, 
+		       (unsigned long)TPAM_MAGICNUMBER);
+		printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
+		       "card=%d, firmware not started\n", card->id);
+		return -EIO;
+	}
+
+	/* the firmware is started */
+	printk(KERN_INFO "TurboPAM: card=%d, firmware started\n", card->id);
+
+	/* init the CRC routines */
+	init_CRC();
+
+	/* create all the NCOs */
+	for (i = 0; i < TPAM_NBCHANNEL; ++i)
+		if ((skb = build_ACreateNCOReq("")))
+			tpam_enqueue(card, skb);
+
+	/* wait for NCO creation confirmation */
+	timeout = jiffies + NCOCREATE_TIMEOUT;
+	while (timeout > jiffies) {
+		if (card->channels_tested == TPAM_NBCHANNEL)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(2);
+	}
+
+	card->running = 1;
+
+	if (card->channels_tested != TPAM_NBCHANNEL)
+		printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
+		       "card=%d, tried to init %d channels, "
+		       "got reply from only %d channels\n", card->id, 
+		       TPAM_NBCHANNEL, card->channels_tested);
+
+	/* if all the channels were not initialized, signal to the ISDN
+	 * link layer that fact that some channels are not usable */
+	if (card->channels_used != TPAM_NBCHANNEL)
+		for (i = card->channels_used; i < TPAM_NBCHANNEL; ++i) {
+			ctrl.driver = card->id;
+			ctrl.command = ISDN_STAT_DISCH;
+			ctrl.arg = i;
+			ctrl.parm.num[0] = 0;
+			(* card->interface.statcallb)(&ctrl);
+		}
+
+	printk(KERN_INFO "TurboPAM: card=%d, ready, %d channels available\n", 
+	       card->id, card->channels_used);
+
+	/* let's rock ! */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_RUN;
+	ctrl.arg = 0;
+	tpam_statcallb(card, ctrl);
+
+	return 0;
+}
+
+/* 
+ * Set/reset the board's looptest mode.
+ *
+ * 	card: the board
+ * 	mode: if 1, sets the board's looptest mode, if 0 resets it.
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_ioctl_loopmode(tpam_card *card, u8 mode) {
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	card->loopmode = mode;
+	return 0;
+}
+
+/*
+ * Issue a dial command. This function builds and sends a CConnectReq.
+ * 
+ * 	card: the board
+ * 	channel: the channel number
+ * 	phone: the remote phone number (EAZ)
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) {
+	struct sk_buff *skb;
+	isdn_ctrl ctrl;
+
+	dprintk("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%s\n",
+		card->id, (unsigned long)channel, phone);
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* initialize channel parameters */
+	card->channels[channel].realhdlc = card->channels[channel].hdlc;
+	card->channels[channel].hdlcshift = 0;
+	card->channels[channel].readytoreceive = 0;
+
+	/* build and send a CConnectReq */
+	skb = build_CConnectReq(card->channels[channel].ncoid, phone, 
+				card->channels[channel].realhdlc);
+	if (!skb)
+		return -ENOMEM;
+	tpam_enqueue(card, skb);
+
+	/* making a connection in modem mode is slow and causes the ISDN
+	 * link layer to hangup the connection before even it gets a chance
+	 * to establish... All we can do is simulate a successful connection
+	 * for now, and send a DHUP later if the connection fails */
+	if (!card->channels[channel].realhdlc) {
+		ctrl.driver = card->id;
+		ctrl.command = ISDN_STAT_DCONN;
+		ctrl.arg = channel;
+		tpam_statcallb(card, ctrl);
+	}
+	
+	return 0;
+}
+
+/*
+ * Set the level2 protocol (modem or HDLC).
+ *
+ * 	card: the board
+ * 	channel: the channel number
+ * 	proto: the level2 protocol (one of ISDN_PROTO_L2*)
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_setl2(tpam_card *card, u32 channel, u8 proto) {
+
+	dprintk("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%d\n",
+		card->id, (unsigned long)channel, proto);
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* set the hdlc/modem mode */
+	switch (proto) {
+		case ISDN_PROTO_L2_HDLC:
+			card->channels[channel].hdlc = 1;
+			break;
+		case ISDN_PROTO_L2_MODEM:
+			card->channels[channel].hdlc = 0;
+			break;
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Return the level2 protocol (modem or HDLC).
+ *
+ * 	card: the board
+ * 	channel: the channel number
+ *
+ * Return: ISDN_PROTO_L2_HDLC/MODEM if OK, <0 if error.
+ */
+static int tpam_command_getl2(tpam_card *card, u32 channel) {
+
+	dprintk("TurboPAM(tpam_command_getl2): card=%d, channel=%lu\n",
+		card->id, (unsigned long)channel);
+	
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* return the current mode */
+	if (card->channels[channel].realhdlc)
+		return ISDN_PROTO_L2_HDLC;
+	else
+		return ISDN_PROTO_L2_MODEM;
+}
+
+/*
+ * Accept a D-channel connection (incoming connection). This function
+ * builds and sends a CConnectRsp message and signals DCONN to the ISDN
+ * link level.
+ *
+ * 	card: the board
+ * 	channel: the channel number
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_acceptd(tpam_card *card, u32 channel) {
+	isdn_ctrl ctrl;
+	struct sk_buff *skb;
+
+	dprintk("TurboPAM(tpam_command_acceptd): card=%d, channel=%lu\n",
+		card->id, (unsigned long)channel);
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* build and send a CConnectRsp */
+	skb = build_CConnectRsp(card->channels[channel].ncoid);
+	if (!skb)
+		return -ENOMEM;
+	tpam_enqueue(card, skb);
+
+	/* issue DCONN to the ISDN link level */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_DCONN;
+	ctrl.arg = channel;
+	tpam_statcallb(card, ctrl);
+	return 0;
+}
+
+/*
+ * Accepts a B-channel connection. This is not used by the driver, 
+ * since the TurboPAM is an active card hiding its B-channels from
+ * us. We just signal BCONN to the ISDN link layer.
+ *
+ * 	card: the board
+ * 	channel: the channel number
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_acceptb(tpam_card *card, u32 channel) {
+	isdn_ctrl ctrl;
+
+	dprintk("TurboPAM(tpam_command_acceptb): card=%d, channel=%lu\n",
+		card->id, (unsigned long)channel);
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* issue BCONN to the ISDN link level */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_BCONN;
+	ctrl.arg = channel;
+	ctrl.parm.num[0] = '\0';
+	tpam_statcallb(card, ctrl);
+	return 0;
+}
+
+/*
+ * Hang up a connection. This function builds and sends a CDisconnectReq.
+ *
+ * 	card: the board
+ * 	channel: the channel number.
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_hangup(tpam_card *card, u32 channel) {
+	struct sk_buff *skb;
+
+	dprintk("TurboPAM(tpam_command_hangup): card=%d, channel=%lu\n",
+		card->id, (unsigned long)channel);
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* build and send a CDisconnectReq */
+	skb = build_CDisconnectReq(card->channels[channel].ncoid);
+	if (!skb)
+		return -ENOMEM;
+	tpam_enqueue(card, skb);
+	return 0;
+}
+
+/*
+ * Proceed with an incoming connection. This function builds and sends a 
+ * CConnectRsp.
+ *
+ * 	card: the board
+ * 	channel: the channel number.
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int tpam_command_proceed(tpam_card *card, u32 channel) {
+	struct sk_buff *skb;
+
+	dprintk("TurboPAM(tpam_command_proceed): card=%d, channel=%lu\n",
+		card->id, (unsigned long)channel);
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* build and send a CConnectRsp */
+	skb = build_CConnectRsp(card->channels[channel].ncoid);
+	if (!skb)
+		return -ENOMEM;
+	tpam_enqueue(card, skb);
+	return 0;
+}
+
+/*
+ * Send data through the board. This function encodes the data depending
+ * on the connection type (modem or HDLC), then builds and sends a U3DataReq.
+ *
+ * 	driverId: the driver id (really meaning here the board)
+ * 	channel: the channel number
+ * 	ack: data needs to be acknowledged upon send
+ * 	skb: sk_buff containing the data
+ *
+ * Return: size of data send if OK, <0 if error.
+ */
+int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) {
+	tpam_card *card;
+	int orig_size = skb->len;
+	void *finaldata;
+	u32 finallen;
+
+	dprintk("TurboPAM(tpam_writebuf_skb): "
+		"card=%d, channel=%ld, ack=%d, data size=%d\n", 
+		driverId, (unsigned long)channel, ack, skb->len);
+
+	/* find the board based on its driver ID */
+	if (!(card = tpam_findcard(driverId))) {
+		printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
+		       "invalid driverId %d\n", driverId);	
+		return -ENODEV;
+	}
+
+	/* board must be running */
+	if (!card->running)
+		return -ENODEV;
+
+	/* allocate some temporary memory */
+	if (!(finaldata = (void *)__get_free_page(GFP_ATOMIC))) {
+		printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
+		       "get_free_page failed\n");
+		return -ENOMEM;
+	}
+
+	/* encode the data */
+	if (!card->channels[channel].realhdlc) {
+		/* modem mode */
+		hdlc_encode_modem(skb->data, skb->len, finaldata, &finallen);
+	}
+	else {
+		/* HDLC mode */
+		void *tempdata;
+		u32 templen;
+
+		if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
+			printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
+			       "get_free_page failed\n");
+			free_page((u32)finaldata);
+			return -ENOMEM;
+		}
+		hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen);
+		finallen = hdlc_encode(tempdata, finaldata, 
+				       &card->channels[channel].hdlcshift, 
+				       templen);
+		free_page((u32)tempdata);
+	}
+
+	/* free the old sk_buff */
+	kfree_skb(skb);
+
+	/* build and send a U3DataReq */
+	skb = build_U3DataReq(card->channels[channel].ncoid, finaldata, 
+			      finallen, ack, orig_size);
+	if (!skb) {
+		free_page((u32)finaldata);
+		return -ENOMEM;
+	}
+	tpam_enqueue_data(&card->channels[channel], skb);
+
+	/* free the temporary memory */
+	free_page((u32)finaldata);
+	return orig_size;
+}
+
+/*
+ * Treat a received ACreateNCOCnf message.
+ *
+ * 	card: the board
+ * 	skb: the received message
+ */
+void tpam_recv_ACreateNCOCnf(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u8 status;
+	u32 channel;
+
+	dprintk("TurboPAM(tpam_recv_ACreateNCOCnf): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_ACreateNCOCnf(skb, &status, &ncoid))
+		return;
+
+	/* if the card is alreay running, it means that this message
+	 * arrives too late... */
+	if (card->running) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
+		       "ACreateNCOCnf received too late, status=%d\n", status);
+		return;
+	}
+
+	/* the NCO creation failed, the corresponding channel will
+	 * be unused */
+	if (status) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
+		       "ACreateNCO failed, status=%d\n", status);
+		card->channels_tested++;
+		return;
+	}
+
+	/* find the first free channel and assign the nco ID to it */
+	if ((channel = tpam_findchannel(card, TPAM_NCOID_INVALID)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
+		       "All channels are assigned\n");
+		return;
+	}
+	card->channels[channel].ncoid = ncoid;
+	card->channels_tested++;
+	card->channels_used++;
+}
+
+/*
+ * Treat a received ADestroyNCOCnf message. Not used by the driver.
+ *
+ * 	card: the board
+ * 	skb: the received message
+ */
+void tpam_recv_ADestroyNCOCnf(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u8 status;
+	u32 channel;
+
+	dprintk("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_ADestroyNCOCnf(skb, &status, &ncoid))
+		return;
+	
+	if (status) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
+		       "ADestroyNCO failed, status=%d\n", status);
+		return;
+	}
+
+	/* clears the channel's nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	card->channels[channel].ncoid = TPAM_NCOID_INVALID;
+}
+
+/*
+ * Treat a received CConnectCnf message.
+ *
+ * 	card: the board
+ * 	skb: the received message
+ */
+void tpam_recv_CConnectCnf(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u32 channel;
+	isdn_ctrl ctrl;
+
+	dprintk("TurboPAM(tpam_recv_CConnectCnf): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_CConnectCnf(skb, &ncoid))
+		return;
+
+	/* find the channel by its nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_CConnectCnf): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	/* issue a DCONN command to the ISDN link layer if we are in HDLC mode.
+	 * In modem mode, we alreay did it - the ISDN timer kludge */
+	if (card->channels[channel].realhdlc) {
+		ctrl.driver = card->id;
+		ctrl.command = ISDN_STAT_DCONN;
+		ctrl.arg = channel;
+		(* card->interface.statcallb)(&ctrl);
+	}
+}
+
+/*
+ * Treat a received CConnectInd message. This function signals a ICALL
+ * to the ISDN link layer.
+ *
+ * 	card: the board
+ * 	skb: the received message
+ */
+void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u32 channel;
+	u8 hdlc, plan, screen;
+	u8 calling[PHONE_MAXIMUMSIZE], called[PHONE_MAXIMUMSIZE];
+	isdn_ctrl ctrl;
+	int status;
+
+	dprintk("TurboPAM(tpam_recv_CConnectInd): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_CConnectInd(skb, &ncoid, &hdlc, calling, called, &plan, &screen))
+		return;
+
+	/* find the channel by its nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_CConnectInd): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	/* initialize the channel parameters */
+	card->channels[channel].realhdlc = hdlc;
+	card->channels[channel].hdlcshift = 0;
+	card->channels[channel].readytoreceive = 0;
+
+	/* issue a ICALL command to the ISDN link layer */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_ICALL;
+	ctrl.arg = channel;
+	memcpy(ctrl.parm.setup.phone, calling, 32);
+	memcpy(ctrl.parm.setup.eazmsn, called, 32);
+	ctrl.parm.setup.si1 = 7;	/* data capability */
+	ctrl.parm.setup.si2 = 0;
+	ctrl.parm.setup.plan = plan;
+	ctrl.parm.setup.screen = screen;
+
+	status = (* card->interface.statcallb)(&ctrl);
+	switch (status) {
+		case 1:
+		case 4:
+			/* call accepted, link layer will send us a ACCEPTD 
+			 * command later */
+			dprintk("TurboPAM(tpam_recv_CConnectInd): "
+				"card=%d, channel=%d, icall waiting, status=%d\n", 
+				card->id, channel, status);
+			break;
+		default:
+			/* call denied, we build and send a CDisconnectReq */
+			dprintk("TurboPAM(tpam_recv_CConnectInd): "
+				"card=%d, channel=%d, icall denied, status=%d\n", 
+				card->id, channel, status);
+			skb = build_CDisconnectReq(ncoid);
+			if (!skb)
+				return;
+			tpam_enqueue(card, skb);
+	}
+}
+
+/*
+ * Treat a received CDisconnectInd message. This function signals a DHUP and
+ * a BHUP to the ISDN link layer.
+ *
+ * 	card: the board
+ * 	skb: the received message
+ */
+void tpam_recv_CDisconnectInd(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u32 channel;
+	u32 cause;
+	isdn_ctrl ctrl;
+
+	dprintk("TurboPAM(tpam_recv_CDisconnectInd): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_CDisconnectInd(skb, &ncoid, &cause))
+		return;
+
+	/* find the channel by its nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectInd): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	/* build and send a CDisconnectRsp */
+	skb = build_CDisconnectRsp(ncoid);
+	if (!skb)
+		return;
+	tpam_enqueue(card, skb);
+
+	/* issue a DHUP to the ISDN link layer */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_DHUP;
+	ctrl.arg = channel;
+	(* card->interface.statcallb)(&ctrl);
+
+	/* issue a BHUP to the ISDN link layer */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_BHUP;
+	ctrl.arg = channel;
+	(* card->interface.statcallb)(&ctrl);
+}
+
+/*
+ * Treat a received CDisconnectCnf message. This function signals a DHUP and
+ * a BHUP to the ISDN link layer.
+ *
+ * 	card: the board
+ * 	skb: the received message
+ */
+void tpam_recv_CDisconnectCnf(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u32 channel;
+	u32 cause;
+	isdn_ctrl ctrl;
+
+	dprintk("TurboPAM(tpam_recv_CDisconnectCnf): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_CDisconnectCnf(skb, &ncoid, &cause))
+		return;
+
+	/* find the channel by its nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectCnf): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	/* issue a DHUP to the ISDN link layer */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_DHUP;
+	ctrl.arg = channel;
+	(* card->interface.statcallb)(&ctrl);
+
+	/* issue a BHUP to the ISDN link layer */
+	ctrl.driver = card->id;
+	ctrl.command = ISDN_STAT_BHUP;
+	ctrl.arg = channel;
+	(* card->interface.statcallb)(&ctrl);
+}
+
+/*
+ * Treat a received U3DataInd message. This function decodes the data
+ * depending on the connection type (modem or HDLC) and passes it to the
+ * ISDN link layer by using rcvcallb_skb.
+ *
+ * 	card: the board
+ * 	skb: the received message + data
+ */
+void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u32 channel;
+	u8 *data;
+	u16 len;
+	struct sk_buff *result;
+
+	dprintk("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%d\n", 
+		card->id, skb->len);
+
+	/* parse the message contents */
+	if (parse_U3DataInd(skb, &ncoid, &data, &len))
+		return;
+
+	/* find the channel by its nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	/* decode the data */
+	if (card->channels[ncoid].realhdlc) {
+		/* HDLC mode */
+		u8 *tempdata;
+		u32 templen;
+
+		if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
+			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
+			       "get_free_page failed\n");
+			return;
+		}
+		templen = hdlc_decode(data, tempdata, len);
+		templen = hdlc_no_accm_decode(tempdata, templen);
+		if (!(result = alloc_skb(templen, GFP_ATOMIC))) {
+			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
+			       "alloc_skb failed\n");
+			free_page((u32)tempdata);
+			return;
+		}
+		memcpy(skb_put(result, templen), tempdata, templen);
+		free_page((u32)tempdata);
+	}
+	else {
+		/* modem mode */
+		if (!(result = alloc_skb(len, GFP_ATOMIC))) {
+			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
+			       "alloc_skb failed\n");
+			return;
+		}
+		memcpy(skb_put(result, len), data, len);
+	}
+
+	/* In loop mode, resend the data immediatly */
+	if (card->loopmode) {
+		struct sk_buff *loopskb;
+
+		if (!(loopskb = alloc_skb(skb->len, GFP_ATOMIC))) {
+			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
+			       "alloc_skb failed\n");
+			kfree_skb(result);
+			return;
+		}
+		memcpy(skb_put(loopskb, result->len), result->data, 
+		       result->len);
+		if (tpam_writebuf_skb(card->id, channel, 0, loopskb) < 0)
+			kfree_skb(loopskb);
+	}
+
+	/* pass the data to the ISDN link layer */
+	(* card->interface.rcvcallb_skb)(card->id, channel, result);
+}
+
+/*
+ * Treat a received U3ReadyToReceiveInd message. This function sets the
+ * channel ready flag and triggers the send of data if the channel becomed
+ * ready.
+ *
+ * 	card: the board
+ * 	skb: the received message + data
+ */
+void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) {
+	u32 ncoid;
+	u32 channel;
+	u8 ready;
+
+	dprintk("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%d\n", card->id);
+
+	/* parse the message contents */
+	if (parse_U3ReadyToReceiveInd(skb, &ncoid, &ready))
+		return;
+
+	/* find the channel by its nco ID */
+	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
+		printk(KERN_ERR "TurboPAM(tpam_recv_U3ReadyToReceiveInd): "
+		       "ncoid invalid %lu\n", (unsigned long)ncoid);
+		return;
+	}
+
+	/* set the readytoreceive flag */
+	card->channels[channel].readytoreceive = ready;
+
+	/* if the channel just becomed ready, trigger the send of queued data */
+	if (ready)
+		tpam_enqueue_data(&card->channels[channel], NULL);
+}
+
+/*
+ * Runs the delayed statcallb when its timer expires.
+ *
+ * 	parm: pointer to the tpam_statcallb_data statcallb argument.
+ */
+static void tpam_statcallb_run(unsigned long parm) {
+	tpam_statcallb_data *ds = (tpam_statcallb_data *)parm;
+
+	dprintk("TurboPAM(tpam_statcallb_run)\n");
+
+	(* ds->card->interface.statcallb)(&ds->ctrl);
+
+	kfree(ds->timer);
+	kfree(ds);
+}
+
+/*
+ * Queues a statcallb call for delayed invocation.
+ *
+ * 	card: the board
+ * 	ctrl: the statcallb argument
+ */
+static void tpam_statcallb(tpam_card *card, isdn_ctrl ctrl) {
+	struct timer_list *timer;
+	tpam_statcallb_data *ds;
+
+	dprintk("TurboPAM(tpam_statcallb): card=%d\n", card->id);
+
+	if (!(timer = (struct timer_list *) kmalloc(sizeof(struct timer_list), 
+						    GFP_ATOMIC))) {
+		printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n");
+		return;
+	}
+
+	if (!(ds = (tpam_statcallb_data *) kmalloc(sizeof(tpam_statcallb_data),
+						   GFP_ATOMIC))) {
+		printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n");
+		kfree(timer);
+		return;
+	}
+	ds->card = card;
+	ds->timer = timer;
+	memcpy(&ds->ctrl, &ctrl, sizeof(isdn_ctrl));
+
+	init_timer(timer);
+	timer->function = tpam_statcallb_run;
+	timer->data = (unsigned long)ds;
+	timer->expires = jiffies + 0.1 * HZ;   /* 0.1 second */
+	add_timer(timer);
+}
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_crcpc.c linux/drivers/isdn/tpam/tpam_crcpc.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_crcpc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_crcpc.c	Mon Dec  3 22:50:37 2001
@@ -0,0 +1,207 @@
+/* $Id: tpam_crcpc.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
+ *
+ * Copyright 1998-2000 AUVERTECH Télécom
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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.
+ *
+ */
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Module Name:
+
+    crcpc.c
+
+Abstract:
+
+    Modem HDLC coding
+    Software HDLC coding / decoding
+
+Revision History:
+
+---------------------------------------------------------------------------*/
+
+#include "tpam.h"
+
+#define  HDLC_CTRL_CHAR_CMPL_MASK	0x20	/* HDLC control character complement mask */
+#define  HDLC_FLAG			0x7E	/* HDLC flag */
+#define  HDLC_CTRL_ESC			0x7D	/* HDLC control escapr character */
+#define  HDLC_LIKE_FCS_INIT_VAL		0xFFFF	/* FCS initial value (0xFFFF for new equipment or 0) */
+#define  HDLC_FCS_OK			0xF0B8	/* This value is the only valid value of FCS */
+
+#define TRUE	1
+#define FALSE	0
+
+static u16 t_ap_hdlc_like_fcs [256] = {
+	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+static u8 ap_t_ctrl_char_complemented[256]; /* list of characters to complement */
+
+static void ap_hdlc_like_ctrl_char_list (u32 ctrl_char) {
+	int i;
+
+	for (i = 0; i < 256; ++i)
+		ap_t_ctrl_char_complemented[i] = FALSE;
+	for (i = 0; i < 32; ++i)
+		if ((ctrl_char >> i) & 0x0001)
+			ap_t_ctrl_char_complemented [i] = TRUE;
+	ap_t_ctrl_char_complemented[HDLC_FLAG] = TRUE;
+	ap_t_ctrl_char_complemented[HDLC_CTRL_ESC] = TRUE;
+		
+}
+
+void init_CRC() {
+	ap_hdlc_like_ctrl_char_list(0xffffffff);
+}
+
+void hdlc_encode_modem(u8 *buffer_in, u32 lng_in,
+		       u8 *buffer_out, u32 *lng_out) {
+	u16 fcs;
+	register u8 data;
+	register u8 *p_data_out = buffer_out;
+
+	fcs = HDLC_LIKE_FCS_INIT_VAL;
+
+	/*
+	 *   Insert HDLC flag at the beginning of the frame
+	 */
+	*p_data_out++ = HDLC_FLAG;
+
+#define ESCAPE_CHAR(data_out, data) \
+	if (ap_t_ctrl_char_complemented[data]) { \
+		*data_out++ = HDLC_CTRL_ESC; \
+		*data_out++ = data ^ 0x20; \
+	} \
+	else \
+		*data_out++ = data;
+
+	while (lng_in--) {
+		data = *buffer_in++;
+
+		/*
+		 *   FCS calculation
+		 */
+		fcs = (fcs>>8) ^ t_ap_hdlc_like_fcs[((u8)(fcs^data)) & 0xff];
+
+		ESCAPE_CHAR(p_data_out, data);
+	}
+
+	/*
+	 *  Add FCS and closing flag
+	 */
+	fcs ^= 0xFFFF;  // Complement
+
+	data = (u8)(fcs & 0xff);	/* LSB */
+	ESCAPE_CHAR(p_data_out, data);
+
+	data = (u8)((fcs >> 8));	/* MSB */
+	ESCAPE_CHAR(p_data_out, data);
+#undef ESCAPE_CHAR
+
+	*p_data_out++ = HDLC_FLAG;
+
+	*lng_out = (u32)(p_data_out - buffer_out);
+}
+
+void hdlc_no_accm_encode(u8 *buffer_in, u32 lng_in, 
+			 u8 *buffer_out, u32 *lng_out) {
+	u16 fcs;
+	register u8 data;
+	register u8 *p_data_out = buffer_out;
+
+	/*
+	 *   Insert HDLC flag at the beginning of the frame
+	 */
+	fcs = HDLC_LIKE_FCS_INIT_VAL;
+
+	while (lng_in--) {
+		data = *buffer_in++;
+		/* calculate FCS */
+		fcs = (fcs>>8) ^ t_ap_hdlc_like_fcs[((u8)(fcs^data)) & 0xff];
+		*p_data_out++ = data;
+	}
+
+	/*
+	 *  Add FCS and closing flag
+	 */
+	fcs ^= 0xFFFF;  // Complement
+	data = (u8)(fcs);    
+	*p_data_out++ = data;
+
+	data =(u8)((fcs >> 8));   // revense MSB / LSB
+	*p_data_out++ = data;
+ 
+	*lng_out = (u32)(p_data_out - buffer_out);
+}
+
+u32 hdlc_no_accm_decode(u8 *buffer_in, u32 lng_in) {
+	u16 fcs;
+	u32 lng = lng_in;
+	register u8 data;
+
+	/*
+	 *   Insert HDLC flag at the beginning of the frame
+	 */
+	fcs = HDLC_LIKE_FCS_INIT_VAL;
+
+	while (lng_in--) {
+		data = *buffer_in++;
+		/* calculate FCS */
+		fcs = (fcs>>8) ^ t_ap_hdlc_like_fcs[((u8)(fcs^data)) & 0xff];
+	}
+
+	if (fcs == HDLC_FCS_OK) 
+		return (lng-2);
+	else 
+		return 0;
+}
+
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_hdlc.c linux/drivers/isdn/tpam/tpam_hdlc.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_hdlc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_hdlc.c	Mon Dec  3 22:50:38 2001
@@ -0,0 +1,934 @@
+/* $Id: tpam_hdlc.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
+ *
+ * Copyright 1998-2000 AUVERTECH Télécom
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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.
+ *
+ */
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Module Name:
+
+    hdlc.c
+
+Abstract:
+
+    stuff0 : array necessary for the bit stuffing algorithm
+    stuff1 : array necessary for the bit stuffing algorithm
+    stuff2 : array necessary for the bit stuffing algorithm
+    stuff3 : array necessary for the bit stuffing algorithm
+    stuff4 : array necessary for the bit stuffing algorithm
+    stuff5 : array necessary for the bit stuffing algorithm
+    stuffs[] : array conaining the previous 6 arrays
+    destuff0 : array necessary for the bit destuffing algorithm
+    destuff1 : array necessary for the bit destuffing algorithm
+    destuff2 : array necessary for the bit destuffing algorithm
+    destuff3 : array necessary for the bit destuffing algorithm
+    destuff4 : array necessary for the bit destuffing algorithm
+    destuff5 : array necessary for the bit destuffing algorithm
+    destuffs[] : array conaining the previous 6 arrays
+
+    hdlc_encode : bit stuffing of a byte array, with the addition of a start and
+    		  end flag, using the bit shift given in parameter (which is 
+		  updated at the end of encoding).
+    hdlc_decode : bit de-stuffing of a byte array with detection of possible
+    		  ABORTs.
+
+Revision History:
+
+---------------------------------------------------------------------------*/
+
+/* The arrays are used as follows:
+
+  For the bit stuffing :
+	
+  stuff0 = used if the previous byte ended with '0'
+  stuff1 = used if the previous byte ended with '10'
+  stuff2 = used if the previous byte ended with '110'
+  stuff3 = used if the previous byte ended with '1110'
+  stuff4 = used if the previous byte ended with '11110'
+  stuff5 = used if the previous byte ended with '111110'
+  
+  those arrays are indexed by the byte to stuff.
+  
+  the data of those arrays are of the form (in binary):
+  "bbbbaaaa cccccccc"
+  with "cccccccc" : byte stuffed
+       "aaaa" : "0000" --> no insertion of '0'
+	            "0100" --> 1 '0' inserted, carry = '0'
+                "0101" --> 1 '0' inserted, carry = '1'
+                "1000" --> 2 '0' inserted, carry = '00'
+                "1001" --> 2 '0' inserted, carry = '01'
+                "1010" --> 2 '0' inserted, carry = '10'
+                "1011" --> 2 '0' inserted, carry = '11'
+       "bbbb" : count of '1' at the end of "cccccccc"
+
+
+  
+  For the bit de-stuffing :
+
+  destuff0 = used if the previous byte ended with '0'
+  destuff1 = used if the previous byte ended with '10'
+  destuff2 = used if the previous byte ended with '110'
+  destuff3 = used if the previous byte ended with '1110'
+  destuff4 = used if the previous byte ended with '11110'
+  destuff5 = used if the previous byte ended with '111110'
+
+  those arrays are indexed by the byte to de-stuff.
+
+  the data of those arrays are of the form (in binary):
+  "dbbbaaaa cccccccc"
+  with "cccccccc" : byte destuffed
+       "aaaa" : count of '1' at the end of the byte non destuffed
+       "bbb" : count of bits to use in the destuffed byte (8 less the count
+               of '0' deleted) less 1 (can be only 7, 6 or 5)
+	   "d" : '1' if the byte non destuffed has more than 5 consecutive '1' 
+	         (flag or abort)
+*/
+
+#include <linux/types.h>
+#include "tpam.h"
+
+typedef u8	BYTE;
+typedef u16	WORD;
+typedef u32	DWORD;
+typedef u8	BOOL;
+
+#define	TRUE			1
+#define FALSE			0
+
+static WORD stuff0[] =
+{
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 
+	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 
+	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 
+	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x041F, 
+	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 
+	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 
+	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x045F, 
+	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 
+	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x149F, 
+	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 
+	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 
+	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 
+	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x24DF, 
+	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 
+	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, 
+	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 
+	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x051F, 
+	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, 
+	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF, 
+	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, 
+	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x055F, 
+	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, 
+	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, 
+	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 
+	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x159F, 
+	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, 
+	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, 
+	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, 
+	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x25DF, 
+};
+
+
+static WORD stuff1[] =
+{
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 
+	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x040F, 
+	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 
+	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x042F, 
+	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 
+	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x044F, 
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 
+	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x046F, 
+	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x148F, 
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 
+	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14AF, 
+	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 
+	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24CF, 
+	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 
+	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x34EF, 
+	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 
+	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x050F, 
+	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 
+	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x052F, 
+	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, 
+	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x054F, 
+	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, 
+	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x056F, 
+	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, 
+	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x158F, 
+	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 
+	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15AF, 
+	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, 
+	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25CF, 
+	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, 
+	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x35EF, 
+};
+
+
+static WORD stuff2[] =
+{
+	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0407, 
+	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0417, 
+	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0427, 
+	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x0437, 
+	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0447, 
+	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x0457, 
+	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0467, 
+	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x0477, 
+	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x1487, 
+	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x1497, 
+	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x14A7, 
+	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14B7, 
+	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x24C7, 
+	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24D7, 
+	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x34E7, 
+	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x44F7, 
+	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x0507, 
+	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x0517, 
+	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x0527, 
+	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x0537, 
+	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x0547, 
+	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x0557, 
+	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x0567, 
+	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x0577, 
+	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x1587, 
+	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x1597, 
+	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x15A7, 
+	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15B7, 
+	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x25C7, 
+	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25D7, 
+	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x35E7, 
+	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x45F7, 
+};
+
+
+static WORD stuff3[] =
+{
+	0x0000, 0x0001, 0x0002, 0x0403, 0x0004, 0x0005, 0x0006, 0x040B, 
+	0x0008, 0x0009, 0x000A, 0x0413, 0x000C, 0x000D, 0x000E, 0x041B, 
+	0x0010, 0x0011, 0x0012, 0x0423, 0x0014, 0x0015, 0x0016, 0x042B, 
+	0x0018, 0x0019, 0x001A, 0x0433, 0x001C, 0x001D, 0x001E, 0x043B, 
+	0x0020, 0x0021, 0x0022, 0x0443, 0x0024, 0x0025, 0x0026, 0x044B, 
+	0x0028, 0x0029, 0x002A, 0x0453, 0x002C, 0x002D, 0x002E, 0x045B, 
+	0x0030, 0x0031, 0x0032, 0x0463, 0x0034, 0x0035, 0x0036, 0x046B, 
+	0x0038, 0x0039, 0x003A, 0x0473, 0x003C, 0x003D, 0x043E, 0x047B, 
+	0x0040, 0x0041, 0x0042, 0x1483, 0x0044, 0x0045, 0x0046, 0x148B, 
+	0x0048, 0x0049, 0x004A, 0x1493, 0x004C, 0x004D, 0x004E, 0x149B, 
+	0x0050, 0x0051, 0x0052, 0x14A3, 0x0054, 0x0055, 0x0056, 0x14AB, 
+	0x0058, 0x0059, 0x005A, 0x14B3, 0x005C, 0x005D, 0x005E, 0x14BB, 
+	0x0060, 0x0061, 0x0062, 0x24C3, 0x0064, 0x0065, 0x0066, 0x24CB, 
+	0x0068, 0x0069, 0x006A, 0x24D3, 0x006C, 0x006D, 0x006E, 0x24DB, 
+	0x0070, 0x0071, 0x0072, 0x34E3, 0x0074, 0x0075, 0x0076, 0x34EB, 
+	0x0078, 0x0079, 0x007A, 0x44F3, 0x047C, 0x047D, 0x14BE, 0x54FB, 
+	0x1080, 0x1081, 0x1082, 0x0503, 0x1084, 0x1085, 0x1086, 0x050B, 
+	0x1088, 0x1089, 0x108A, 0x0513, 0x108C, 0x108D, 0x108E, 0x051B, 
+	0x1090, 0x1091, 0x1092, 0x0523, 0x1094, 0x1095, 0x1096, 0x052B, 
+	0x1098, 0x1099, 0x109A, 0x0533, 0x109C, 0x109D, 0x109E, 0x053B, 
+	0x10A0, 0x10A1, 0x10A2, 0x0543, 0x10A4, 0x10A5, 0x10A6, 0x054B, 
+	0x10A8, 0x10A9, 0x10AA, 0x0553, 0x10AC, 0x10AD, 0x10AE, 0x055B, 
+	0x10B0, 0x10B1, 0x10B2, 0x0563, 0x10B4, 0x10B5, 0x10B6, 0x056B, 
+	0x10B8, 0x10B9, 0x10BA, 0x0573, 0x10BC, 0x10BD, 0x053E, 0x057B, 
+	0x20C0, 0x20C1, 0x20C2, 0x1583, 0x20C4, 0x20C5, 0x20C6, 0x158B, 
+	0x20C8, 0x20C9, 0x20CA, 0x1593, 0x20CC, 0x20CD, 0x20CE, 0x159B, 
+	0x20D0, 0x20D1, 0x20D2, 0x15A3, 0x20D4, 0x20D5, 0x20D6, 0x15AB, 
+	0x20D8, 0x20D9, 0x20DA, 0x15B3, 0x20DC, 0x20DD, 0x20DE, 0x15BB, 
+	0x30E0, 0x30E1, 0x30E2, 0x25C3, 0x30E4, 0x30E5, 0x30E6, 0x25CB, 
+	0x30E8, 0x30E9, 0x30EA, 0x25D3, 0x30EC, 0x30ED, 0x30EE, 0x25DB, 
+	0x40F0, 0x40F1, 0x40F2, 0x35E3, 0x40F4, 0x40F5, 0x40F6, 0x35EB, 
+	0x50F8, 0x50F9, 0x50FA, 0x45F3, 0x057C, 0x057D, 0x15BE, 0x55FB, 
+};
+
+
+static WORD stuff4[] =
+{
+	0x0000, 0x0401, 0x0002, 0x0405, 0x0004, 0x0409, 0x0006, 0x040D, 
+	0x0008, 0x0411, 0x000A, 0x0415, 0x000C, 0x0419, 0x000E, 0x041D, 
+	0x0010, 0x0421, 0x0012, 0x0425, 0x0014, 0x0429, 0x0016, 0x042D, 
+	0x0018, 0x0431, 0x001A, 0x0435, 0x001C, 0x0439, 0x001E, 0x043D, 
+	0x0020, 0x0441, 0x0022, 0x0445, 0x0024, 0x0449, 0x0026, 0x044D, 
+	0x0028, 0x0451, 0x002A, 0x0455, 0x002C, 0x0459, 0x002E, 0x045D, 
+	0x0030, 0x0461, 0x0032, 0x0465, 0x0034, 0x0469, 0x0036, 0x046D, 
+	0x0038, 0x0471, 0x003A, 0x0475, 0x003C, 0x0479, 0x043E, 0x087D, 
+	0x0040, 0x1481, 0x0042, 0x1485, 0x0044, 0x1489, 0x0046, 0x148D, 
+	0x0048, 0x1491, 0x004A, 0x1495, 0x004C, 0x1499, 0x004E, 0x149D, 
+	0x0050, 0x14A1, 0x0052, 0x14A5, 0x0054, 0x14A9, 0x0056, 0x14AD, 
+	0x0058, 0x14B1, 0x005A, 0x14B5, 0x005C, 0x14B9, 0x005E, 0x14BD, 
+	0x0060, 0x24C1, 0x0062, 0x24C5, 0x0064, 0x24C9, 0x0066, 0x24CD, 
+	0x0068, 0x24D1, 0x006A, 0x24D5, 0x006C, 0x24D9, 0x006E, 0x24DD, 
+	0x0070, 0x34E1, 0x0072, 0x34E5, 0x0074, 0x34E9, 0x0076, 0x34ED, 
+	0x0078, 0x44F1, 0x007A, 0x44F5, 0x047C, 0x54F9, 0x14BE, 0x097D, 
+	0x1080, 0x0501, 0x1082, 0x0505, 0x1084, 0x0509, 0x1086, 0x050D, 
+	0x1088, 0x0511, 0x108A, 0x0515, 0x108C, 0x0519, 0x108E, 0x051D, 
+	0x1090, 0x0521, 0x1092, 0x0525, 0x1094, 0x0529, 0x1096, 0x052D, 
+	0x1098, 0x0531, 0x109A, 0x0535, 0x109C, 0x0539, 0x109E, 0x053D, 
+	0x10A0, 0x0541, 0x10A2, 0x0545, 0x10A4, 0x0549, 0x10A6, 0x054D, 
+	0x10A8, 0x0551, 0x10AA, 0x0555, 0x10AC, 0x0559, 0x10AE, 0x055D, 
+	0x10B0, 0x0561, 0x10B2, 0x0565, 0x10B4, 0x0569, 0x10B6, 0x056D, 
+	0x10B8, 0x0571, 0x10BA, 0x0575, 0x10BC, 0x0579, 0x053E, 0x0A7D, 
+	0x20C0, 0x1581, 0x20C2, 0x1585, 0x20C4, 0x1589, 0x20C6, 0x158D, 
+	0x20C8, 0x1591, 0x20CA, 0x1595, 0x20CC, 0x1599, 0x20CE, 0x159D, 
+	0x20D0, 0x15A1, 0x20D2, 0x15A5, 0x20D4, 0x15A9, 0x20D6, 0x15AD, 
+	0x20D8, 0x15B1, 0x20DA, 0x15B5, 0x20DC, 0x15B9, 0x20DE, 0x15BD, 
+	0x30E0, 0x25C1, 0x30E2, 0x25C5, 0x30E4, 0x25C9, 0x30E6, 0x25CD, 
+	0x30E8, 0x25D1, 0x30EA, 0x25D5, 0x30EC, 0x25D9, 0x30EE, 0x25DD, 
+	0x40F0, 0x35E1, 0x40F2, 0x35E5, 0x40F4, 0x35E9, 0x40F6, 0x35ED, 
+	0x50F8, 0x45F1, 0x50FA, 0x45F5, 0x057C, 0x55F9, 0x15BE, 0x0B7D, 
+};
+
+
+static WORD stuff5[] =
+{
+	0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, 
+	0x0410, 0x0412, 0x0414, 0x0416, 0x0418, 0x041A, 0x041C, 0x041E, 
+	0x0420, 0x0422, 0x0424, 0x0426, 0x0428, 0x042A, 0x042C, 0x042E, 
+	0x0430, 0x0432, 0x0434, 0x0436, 0x0438, 0x043A, 0x043C, 0x083E, 
+	0x0440, 0x0442, 0x0444, 0x0446, 0x0448, 0x044A, 0x044C, 0x044E, 
+	0x0450, 0x0452, 0x0454, 0x0456, 0x0458, 0x045A, 0x045C, 0x045E, 
+	0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, 0x046E, 
+	0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x087C, 0x18BE, 
+	0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148A, 0x148C, 0x148E, 
+	0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149A, 0x149C, 0x149E, 
+	0x14A0, 0x14A2, 0x14A4, 0x14A6, 0x14A8, 0x14AA, 0x14AC, 0x14AE, 
+	0x14B0, 0x14B2, 0x14B4, 0x14B6, 0x14B8, 0x14BA, 0x14BC, 0x093E, 
+	0x24C0, 0x24C2, 0x24C4, 0x24C6, 0x24C8, 0x24CA, 0x24CC, 0x24CE, 
+	0x24D0, 0x24D2, 0x24D4, 0x24D6, 0x24D8, 0x24DA, 0x24DC, 0x24DE, 
+	0x34E0, 0x34E2, 0x34E4, 0x34E6, 0x34E8, 0x34EA, 0x34EC, 0x34EE, 
+	0x44F0, 0x44F2, 0x44F4, 0x44F6, 0x54F8, 0x54FA, 0x097C, 0x19BE, 
+	0x0500, 0x0502, 0x0504, 0x0506, 0x0508, 0x050A, 0x050C, 0x050E, 
+	0x0510, 0x0512, 0x0514, 0x0516, 0x0518, 0x051A, 0x051C, 0x051E, 
+	0x0520, 0x0522, 0x0524, 0x0526, 0x0528, 0x052A, 0x052C, 0x052E, 
+	0x0530, 0x0532, 0x0534, 0x0536, 0x0538, 0x053A, 0x053C, 0x0A3E, 
+	0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E, 
+	0x0550, 0x0552, 0x0554, 0x0556, 0x0558, 0x055A, 0x055C, 0x055E, 
+	0x0560, 0x0562, 0x0564, 0x0566, 0x0568, 0x056A, 0x056C, 0x056E, 
+	0x0570, 0x0572, 0x0574, 0x0576, 0x0578, 0x057A, 0x0A7C, 0x1ABE, 
+	0x1580, 0x1582, 0x1584, 0x1586, 0x1588, 0x158A, 0x158C, 0x158E, 
+	0x1590, 0x1592, 0x1594, 0x1596, 0x1598, 0x159A, 0x159C, 0x159E, 
+	0x15A0, 0x15A2, 0x15A4, 0x15A6, 0x15A8, 0x15AA, 0x15AC, 0x15AE, 
+	0x15B0, 0x15B2, 0x15B4, 0x15B6, 0x15B8, 0x15BA, 0x15BC, 0x0B3E, 
+	0x25C0, 0x25C2, 0x25C4, 0x25C6, 0x25C8, 0x25CA, 0x25CC, 0x25CE, 
+	0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8, 0x25DA, 0x25DC, 0x25DE, 
+	0x35E0, 0x35E2, 0x35E4, 0x35E6, 0x35E8, 0x35EA, 0x35EC, 0x35EE, 
+	0x45F0, 0x45F2, 0x45F4, 0x45F6, 0x55F8, 0x55FA, 0x0B7C, 0x1BBE, 
+};
+
+static WORD destuff0[] =
+{
+	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, 
+	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x700F, 
+	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, 
+	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0x601F, 
+	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027, 
+	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x702F, 
+	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037, 
+	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, 
+	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, 
+	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x704F, 
+	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, 
+	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0x603F, 
+	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, 
+	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x706F, 
+	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077, 
+	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, 
+	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187, 
+	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x718F, 
+	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197, 
+	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0x615F, 
+	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7, 
+	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x71AF, 
+	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7, 
+	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
+	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7, 
+	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x72CF, 
+	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7, 
+	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0x627F, 
+	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7, 
+	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x73EF, 
+	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7, 
+	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF8FF, 
+};
+
+
+static WORD destuff1[] =
+{
+	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, 
+	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x600F, 
+	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, 
+	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F, 
+	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027, 
+	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x601F, 
+	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037, 
+	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, 
+	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, 
+	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x602F, 
+	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, 
+	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F, 
+	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, 
+	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x603F, 
+	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077, 
+	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, 
+	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187, 
+	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x614F, 
+	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197, 
+	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F, 
+	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7, 
+	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x615F, 
+	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7, 
+	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
+	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7, 
+	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x626F, 
+	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7, 
+	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, 
+	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7, 
+	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x637F, 
+	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7, 
+	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF9FF, 
+};
+
+
+static WORD destuff2[] =
+{
+	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x6007, 
+	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0xF00F, 
+	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x600F, 
+	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F, 
+	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x6017, 
+	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0xF02F, 
+	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x601F, 
+	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, 
+	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x6027, 
+	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0xF04F, 
+	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x602F, 
+	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F, 
+	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x6037, 
+	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0xF06F, 
+	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x603F, 
+	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, 
+	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x6147, 
+	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0xF18F, 
+	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x614F, 
+	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F, 
+	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x6157, 
+	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0xF1AF, 
+	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x615F, 
+	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
+	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x6267, 
+	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0xF2CF, 
+	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x626F, 
+	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, 
+	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x6377, 
+	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0xF3EF, 
+	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x647F, 
+	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xFAFF, 
+};
+
+
+static WORD destuff3[] =
+{
+	0x7000, 0x7001, 0x7002, 0x6003, 0x7004, 0x7005, 0x7006, 0xF007, 
+	0x7008, 0x7009, 0x700A, 0x6007, 0x700C, 0x700D, 0x700E, 0xF00F, 
+	0x7010, 0x7011, 0x7012, 0x600B, 0x7014, 0x7015, 0x7016, 0xF017, 
+	0x7018, 0x7019, 0x701A, 0x600F, 0x701C, 0x701D, 0x701E, 0xF01F, 
+	0x7020, 0x7021, 0x7022, 0x6013, 0x7024, 0x7025, 0x7026, 0xF027, 
+	0x7028, 0x7029, 0x702A, 0x6017, 0x702C, 0x702D, 0x702E, 0xF02F, 
+	0x7030, 0x7031, 0x7032, 0x601B, 0x7034, 0x7035, 0x7036, 0xF037, 
+	0x7038, 0x7039, 0x703A, 0x601F, 0x703C, 0x703D, 0x603E, 0xF03F, 
+	0x7040, 0x7041, 0x7042, 0x6023, 0x7044, 0x7045, 0x7046, 0xF047, 
+	0x7048, 0x7049, 0x704A, 0x6027, 0x704C, 0x704D, 0x704E, 0xF04F, 
+	0x7050, 0x7051, 0x7052, 0x602B, 0x7054, 0x7055, 0x7056, 0xF057, 
+	0x7058, 0x7059, 0x705A, 0x602F, 0x705C, 0x705D, 0x705E, 0xF05F, 
+	0x7060, 0x7061, 0x7062, 0x6033, 0x7064, 0x7065, 0x7066, 0xF067, 
+	0x7068, 0x7069, 0x706A, 0x6037, 0x706C, 0x706D, 0x706E, 0xF06F, 
+	0x7070, 0x7071, 0x7072, 0x603B, 0x7074, 0x7075, 0x7076, 0xF077, 
+	0x7078, 0x7079, 0x707A, 0x603F, 0x607C, 0x607D, 0xF07E, 0xF07F, 
+	0x7180, 0x7181, 0x7182, 0x6143, 0x7184, 0x7185, 0x7186, 0xF187, 
+	0x7188, 0x7189, 0x718A, 0x6147, 0x718C, 0x718D, 0x718E, 0xF18F, 
+	0x7190, 0x7191, 0x7192, 0x614B, 0x7194, 0x7195, 0x7196, 0xF197, 
+	0x7198, 0x7199, 0x719A, 0x614F, 0x719C, 0x719D, 0x719E, 0xF19F, 
+	0x71A0, 0x71A1, 0x71A2, 0x6153, 0x71A4, 0x71A5, 0x71A6, 0xF1A7, 
+	0x71A8, 0x71A9, 0x71AA, 0x6157, 0x71AC, 0x71AD, 0x71AE, 0xF1AF, 
+	0x71B0, 0x71B1, 0x71B2, 0x615B, 0x71B4, 0x71B5, 0x71B6, 0xF1B7, 
+	0x71B8, 0x71B9, 0x71BA, 0x615F, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
+	0x72C0, 0x72C1, 0x72C2, 0x6263, 0x72C4, 0x72C5, 0x72C6, 0xF2C7, 
+	0x72C8, 0x72C9, 0x72CA, 0x6267, 0x72CC, 0x72CD, 0x72CE, 0xF2CF, 
+	0x72D0, 0x72D1, 0x72D2, 0x626B, 0x72D4, 0x72D5, 0x72D6, 0xF2D7, 
+	0x72D8, 0x72D9, 0x72DA, 0x626F, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, 
+	0x73E0, 0x73E1, 0x73E2, 0x6373, 0x73E4, 0x73E5, 0x73E6, 0xF3E7, 
+	0x73E8, 0x73E9, 0x73EA, 0x6377, 0x73EC, 0x73ED, 0x73EE, 0xF3EF, 
+	0x74F0, 0x74F1, 0x74F2, 0x647B, 0x74F4, 0x74F5, 0x74F6, 0xF4F7, 
+	0x75F8, 0x75F9, 0x75FA, 0x657F, 0xF6FC, 0xF6FD, 0xF7FE, 0xFBFF, 
+};
+
+
+static WORD destuff4[] =
+{
+	0x7000, 0x6001, 0x7002, 0xF003, 0x7004, 0x6003, 0x7006, 0xF007, 
+	0x7008, 0x6005, 0x700A, 0xF00B, 0x700C, 0x6007, 0x700E, 0xF00F, 
+	0x7010, 0x6009, 0x7012, 0xF013, 0x7014, 0x600B, 0x7016, 0xF017, 
+	0x7018, 0x600D, 0x701A, 0xF01B, 0x701C, 0x600F, 0x701E, 0xF01F, 
+	0x7020, 0x6011, 0x7022, 0xF023, 0x7024, 0x6013, 0x7026, 0xF027, 
+	0x7028, 0x6015, 0x702A, 0xF02B, 0x702C, 0x6017, 0x702E, 0xF02F, 
+	0x7030, 0x6019, 0x7032, 0xF033, 0x7034, 0x601B, 0x7036, 0xF037, 
+	0x7038, 0x601D, 0x703A, 0xF03B, 0x703C, 0x601F, 0x603E, 0xF03F, 
+	0x7040, 0x6021, 0x7042, 0xF043, 0x7044, 0x6023, 0x7046, 0xF047, 
+	0x7048, 0x6025, 0x704A, 0xF04B, 0x704C, 0x6027, 0x704E, 0xF04F, 
+	0x7050, 0x6029, 0x7052, 0xF053, 0x7054, 0x602B, 0x7056, 0xF057, 
+	0x7058, 0x602D, 0x705A, 0xF05B, 0x705C, 0x602F, 0x705E, 0xF05F, 
+	0x7060, 0x6031, 0x7062, 0xF063, 0x7064, 0x6033, 0x7066, 0xF067, 
+	0x7068, 0x6035, 0x706A, 0xF06B, 0x706C, 0x6037, 0x706E, 0xF06F, 
+	0x7070, 0x6039, 0x7072, 0xF073, 0x7074, 0x603B, 0x7076, 0xF077, 
+	0x7078, 0x603D, 0x707A, 0xF07B, 0x607C, 0x503F, 0xF07E, 0xF07F, 
+	0x7180, 0x6141, 0x7182, 0xF183, 0x7184, 0x6143, 0x7186, 0xF187, 
+	0x7188, 0x6145, 0x718A, 0xF18B, 0x718C, 0x6147, 0x718E, 0xF18F, 
+	0x7190, 0x6149, 0x7192, 0xF193, 0x7194, 0x614B, 0x7196, 0xF197, 
+	0x7198, 0x614D, 0x719A, 0xF19B, 0x719C, 0x614F, 0x719E, 0xF19F, 
+	0x71A0, 0x6151, 0x71A2, 0xF1A3, 0x71A4, 0x6153, 0x71A6, 0xF1A7, 
+	0x71A8, 0x6155, 0x71AA, 0xF1AB, 0x71AC, 0x6157, 0x71AE, 0xF1AF, 
+	0x71B0, 0x6159, 0x71B2, 0xF1B3, 0x71B4, 0x615B, 0x71B6, 0xF1B7, 
+	0x71B8, 0x615D, 0x71BA, 0xF1BB, 0x71BC, 0x615F, 0x617E, 0xF1BF, 
+	0x72C0, 0x6261, 0x72C2, 0xF2C3, 0x72C4, 0x6263, 0x72C6, 0xF2C7, 
+	0x72C8, 0x6265, 0x72CA, 0xF2CB, 0x72CC, 0x6267, 0x72CE, 0xF2CF, 
+	0x72D0, 0x6269, 0x72D2, 0xF2D3, 0x72D4, 0x626B, 0x72D6, 0xF2D7, 
+	0x72D8, 0x626D, 0x72DA, 0xF2DB, 0x72DC, 0x626F, 0x72DE, 0xF2DF, 
+	0x73E0, 0x6371, 0x73E2, 0xF3E3, 0x73E4, 0x6373, 0x73E6, 0xF3E7, 
+	0x73E8, 0x6375, 0x73EA, 0xF3EB, 0x73EC, 0x6377, 0x73EE, 0xF3EF, 
+	0x74F0, 0x6479, 0x74F2, 0xF4F3, 0x74F4, 0x647B, 0x74F6, 0xF4F7, 
+	0x75F8, 0x657D, 0x75FA, 0xF5FB, 0xF6FC, 0xE67F, 0xF7FE, 0xFCFF, 
+};
+
+
+static WORD destuff5[] =
+{
+	0x6000, 0xF001, 0x6001, 0xF003, 0x6002, 0xF005, 0x6003, 0xF007, 
+	0x6004, 0xF009, 0x6005, 0xF00B, 0x6006, 0xF00D, 0x6007, 0xF00F, 
+	0x6008, 0xF011, 0x6009, 0xF013, 0x600A, 0xF015, 0x600B, 0xF017, 
+	0x600C, 0xF019, 0x600D, 0xF01B, 0x600E, 0xF01D, 0x600F, 0xF01F, 
+	0x6010, 0xF021, 0x6011, 0xF023, 0x6012, 0xF025, 0x6013, 0xF027, 
+	0x6014, 0xF029, 0x6015, 0xF02B, 0x6016, 0xF02D, 0x6017, 0xF02F, 
+	0x6018, 0xF031, 0x6019, 0xF033, 0x601A, 0xF035, 0x601B, 0xF037, 
+	0x601C, 0xF039, 0x601D, 0xF03B, 0x601E, 0xF03D, 0x501F, 0xF03F, 
+	0x6020, 0xF041, 0x6021, 0xF043, 0x6022, 0xF045, 0x6023, 0xF047, 
+	0x6024, 0xF049, 0x6025, 0xF04B, 0x6026, 0xF04D, 0x6027, 0xF04F, 
+	0x6028, 0xF051, 0x6029, 0xF053, 0x602A, 0xF055, 0x602B, 0xF057, 
+	0x602C, 0xF059, 0x602D, 0xF05B, 0x602E, 0xF05D, 0x602F, 0xF05F, 
+	0x6030, 0xF061, 0x6031, 0xF063, 0x6032, 0xF065, 0x6033, 0xF067, 
+	0x6034, 0xF069, 0x6035, 0xF06B, 0x6036, 0xF06D, 0x6037, 0xF06F, 
+	0x6038, 0xF071, 0x6039, 0xF073, 0x603A, 0xF075, 0x603B, 0xF077, 
+	0x603C, 0xF079, 0x603D, 0xF07B, 0x503E, 0xE07D, 0xE03F, 0xF07F, 
+	0x6140, 0xF181, 0x6141, 0xF183, 0x6142, 0xF185, 0x6143, 0xF187, 
+	0x6144, 0xF189, 0x6145, 0xF18B, 0x6146, 0xF18D, 0x6147, 0xF18F, 
+	0x6148, 0xF191, 0x6149, 0xF193, 0x614A, 0xF195, 0x614B, 0xF197, 
+	0x614C, 0xF199, 0x614D, 0xF19B, 0x614E, 0xF19D, 0x614F, 0xF19F, 
+	0x6150, 0xF1A1, 0x6151, 0xF1A3, 0x6152, 0xF1A5, 0x6153, 0xF1A7, 
+	0x6154, 0xF1A9, 0x6155, 0xF1AB, 0x6156, 0xF1AD, 0x6157, 0xF1AF, 
+	0x6158, 0xF1B1, 0x6159, 0xF1B3, 0x615A, 0xF1B5, 0x615B, 0xF1B7, 
+	0x615C, 0xF1B9, 0x615D, 0xF1BB, 0x615E, 0xF1BD, 0x513F, 0xF1BF, 
+	0x6260, 0xF2C1, 0x6261, 0xF2C3, 0x6262, 0xF2C5, 0x6263, 0xF2C7, 
+	0x6264, 0xF2C9, 0x6265, 0xF2CB, 0x6266, 0xF2CD, 0x6267, 0xF2CF, 
+	0x6268, 0xF2D1, 0x6269, 0xF2D3, 0x626A, 0xF2D5, 0x626B, 0xF2D7, 
+	0x626C, 0xF2D9, 0x626D, 0xF2DB, 0x626E, 0xF2DD, 0x626F, 0xF2DF, 
+	0x6370, 0xF3E1, 0x6371, 0xF3E3, 0x6372, 0xF3E5, 0x6373, 0xF3E7, 
+	0x6374, 0xF3E9, 0x6375, 0xF3EB, 0x6376, 0xF3ED, 0x6377, 0xF3EF, 
+	0x6478, 0xF4F1, 0x6479, 0xF4F3, 0x647A, 0xF4F5, 0x647B, 0xF4F7, 
+	0x657C, 0xF5F9, 0x657D, 0xF5FB, 0xE67E, 0xF6FD, 0xE77F, 0xFDFF, 
+};
+
+
+static WORD * stuffs[] = { stuff0, stuff1, stuff2, stuff3, stuff4, stuff5 };
+WORD * destuffs[] = { destuff0, destuff1, destuff2, destuff3, destuff4, destuff5 };
+
+
+/*- AuverTech Telecom -------------------------------------------------------+
+ |                                                                           |
+ | @Function  : hdlc_encode                                                  |
+ | @Author    : Cyrille Boudon                                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------+
+ |                                                                           |
+ | @Param     : BYTE *pbyBuffIn        IN,    array of bytes to encode       |
+ | @Param     : BYTE *pbyBuffOut       OUT,   array of bytes encoded         |
+ | @Param     : DWORD *pdwInitialShift INOUT, initial shift                  |
+ | @Param     : DWORD dwLength         IN,    count of bytes to encode       |
+ |                                                                           |
+ | @Return    : DWORD                  count of bytes encoded                |
+ |                                                                           |
+ +------------------------------- @Abstract ---------------------------------+
+ |                                                                           |
+ | Bit stuffing of thz array pbyBuffIn with the insertion of a flag at the   |
+ | beginning and the end, using the initial shift (due to the emission of    |
+ | previous frames). The last byte can be used to insert flags (by outputting|
+ | the flag N times) before the next frame. The initial shift is updated at  |
+ | the end of the algorithm for the next frame. Its signification is: for the|
+ | flags shifted like  "1100111111001111" *pdwInitialShift = 3. At the       |
+ | beginning (for the first frame), the shift must be initialized to 0.      |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+DWORD hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut,
+		  DWORD *pdwInitialShift, DWORD dwLength)
+{
+	DWORD	dwShifter;     // temporary variable
+	DWORD	dwShiftNb;     // shift due to the insertion of '0'
+	DWORD	dwState;       // count of '1' at the end of the current byte
+	DWORD	dwNb;          // length of the encoded array
+	BYTE	byCarry;       // carry due to the shift
+	BYTE	byNewCarry;    // temporary variable
+	BYTE	byCharIn;      // byte being encoded
+	BYTE	byCarryMSB;    // lost bit of the carry if dwShiftNb=7 and 2 '0' inserted
+	WORD	woDecal;       // temporary variable
+	WORD	woInfo;        // data read in the arrays
+	BOOL	bContinue;     // true until the two last bytes
+	BOOL	bContinue2;    // true until the last byte
+
+	bContinue = TRUE;
+	bContinue2 = TRUE;
+	dwShiftNb = 0;
+	byCarry = 0;
+	dwState = 0;
+	woDecal = 0x7E;
+	byCarryMSB = 0xFF;
+	dwNb = 1; // length to 1 to account for the first flag
+	
+	/*-----------------------------
+	 | insert the flag using the
+	 | shift given by
+	 | *pdwInitialShift)
+	 +-----------------------------*/
+	* pbyBuffOut ++ = 0x7E7E >> *pdwInitialShift;
+
+	/*-----------------------------
+	 | main loop
+	 +-----------------------------*/
+	while (dwLength--)
+	{
+		byCharIn = *pbyBuffIn ++;
+		
+/*-----------------------------
+ | go back here to treat the
+ | carry when its length
+ | is over 7 and for the first
+ | byte (with flag)
+ +-----------------------------*/
+carry:
+
+		dwNb ++;
+
+		/*-----------------------------
+		 | shift the byte to get the
+		 | byte to encode (without
+		 | taking into account the
+		 | initial shift)
+		 +-----------------------------*/
+		if (dwShiftNb)
+		{
+			dwShifter = byCharIn << dwShiftNb;
+			byNewCarry = dwShifter >> 8;
+			byCharIn = dwShifter | byCarry;
+			byCarry = byNewCarry;
+		}
+
+		/*-----------------------------
+		 | get the data from the arrays
+		 | and take into account the
+		 | initial shift for the byte
+		 | to encode
+		 +-----------------------------*/
+		woInfo = stuffs[dwState][byCharIn];
+		woDecal |= (woInfo & 0x00FF) << 8;
+		* pbyBuffOut ++ = woDecal >> *pdwInitialShift;
+		woDecal = woInfo & 0x00FF;
+		dwState = woInfo >> 12;
+
+		/*-----------------------------
+		 | treat the lost bit if we had
+		 | a carry overflow
+		 +-----------------------------*/
+		if (byCarryMSB != 0xFF)
+		{
+			if (!dwShiftNb)
+			{
+				if(byCarryMSB)
+					byCarry = 1;
+				dwShiftNb = 1;
+			}
+			byCarryMSB = 0xFF;
+		}
+
+		/*-----------------------------
+		 | if one '0' get inserted, we
+		 | have to calculate the new
+		 | carry and the new shift
+		 +-----------------------------*/
+		if (woInfo & 0x0F00)
+		{
+			byCarryMSB = byCarry & 0x40;
+			byCarry <<= (woInfo & 0x0C00) >> 10;
+			byCarry |= (woInfo & 0x0300) >> 8;
+			dwShiftNb += (woInfo & 0x0C00) >> 10;
+		}
+
+		/*-----------------------------
+		 | if the carry is a whole byte
+		 | we use it as a byte to encode
+		 +-----------------------------*/
+		if (dwShiftNb > 7)
+		{
+			if (dwShiftNb == 8)
+				byCarryMSB = 0xFF;
+			dwShiftNb = 0;
+			byCharIn = byCarry;
+			byCarry = 0;
+			goto carry;
+		}
+
+		/*-----------------------------
+		 | at the end of the array
+		 +-----------------------------*/
+		if (!dwLength)
+		{
+			/*-----------------------------
+			 | take into account the bits
+			 | set in the carry
+			 +-----------------------------*/
+			if (bContinue)
+			{
+				bContinue = FALSE;
+				byCharIn = 0;
+				goto carry;
+			}
+			
+			/*-----------------------------
+			 | treat the last byte if we
+			 | had a carry overflow
+			 +-----------------------------*/
+			if (bContinue2 && ((8 - *pdwInitialShift) + dwShiftNb) > 7)
+			{
+				bContinue2 = FALSE;
+				byCharIn = 0;
+				goto carry;
+			}
+
+			/*-----------------------------
+			 | Calculate the new shift
+			 +-----------------------------*/
+			*pdwInitialShift = ((8 - *pdwInitialShift) + dwShiftNb)%8;
+
+			/*-----------------------------
+			 | Add a flag at the end of the
+			 | carry and a full flag
+			 +-----------------------------*/
+			pbyBuffOut--;
+			*pbyBuffOut++ |= 0x7E << *pdwInitialShift;
+			byCarry = 0x7E7E >> (8 - *pdwInitialShift);
+			*pbyBuffOut++ = byCarry;
+			*pbyBuffOut++ = byCarry;
+			dwNb += 2;
+		}
+	}
+
+	/*-------------------------------
+	 | Pad the array to a multiple
+	 | of 64 bytes.
+	 +-------------------------------*/
+	for(;dwNb%64;dwNb++)
+		*pbyBuffOut ++ = byCarry;
+
+	*pdwInitialShift = (8 - *pdwInitialShift)%8;
+
+	return dwNb;
+}
+
+
+
+/*- AuverTech Telecom -------------------------------------------------------+
+ |                                                                           |
+ | @Function  : hdlc_decode                                                  |
+ | @Author    : Cyrille Boudon                                               |
+ |                                                                           |
+ +---------------------------------------------------------------------------+
+ |                                                                           |
+ | @Param     : BYTE * pbyBuffIn  IN,  array of bytes to decode              |
+ | @Param     : BYTE * pbyBuffOut OUT, array of decoded bytes                |
+ | @Param     : DWORD dwLength    IN,  count of bytes to decode              |
+ |                                                                           |
+ | @Return    : DWORD             count of decoded bytes                     |
+ |                                                                           |
+ +------------------------------- @Abstract ---------------------------------+
+ |                                                                           |
+ | Bit de-stuffing of the array pbyBuffIn. There has to be at least 1 full   |
+ | flag at the beginning. At the end there has to be a flag or an abort (more|
+ | than 6 consecutive '1').                                                  |
+ | If an abort is encountered, the returned count is '0'.                    |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+DWORD hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength)
+{
+	BYTE	byCharIn;    // byte being decoded
+	BYTE	byCarry;     // current carry
+	WORD	woInfo;      // data read in the arrays
+	WORD	woNb1;       // count of '1' at the end of the previous byte
+	BYTE	byShift;     // shift of the first flag
+	DWORD	dwInit;      // temporary variable
+	DWORD	dwLengthOut; // count of the decoded bytes
+	BYTE	byLgCarry;   // count of used bits in the carry
+	BYTE	byLgByte;    // count of used bits in the decoded byte
+
+	/*-----------------------------
+	 | Find the 1st flag. At the end
+	 | of the loop dwShift is the count
+	 | of bits to reach the 1st bit
+	 | of the 1st flag.
+	 +-----------------------------*/
+	dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8) | (*(pbyBuffIn+2)<<16);
+	for (byShift=0;byShift<17;byShift++)
+	{
+		if (!(((dwInit>>byShift)&0xFF)^0x7E))
+		{
+			break;
+		}
+	}
+
+	/*-----------------------------
+	 | If at the end of the previous
+	 | loop dwShift = 17, it means
+	 | that no flag was found in the
+	 | first 3 bytes (normally
+	 | impossible impossible with the
+	 | DSP algorithm)
+	 +-----------------------------*/
+	if (byShift == 17)
+		return 0;
+
+	/*-----------------------------
+	 | Plase the array pointer after
+	 | the first flag. Update the
+	 | shift.
+	 +-----------------------------*/
+	pbyBuffIn += byShift/8 + 1;
+	dwLength -= byShift/8 + 1;
+	byShift %= 8;
+	
+	/*-----------------------------
+	 | Walk through the frame to
+	 | find the first data byte
+	 +-----------------------------*/
+	dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
+	while (!(((dwInit>>byShift)&0xFF)^0x7E))
+	{
+		pbyBuffIn ++;
+		dwLength --;
+		dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
+	}
+
+	dwLengthOut = 0;
+	byCarry = 0;
+	byLgCarry = 0;
+	byLgByte = 0;
+
+	/*-------------------------------
+	 | Treat the first byte
+	 +-------------------------------*/	
+	byCharIn = (*pbyBuffIn >> byShift) << byShift;
+	woInfo = destuffs[0][byCharIn];
+	byLgByte = ((woInfo & 0x7000) >> 12) + 1;
+	woNb1 = (woInfo & 0x0F00) >> 8;
+	dwLength --;
+	pbyBuffIn++;
+
+	if (woNb1 > 5)
+		return 0;
+
+	if (byLgByte - byShift == 8)
+	{
+		*pbyBuffOut ++ = woInfo;
+		dwLengthOut ++;
+	}
+	else
+	{
+		byCarry = woInfo << (8 - byLgByte);
+		byLgCarry = byLgByte - byShift;
+	}
+
+	/*-------------------------------
+	 | main loop
+	 +-------------------------------*/
+	while(dwLength --)
+	{
+		byCharIn = *pbyBuffIn ++;
+
+		woInfo = destuffs[woNb1][byCharIn];
+		byLgByte = ((woInfo & 0x7000) >> 12) + 1;
+		
+		/*-------------------------------
+		 | if the used bits in the carry
+		 | and the current byte makes
+		 | possible to output a full byte
+		 +-------------------------------*/
+		if (byLgByte + byLgCarry >= 8)
+		{
+			*pbyBuffOut ++ = ( (woInfo << 8) | byCarry) >> (8 - byLgCarry);
+			dwLengthOut ++;
+			byLgCarry += byLgByte - 8;
+			byCarry = woInfo << (8-byLgByte);
+		}
+		/*-------------------------------
+		 | if the used bits in the carry
+		 | and the current byte doesn't
+		 | make possible to output a full 
+		 | byte
+		 +-------------------------------*/
+		else
+		{
+			dwInit = (woInfo << 8) | byCarry;
+			byLgCarry += byLgByte;
+			byCarry = dwInit >> byLgByte;
+		}
+
+		woNb1 = (woInfo & 0x0F00) >> 8;
+
+		/*-------------------------------
+		 | if the current byte contains
+		 | six or more consecutive '1'
+		 +-------------------------------*/
+		if (woInfo & 0x8000)
+		{
+			byCarry = ((byCharIn << 8) | *(pbyBuffIn-2)) >> (8 - byLgCarry);
+			if (byCarry == 0x7E)
+				return dwLengthOut-1;
+			else
+				if (woNb1 > 6)
+					return 0;
+				else
+					if ((!(*pbyBuffIn & 1)) && (byLgCarry == 7))
+						return dwLengthOut;
+					else
+						return 0;
+		}
+	}
+
+	return dwLengthOut;
+}
+
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_main.c linux/drivers/isdn/tpam/tpam_main.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_main.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_main.c	Mon Dec  3 22:50:38 2001
@@ -0,0 +1,289 @@
+/* $Id: tpam_main.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+#include "tpam.h"
+
+/* Local functions prototypes */
+static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
+static void __devexit tpam_unregister_card(tpam_card *);
+static void __devexit tpam_remove(struct pci_dev *);
+static int __init tpam_init(void);
+static void __exit tpam_exit(void);
+
+/* List of boards */
+static tpam_card *cards; /* = NULL; */
+/* Number of cards */
+static int cards_num;
+/* Configurable id of the driver */
+static char *id = "tpam\0\0\0\0\0\0\0\0\0\0\0\0";
+
+MODULE_DESCRIPTION("Driver for TurboPAM cards");
+MODULE_AUTHOR("Stelian Pop, Alcove");
+MODULE_SUPPORTED_DEVICE("ISDN subsystem");
+MODULE_PARM_DESC(id,"ID-String of the driver");
+MODULE_PARM(id,"s");
+
+/*
+ * Finds a board by its driver ID.
+ *
+ * 	driverId: driver ID (as referenced by the IDSN link layer)
+ *
+ * Return: the tpam_card structure if found, NULL on error.
+ */
+tpam_card *tpam_findcard(int driverid) {
+	tpam_card *p = cards;
+
+	while (p) {
+		if (p->id == driverid)
+			return p;
+		p = p->next;
+	}
+	return NULL;
+}
+
+/*
+ * Finds a channel number by its ncoid.
+ *
+ * 	card: the board
+ * 	ncoid: the NCO id
+ *
+ * Return: the channel number if found, TPAM_CHANNEL_INVALID if not.
+ */
+u32 tpam_findchannel(tpam_card *card, u32 ncoid) {
+	int i;
+
+	for (i = 0; i < TPAM_NBCHANNEL; ++i)
+		if (card->channels[i].ncoid == ncoid)
+			return card->channels[i].num;
+	return TPAM_CHANNEL_INVALID;
+}
+
+/*
+ * Initializes and registers a new TurboPAM card.
+ *
+ * 	dev: the PCI device
+ * 	num: the board number
+ *
+ * Return: 0 if OK, <0 if error
+ */
+static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
+	tpam_card *card, *c;
+	int i;
+
+	/* allocate memory for the board structure */
+	if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
+		printk(KERN_ERR "TurboPAM: tpam_register_card: "
+		       "kmalloc failed!\n");
+		return -ENOMEM;
+	}
+
+	memset((char *)card, 0, sizeof(tpam_card));
+
+	card->irq = dev->irq;
+	card->lock = SPIN_LOCK_UNLOCKED;
+	sprintf(card->interface.id, "%s%d", id, cards_num);
+
+	/* request interrupt */
+	if (request_irq(card->irq, &tpam_irq, SA_INTERRUPT | SA_SHIRQ, 
+			card->interface.id, card)) {
+		printk(KERN_ERR "TurboPAM: tpam_register_card: "
+		       "could not request irq %d\n", card->irq);
+		kfree(card);
+		return -EIO;
+	}
+
+	/* remap board memory */
+	if (!(card->bar0 = (unsigned long) ioremap(pci_resource_start(dev, 0),
+						   0x800000))) {
+		printk(KERN_ERR "TurboPAM: tpam_register_card: "
+		       "unable to remap bar0\n");
+		free_irq(card->irq, card);
+		kfree(card);
+		return -EIO;
+	}
+
+	/* reset the board */
+	readl(card->bar0 + TPAM_RESETPAM_REGISTER);
+
+	/* initialisation magic :-( */
+	copy_to_pam_dword(card, (void *)0x01800008, 0x00000030);
+	copy_to_pam_dword(card, (void *)0x01800010, 0x00000030);
+	copy_to_pam_dword(card, (void *)0x01800014, 0x42240822);
+	copy_to_pam_dword(card, (void *)0x01800018, 0x07114000);
+	copy_to_pam_dword(card, (void *)0x0180001c, 0x00000400);
+	copy_to_pam_dword(card, (void *)0x01840070, 0x00000010);
+
+	/* fill the ISDN link layer structure */
+	card->interface.channels = TPAM_NBCHANNEL;
+	card->interface.maxbufsize = TPAM_MAXBUFSIZE;
+	card->interface.features = 
+		ISDN_FEATURE_P_EURO |
+		ISDN_FEATURE_L2_HDLC |
+		ISDN_FEATURE_L2_MODEM;
+	card->interface.hl_hdrlen = 0;
+	card->interface.command = tpam_command;
+	card->interface.writebuf_skb = tpam_writebuf_skb;
+	card->interface.writecmd = NULL;
+	card->interface.readstat = NULL;
+
+	/* register wrt the ISDN link layer */
+	if (!register_isdn(&card->interface)) {
+		printk(KERN_ERR "TurboPAM: tpam_register_card: "
+		       "unable to register %s\n", card->interface.id);
+		free_irq(card->irq, card);
+		iounmap((void *)card->bar0);
+		kfree(card);
+		return -EIO;
+	}
+	card->id = card->interface.channels;
+
+	/* initialize all channels */
+	for (i = 0; i < TPAM_NBCHANNEL; ++i) {
+		card->channels[i].num = i;
+		card->channels[i].card = card;
+		card->channels[i].ncoid = TPAM_NCOID_INVALID;
+		card->channels[i].hdlc = 0;
+		card->channels[i].realhdlc = 0;
+		card->channels[i].hdlcshift = 0;
+		skb_queue_head_init(&card->channels[i].sendq);
+	}
+
+	/* initialize the rest of board structure */
+	card->channels_used = 0;
+	card->channels_tested = 0;
+	card->running = 0;
+	card->busy = 0;
+	card->roundrobin = 0;
+	card->loopmode = 0;
+	skb_queue_head_init(&card->sendq);
+	skb_queue_head_init(&card->recvq);
+	card->recv_tq.routine = (void *) (void *) tpam_recv_tq;
+	card->recv_tq.data = card;
+	card->send_tq.routine = (void *) (void *) tpam_send_tq;
+	card->send_tq.data = card;
+
+	/* add the board at the end of the list of boards */
+	card->next = NULL;
+	if (cards) {
+		c = cards;
+		while (c->next)
+			c = c->next;
+		c->next = card;
+	}
+	else
+		cards = card;
+
+	++cards_num;
+	pci_set_drvdata(dev, card);
+
+	return 0;
+}
+
+/*
+ * Unregisters a TurboPAM board by releasing all its ressources (irq, mem etc).
+ *
+ * 	card: the board.
+ */
+static void __devexit tpam_unregister_card(tpam_card *card) {
+	isdn_ctrl cmd;
+
+	/* prevent the ISDN link layer that the driver will be unloaded */
+	cmd.command = ISDN_STAT_UNLOAD;
+	cmd.driver = card->id;
+	(* card->interface.statcallb)(&cmd);
+
+	/* release interrupt */
+	free_irq(card->irq, card);
+
+	/* release mapped memory */
+	iounmap((void *)card->bar0);
+}
+
+/*
+ * Stops the driver.
+ */
+static void __devexit tpam_remove(struct pci_dev *pcidev) {
+	tpam_card *card = pci_get_drvdata(pcidev);
+	tpam_card *c;
+
+	/* remove from the list of cards */
+	if (card == cards)
+		cards = cards->next;
+	else {
+		c = cards;
+		while (c->next != card) 
+			c = c->next;
+		c->next = c->next->next;
+	}
+	
+	/* unregister each board */
+	tpam_unregister_card(card);
+	
+	/* and free the board structure itself */
+	kfree(card);
+}
+
+static struct pci_device_id tpam_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_TURBOPAM,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, tpam_pci_tbl);
+
+static struct pci_driver tpam_driver = {
+	name:		"tpam",
+	id_table:	tpam_pci_tbl,
+	probe:		tpam_probe,
+	remove:		tpam_remove,
+};
+
+static int __init tpam_init(void) {
+	int ret;
+	
+	ret = pci_module_init(&tpam_driver);
+	if (ret)
+		return ret;
+	printk(KERN_INFO "TurboPAM: %d card%s found, driver loaded.\n", 
+	       cards_num, (cards_num > 1) ? "s" : "");
+	return 0;
+}
+
+static void __exit tpam_exit(void) {
+	pci_unregister_driver(&tpam_driver);
+	printk(KERN_INFO "TurboPAM: driver unloaded\n");
+}
+
+/* Module entry points */
+module_init(tpam_init);
+module_exit(tpam_exit);
+
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_memory.c linux/drivers/isdn/tpam/tpam_memory.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_memory.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_memory.c	Mon Dec  3 22:50:38 2001
@@ -0,0 +1,258 @@
+/* $Id: tpam_memory.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "tpam.h"
+
+/*
+ * Write a DWORD into the board memory.
+ *
+ * 	card: the board
+ * 	addr: the address (in the board memory)
+ * 	val: the value to put into the memory.
+ */
+void copy_to_pam_dword(tpam_card *card, const void *addr, u32 val) {
+
+	/* set the page register */
+	writel(((unsigned long)addr) | TPAM_PAGE_SIZE, 
+	       card->bar0 + TPAM_PAGE_REGISTER);
+
+	/* write the value */
+	writel(val, card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE));
+}
+
+/*
+ * Write n bytes into the board memory. The count of bytes will be rounded
+ * up to a multiple of 4.
+ *
+ * 	card: the board
+ * 	to: the destination address (in the board memory)
+ * 	from: the source address (in the kernel memory)
+ * 	n: number of bytes
+ */
+void copy_to_pam(tpam_card *card, void *to, const void *from, u32 n) {
+	u32 page, offset, count;
+
+	/* need to write in dword ! */
+	while (n & 3) n++;
+
+	while (n) {
+		page = ((u32)to) | TPAM_PAGE_SIZE;
+		offset = ((u32)to) & TPAM_PAGE_SIZE;
+		count = n < TPAM_PAGE_SIZE - offset
+				? n
+				: TPAM_PAGE_SIZE - offset;
+
+		/* set the page register */
+		writel(page, card->bar0 + TPAM_PAGE_REGISTER);
+
+		/* copy the data */
+		memcpy_toio((void *)(card->bar0 + offset), from, count);
+		
+		from += count;
+		to += count;
+		n -= count;
+	}
+}
+
+/*
+ * Read a DWORD from the board memory.
+ *
+ * 	card: the board
+ * 	addr: the address (in the board memory)
+ *
+ * Return: the value read into the memory.
+ */
+u32 copy_from_pam_dword(tpam_card *card, const void *addr) {
+
+	/* set the page register */
+	writel(((u32)addr) | TPAM_PAGE_SIZE, 
+	       card->bar0 + TPAM_PAGE_REGISTER);
+
+	/* read the data */
+	return readl(card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE));
+}
+
+/*
+ * Read n bytes from the board memory.
+ *
+ * 	card: the board
+ * 	to: the destination address (in the kernel memory)
+ * 	from: the source address (in the board memory)
+ * 	n: number of bytes
+ */
+void copy_from_pam(tpam_card *card, void *to, const void *from, u32 n) {
+	u32 page, offset, count;
+
+	while (n) {
+		page = ((u32)from) | TPAM_PAGE_SIZE;
+		offset = ((u32)from) & TPAM_PAGE_SIZE;
+		count = n < TPAM_PAGE_SIZE - offset 
+				? n 
+				: TPAM_PAGE_SIZE - offset;
+
+		/* set the page register */
+		writel(page, card->bar0 + TPAM_PAGE_REGISTER);
+
+		/* read the data */
+		memcpy_fromio(to, (void *)(card->bar0 + offset), count);
+		
+		from += count;
+		to += count;
+		n -= count;
+	}
+}
+
+/*
+ * Read n bytes from the board memory and writes them into the user memory.
+ *
+ * 	card: the board
+ * 	to: the destination address (in the userspace memory)
+ * 	from: the source address (in the board memory)
+ * 	n: number of bytes
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int copy_from_pam_to_user(tpam_card *card, void *to, const void *from, u32 n) {
+	void *page;
+	u32 count;
+
+	/* allocate a free page for the data transfer */
+	if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
+		printk(KERN_ERR "TurboPAM(copy_from_pam_to_user): "
+		       "get_free_page failed\n");
+		return -ENOMEM;
+	}
+
+	while (n) {
+		count = n < PAGE_SIZE ? n : PAGE_SIZE;
+
+		/* copy data from the board into the kernel memory */
+		spin_lock_irq(&card->lock);
+		copy_from_pam(card, page, from, count);
+		spin_unlock_irq(&card->lock);
+
+		/* copy it from the kernel memory into the user memory */
+		if (copy_to_user(to, page, count)) {
+			
+			/* this can fail... */
+			free_page((u32)page);
+			return -EFAULT;
+		}
+		from += count;
+		to += count;
+		n -= count;
+	}
+
+	/* release allocated memory */
+	free_page((u32)page);
+	return 0;
+}
+
+/*
+ * Read n bytes from the user memory and writes them into the board memory.
+ *
+ * 	card: the board
+ * 	to: the destination address (in the board memory)
+ * 	from: the source address (in the userspace memory)
+ * 	n: number of bytes
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int copy_from_user_to_pam(tpam_card *card, void *to, const void *from, u32 n) {
+	void *page;
+	u32 count;
+
+	/* allocate a free page for the data transfer */
+	if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
+		printk(KERN_ERR "TurboPAM(copy_from_user_to_pam): "
+		       "get_free_page failed\n");
+		return -ENOMEM;
+	}
+
+	while (n) {
+		count = n < PAGE_SIZE ? n : PAGE_SIZE;
+
+		/* copy data from the user memory into the kernel memory */
+		if (copy_from_user(page, from, count)) {
+			/* this can fail... */
+			free_page((u32)page);
+			return -EFAULT;
+		}
+
+		/* copy it from the kernel memory into the board memory */
+		spin_lock_irq(&card->lock);
+		copy_to_pam(card, to, page, count);
+		spin_unlock_irq(&card->lock);
+
+		from += count;
+		to += count;
+		n -= count;
+	}
+
+	/* release allocated memory */
+	free_page((u32)page);
+	return 0;
+}
+
+/*
+ * Verify if we have the permission to read or writes len bytes at the
+ * address address from/to the board memory.
+ *
+ * 	address: the start address (in the board memory)
+ * 	len: number of bytes
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int tpam_verify_area(u32 address, u32 len) {
+
+	if (address < TPAM_RESERVEDAREA1_START)
+		return (address + len <= TPAM_RESERVEDAREA1_START) ? 0 : -1;
+
+	if (address <= TPAM_RESERVEDAREA1_END)
+		return -1;
+
+	if (address < TPAM_RESERVEDAREA2_START)
+		return (address + len <= TPAM_RESERVEDAREA2_START) ? 0 : -1;
+
+	if (address <= TPAM_RESERVEDAREA2_END)
+		return -1;
+
+	if (address < TPAM_RESERVEDAREA3_START)
+		return (address + len <= TPAM_RESERVEDAREA3_START) ? 0 : -1;
+
+	if (address <= TPAM_RESERVEDAREA3_END)
+		return -1;
+
+	if (address < TPAM_RESERVEDAREA4_START)
+		return (address + len <= TPAM_RESERVEDAREA4_START) ? 0 : -1;
+
+	if (address <= TPAM_RESERVEDAREA4_END)
+		return -1;
+
+	return 0;
+}
+
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_nco.c linux/drivers/isdn/tpam/tpam_nco.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_nco.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_nco.c	Mon Dec  3 22:50:38 2001
@@ -0,0 +1,662 @@
+/* $Id: tpam_nco.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - Low Level NCO Manipulation)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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/config.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "tpam.h"
+
+/* Local function prototypes */
+static struct sk_buff *build_NCOpacket(u16, u16, u16, u16, u16);
+static int extract_NCOParameter(struct sk_buff *, u8, void *, u16);
+
+/*
+ * Build a NCO packet (PCI message).
+ *
+ * 	messageID: the message type (ID_*)
+ * 	size: size of the TLV block
+ * 	data_size: size of the data block
+ * 	ack: packet needs to send ack upon send
+ * 	ack_size: size of data to be acknowledged upon send
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+static struct sk_buff *build_NCOpacket(u16 messageID, u16 size, 
+				       u16 data_size, u16 ack, 
+				       u16 ack_size) {
+	struct sk_buff *skb;
+	skb_header *h;
+	pci_mpb *p;
+	u16 finalsize;
+
+	/* reserve enough space for the sk_buff header, the pci * header, 
+	 * size bytes for the TLV block, size bytes for the data and 4 more
+	 * bytes in order to make sure we can write dwords to the board. */
+	finalsize = sizeof(skb_header) + sizeof(pci_mpb) + size + data_size + 4;
+
+	/* allocate the sk_buff */
+	if (!(skb = alloc_skb(finalsize, GFP_ATOMIC))) {
+		printk(KERN_ERR "TurboPAM(make_NCOpacket): alloc_skb failed\n");
+		return NULL;
+	}
+
+	/* construct the skb_header */
+	h = (skb_header *)skb_put(skb, sizeof(skb_header));
+	h->size = sizeof(pci_mpb) + size;
+	h->data_size = data_size;
+	h->ack = ack;
+	h->ack_size = ack_size;
+
+	/* construct the pci_mpb */
+	p = (pci_mpb *)skb_put(skb, sizeof(pci_mpb));
+	p->exID = 0;
+	p->flags = 0;
+	p->errorCode = 0;
+	p->messageID = messageID;
+	p->maximumBlockTLVSize = MPB_MAXIMUMBLOCKTLVSIZE;
+	p->actualBlockTLVSize = size;
+	p->maximumDataSize = MPB_MAXIMUMDATASIZE;
+	p->actualDataSize = data_size;
+	return skb;
+}
+
+/*
+ * Build a ACreateNCOReq message.
+ *
+ * 	phone: the local phone number.
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_ACreateNCOReq(const u8 *phone) {
+	struct sk_buff *skb;
+	u8 *tlv;
+
+	dprintk("TurboPAM(build_ACreateNCOReq): phone=%s\n", phone);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_ACreateNCOReq, 23 + strlen(phone), 0, 0, 0))) 
+		return NULL;
+
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 3);
+	*tlv = PAR_NCOType; 
+	*(tlv+1) = 1;
+	*(tlv+2) = 5;	/* mistery value... */
+
+	tlv = (u8 *)skb_put(skb, 4);
+	*tlv = PAR_U3Protocol;
+	*(tlv+1) = 2;
+	*(tlv+2) = 4;	/* no level 3 protocol */
+	*(tlv+3) = 1;	/* HDLC in level 2 */
+
+	tlv = (u8 *)skb_put(skb, 3);
+	*tlv = PAR_Cdirection;
+	*(tlv+1) = 1;
+	*(tlv+2) = 3; /* PCI_DIRECTION_BOTH */
+
+	tlv = (u8 *)skb_put(skb, 3);
+	*tlv = PAR_Udirection;
+	*(tlv+1) = 1;
+	*(tlv+2) = 3; /* PCI_DIRECTION_BOTH */
+
+	tlv = (u8 *)skb_put(skb, 4);
+	*tlv = PAR_BearerCap;
+	*(tlv+1) = 2;
+	*(tlv+2) = 0x88;
+	*(tlv+3) = 0x90;
+
+	tlv = (u8 *)skb_put(skb, 6 + strlen(phone));
+	*tlv = PAR_CallingNumber;
+	*(tlv+1) = strlen(phone) + 4;
+	*(tlv+2) = 0x01; /* international */
+	*(tlv+3) = 0x01; /* isdn */
+	*(tlv+4) = 0x00;
+	*(tlv+5) = 0x00;
+	memcpy(tlv + 6, phone, strlen(phone));
+
+	return skb;
+}
+
+/*
+ * Build a ADestroyNCOReq message.
+ *
+ * 	ncoid: the NCO id.
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_ADestroyNCOReq(u32 ncoid) {
+	struct sk_buff *skb;
+	u8 *tlv;
+
+	dprintk("TurboPAM(build_ADestroyNCOReq): ncoid=%lu\n", 
+		(unsigned long)ncoid);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_ADestroyNCOReq, 6, 0, 0, 0)))
+		return NULL;
+	
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 6);
+	*tlv = PAR_NCOID;
+	*(tlv+1) = 4;
+	*((u32 *)(tlv+2)) = ncoid;
+
+	return skb;
+}
+
+/*
+ * Build a CConnectReq message.
+ *
+ * 	ncoid: the NCO id.
+ * 	called: the destination phone number
+ * 	hdlc: type of connection: 1 (HDLC) or 0(modem)
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_CConnectReq(u32 ncoid, const u8 *called, u8 hdlc) {
+	struct sk_buff *skb;
+	u8 *tlv;
+
+	dprintk("TurboPAM(build_CConnectReq): ncoid=%lu, called=%s, hdlc=%d\n",
+		(unsigned long)ncoid, called, hdlc);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_CConnectReq, 20 + strlen(called), 0, 0, 0)))
+		return NULL;
+	
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 6);
+	*tlv = PAR_NCOID;
+	*(tlv+1) = 4;
+	*((u32 *)(tlv+2)) = ncoid;
+
+	tlv = (u8 *)skb_put(skb, 4 + strlen(called));
+	*tlv = PAR_CalledNumber;
+	*(tlv+1) = strlen(called) + 2;
+	*(tlv+2) = 0x01; /* international */
+	*(tlv+3) = 0x01; /* isdn */
+	memcpy(tlv + 4, called, strlen(called));
+
+	tlv = (u8 *)skb_put(skb, 3);
+	*tlv = PAR_BearerCap;
+	*(tlv+1) = 1;
+	*(tlv+2) = hdlc ? 0x88 /* HDLC */ : 0x80 /* MODEM */;
+
+	tlv = (u8 *)skb_put(skb, 4);
+	*tlv = PAR_HLC;
+	*(tlv+1) = 2;
+	*(tlv+2) = 0x2;
+	*(tlv+3) = 0x7f;
+
+	tlv = (u8 *)skb_put(skb, 3);
+	*tlv = PAR_Facility;
+	*(tlv+1) = 1;
+	*(tlv+2) = 2;
+
+	return skb;
+}
+
+/*
+ * Build a CConnectRsp message.
+ *
+ * 	ncoid: the NCO id.
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_CConnectRsp(u32 ncoid) {
+	struct sk_buff *skb;
+	u8 *tlv;
+
+	dprintk("TurboPAM(build_CConnectRsp): ncoid=%lu\n",
+		(unsigned long)ncoid);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_CConnectRsp, 6, 0, 0, 0)))
+		return NULL;
+
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 6);
+	*tlv = PAR_NCOID;
+	*(tlv+1) = 4;
+	*((u32 *)(tlv+2)) = ncoid;
+
+	return skb;
+}
+
+/*
+ * Build a CDisconnectReq message.
+ *
+ * 	ncoid: the NCO id.
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_CDisconnectReq(u32 ncoid) {
+	struct sk_buff *skb;
+	u8 *tlv;
+
+	dprintk("TurboPAM(build_CDisconnectReq): ncoid=%lu\n",
+		(unsigned long)ncoid);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_CDisconnectReq, 6, 0, 0, 0)))
+		return NULL;
+
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 6);
+	*tlv = PAR_NCOID;
+	*(tlv+1) = 4;
+	*((u32 *)(tlv+2)) = ncoid;
+
+	return skb;
+}
+
+/*
+ * Build a CDisconnectRsp message.
+ *
+ * 	ncoid: the NCO id.
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_CDisconnectRsp(u32 ncoid) {
+	struct sk_buff *skb;
+	u8 *tlv;
+
+	dprintk("TurboPAM(build_CDisconnectRsp): ncoid=%lu\n",
+		(unsigned long)ncoid);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_CDisconnectRsp, 6, 0, 0, 0)))
+		return NULL;
+
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 6);
+	*tlv = PAR_NCOID;
+	*(tlv+1) = 4;
+	*((u32 *)(tlv+2)) = ncoid;
+
+	return skb;
+}
+
+/*
+ * Build a U3DataReq message.
+ *
+ * 	ncoid: the NCO id.
+ * 	data: the data to be send
+ * 	len: length of the data
+ * 	ack: send ack upon send
+ * 	ack_size: size of data to be acknowledged upon send
+ *
+ * Return: the sk_buff filled with the NCO packet, or NULL if error.
+ */
+struct sk_buff *build_U3DataReq(u32 ncoid, void *data, u16 len,
+				u16 ack, u16 ack_size) {
+	struct sk_buff *skb;
+	u8 *tlv;
+	void *p;
+
+	dprintk("TurboPAM(build_U3DataReq): "
+		"ncoid=%lu, len=%d, ack=%d, ack_size=%d\n", 
+		(unsigned long)ncoid, len, ack, ack_size);
+
+	/* build the NCO packet */
+	if (!(skb = build_NCOpacket(ID_U3DataReq, 6, len, ack, ack_size)))
+		return NULL;
+
+	/* add the parameters */
+	tlv = (u8 *)skb_put(skb, 6);
+	*tlv = PAR_NCOID;
+	*(tlv+1) = 4;
+	*((u32 *)(tlv+2)) = ncoid;
+
+	p = skb_put(skb, len);
+	memcpy(p, data, len);
+
+	return skb;
+}
+
+/*
+ * Extract a parameter from a TLV block.
+ *
+ * 	skb: sk_buff containing the PCI message
+ * 	type: parameter to search for (PARAM_*)
+ * 	value: to be filled with the value of the parameter
+ * 	len: maximum length of the parameter value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+static int extract_NCOParameter(struct sk_buff *skb, u8 type, 
+				void *value, u16 len) {
+	void *buffer = (void *)skb->data;
+	pci_mpb *p;
+	void * bufferend;
+	u8 valtype;
+	u16 vallen;
+
+	/* calculate the start and end of the TLV block */
+	buffer += sizeof(skb_header);
+	p = (pci_mpb *)buffer;
+	buffer += sizeof(pci_mpb);
+	bufferend = buffer + p->actualBlockTLVSize;
+
+	/* walk through the parameters */
+	while (buffer < bufferend) {
+
+		/* parameter type */
+		valtype = *((u8 *)buffer++);
+		/* parameter length */
+		vallen = *((u8 *)buffer++);
+		if (vallen == 0xff) {
+			/* parameter length is on 2 bytes */
+			vallen = *((u8 *)buffer++);
+			vallen <<= 8;
+			vallen |= *((u8 *)buffer++);
+		}
+		/* got the right parameter */
+		if (valtype == type) {
+			/* not enough space for returning the value */
+			if (vallen > len)
+				return -1;
+			/* OK, return it */
+			memcpy(value, buffer, vallen);
+			return 0;
+		}
+		buffer += vallen;
+	}
+	return -1;
+}
+
+/*
+ * Parse a ACreateNCOCnf message.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	status: to be filled with the status field value
+ * 	ncoid: to be filled with the ncoid field value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_ACreateNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) {
+
+	/* extract the status */
+	if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) {
+		printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): "
+		       "CompletionStatus not found\n");
+		return -1;
+	}
+
+	if (*status) {
+		dprintk("TurboPAM(parse_ACreateNCOCnf): status=%d\n", *status);
+		return 0;
+	}
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): "
+		       "NCOID not found\n");
+		return -1;
+	}
+
+	dprintk("TurboPAM(parse_ACreateNCOCnf): ncoid=%lu, status=%d\n",
+		(unsigned long)*ncoid, *status);
+	return 0;
+}
+
+/*
+ * Parse a ADestroyNCOCnf message. Not used in the driver.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	status: to be filled with the status field value
+ * 	ncoid: to be filled with the ncoid field value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_ADestroyNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) {
+
+	/* extract the status */
+	if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) {
+		printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): "
+		       "CompletionStatus not found\n");
+		return -1;
+	}
+
+	if (*status) {
+		dprintk("TurboPAM(parse_ADestroyNCOCnf): status=%d\n", *status);
+		return 0;
+	}
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): "
+		       "NCOID not found\n");
+		return -1;
+	}
+
+	dprintk("TurboPAM(parse_ADestroyNCOCnf): ncoid=%lu, status=%d\n", 
+		(unsigned long)*ncoid, *status);
+	return 0;
+}
+
+/*
+ * Parse a CConnectCnf message.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	ncoid: to be filled with the ncoid field value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_CConnectCnf(struct sk_buff *skb, u32 *ncoid) {
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CConnectCnf): "
+		       "NCOID not found\n");
+		return -1;
+	}
+	dprintk("TurboPAM(parse_CConnectCnf): ncoid=%lu\n", 
+		(unsigned long)*ncoid);
+	return 0;
+}
+
+/*
+ * Parse a CConnectInd message.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	ncoid: to be filled with the ncoid field value
+ * 	hdlc: to be filled with 1 if the incoming connection is a HDLC one,
+ * 		with 0 if the incoming connection is a modem one
+ * 	calling: to be filled with the calling phone number value
+ * 	called: to be filled with the called phone number value
+ * 	plan: to be filled with the plan value
+ * 	screen: to be filled with the screen value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_CConnectInd(struct sk_buff *skb, u32 *ncoid, u8 *hdlc, 
+		      u8 *calling, u8 *called, u8 *plan, u8 *screen) {
+	u8 phone[PHONE_MAXIMUMSIZE + 4];
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
+		       "NCOID not found\n");
+		return -1;
+	}
+
+	/* extract the bearer capability field */
+	if (extract_NCOParameter(skb, PAR_BearerCap, hdlc, 1)) {
+		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
+		       "BearerCap not found\n");
+		return -1;
+	}
+	*hdlc = (*hdlc == 0x88) ? 1 : 0;
+
+	/* extract the calling number / plan / screen */
+	if (extract_NCOParameter(skb, PAR_CallingNumber, phone, 
+				 PHONE_MAXIMUMSIZE + 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
+		       "CallingNumber not found\n");
+		return -1;
+	}
+	memcpy(calling, phone + 4, PHONE_MAXIMUMSIZE);
+	*plan = phone[1];
+	*screen = phone[3];
+
+	/* extract the called number */
+	if (extract_NCOParameter(skb, PAR_CalledNumber, phone, 
+				 PHONE_MAXIMUMSIZE + 2)) {
+		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
+		       "CalledNumber not found\n");
+		return -1;
+	}
+	memcpy(called, phone + 2, PHONE_MAXIMUMSIZE);
+
+	dprintk("TurboPAM(parse_CConnectInd): "
+		"ncoid=%lu, hdlc=%d, plan=%d, scr=%d, calling=%s, called=%s\n",
+		(unsigned long)*ncoid, *hdlc, *plan, *screen, calling, called);
+	return 0;
+}
+
+/*
+ * Parse a CDisconnectCnf message.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	ncoid: to be filled with the ncoid field value
+ * 	causetopuf: to be filled with the cause field value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_CDisconnectCnf(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) {
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): "
+		       "NCOID not found\n");
+		return -1;
+	}
+
+	/* extract the cause of disconnection */
+	if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): "
+		       "CauseToPUF not found\n");
+		return -1;
+	}
+
+	dprintk("TurboPAM(parse_CDisconnectCnf): ncoid=%lu, causetopuf=%lu\n", 
+		(unsigned long)*ncoid, (unsigned long)*causetopuf);
+	return 0;
+}
+
+/*
+ * Parse a CDisconnectInd message.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	ncoid: to be filled with the ncoid field value
+ * 	causetopuf: to be filled with the cause field value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_CDisconnectInd(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) {
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): "
+		       "NCOID not found\n");
+		return -1;
+	}
+
+	/* extract the cause of disconnection */
+	if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): "
+		       "CauseToPUF not found\n");
+		return -1;
+	}
+
+	dprintk("TurboPAM(parse_CDisconnectInd): ncoid=%lu, causetopuf=%lu\n", 
+		(unsigned long)*ncoid, (unsigned long)*causetopuf);
+	return 0;
+}
+
+/*
+ * Parse a U3ReadyToReceiveInd message.
+ *
+ * 	skb: the sk_buff containing the message
+ * 	ncoid: to be filled with the ncoid field value
+ * 	ready: to be filled with the ready field value
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_U3ReadyToReceiveInd(struct sk_buff *skb, u32 *ncoid, u8 *ready) {
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
+		printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): "
+		       "NCOID not found\n");
+		return -1;
+	}
+
+	/* extract the ready flag */
+	if (extract_NCOParameter(skb, PAR_ReadyFlag, ready, 1)) {
+		printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): "
+		       "ReadyFlag not found\n");
+		return -1;
+	}
+
+	dprintk("TurboPAM(parse_U3ReadyToReceiveInd): ncoid=%lu, ready=%d\n", 
+		(unsigned long)*ncoid, *ready);
+	return 0;
+}
+
+/*
+ * Parse a U3DataInd message.
+ *
+ * 	skb: the sk_buff containing the message + data
+ * 	ncoid: to be filled with the ncoid field value
+ * 	data: to be filled with the data 
+ * 	ready: to be filled with the data length
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int parse_U3DataInd(struct sk_buff *skb, u32 *ncoid, u8 **data, u16 *len) {
+	pci_mpb *p;
+
+	/* extract the ncoid */
+	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4) == -1) {
+		printk(KERN_ERR "TurboPAM(parse_U3DataInd): NCOID not found\n");
+		return -1;
+	}
+
+	/* get a pointer to the beginning of the data block and its length */
+	p = (pci_mpb *)(skb->data + sizeof(skb_header));
+	*len = p->actualDataSize;
+	skb_pull(skb, 
+		 sizeof(skb_header) + sizeof(pci_mpb) + p->actualBlockTLVSize);
+	*data = skb->data;
+
+	dprintk("TurboPAM(parse_U3DataInd): ncoid=%lu, datalen=%d\n", 
+		(unsigned long)*ncoid, *len);
+	return 0;
+}
+
diff -urN linux-2.4.6-pre8/drivers/isdn/tpam/tpam_queues.c linux/drivers/isdn/tpam/tpam_queues.c
--- linux-2.4.6-pre8/drivers/isdn/tpam/tpam_queues.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/tpam/tpam_queues.c	Mon Dec  3 22:50:38 2001
@@ -0,0 +1,418 @@
+/* $Id: tpam_queues.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "tpam.h"
+
+/* Local function prototype */
+static int tpam_sendpacket(tpam_card *card, tpam_channel *channel);
+
+/*
+ * Queue a message to be send to the card when possible.
+ *
+ * 	card: the board
+ * 	skb: the sk_buff containing the message.
+ */
+void tpam_enqueue(tpam_card *card, struct sk_buff *skb) {
+
+	dprintk("TurboPAM(tpam_enqueue): card=%d\n", card->id);
+
+	/* queue the sk_buff on the board's send queue */
+	skb_queue_tail(&card->sendq, skb);
+
+	/* queue the board's send task struct for immediate treatment */
+	queue_task(&card->send_tq, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*
+ * Queue a data message to be send to the card when possible.
+ *
+ * 	card: the board
+ * 	skb: the sk_buff containing the message and the data. This parameter
+ * 		can be NULL if we want just to trigger the send of queued 
+ * 		messages.
+ */
+void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) {
+	
+	dprintk("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n", 
+		channel->card->id, channel->num);
+
+	/* if existant, queue the sk_buff on the channel's send queue */
+	if (skb)
+		skb_queue_tail(&channel->sendq, skb);
+
+	/* queue the channel's send task struct for immediate treatment */
+	queue_task(&channel->card->send_tq, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*
+ * IRQ handler.
+ *
+ * If a message comes from the board we read it, construct a sk_buff containing
+ * the message and we queue the sk_buff on the board's receive queue, and we
+ * trigger the execution of the board's receive task queue.
+ *
+ * If a message ack comes from the board we can go on and send a new message,
+ * so we trigger the execution of the board's send task queue.
+ *
+ * 	irq: the irq number
+ * 	dev_id: the registered board to the irq
+ * 	regs: not used.
+ */
+void tpam_irq(int irq, void *dev_id, struct pt_regs *regs) {
+	tpam_card *card = (tpam_card *)dev_id;
+	u32 ackupload, uploadptr;
+	u32 waiting_too_long;
+	u32 hpic;
+	struct sk_buff *skb;
+	pci_mpb mpb;
+	skb_header *skbh;
+
+	dprintk("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id);
+
+	/* grab the board lock */
+	spin_lock(&card->lock);
+
+	/* get the message type */
+	ackupload = copy_from_pam_dword(card, (void *)TPAM_ACKUPLOAD_REGISTER);
+
+	/* acknowledge the interrupt */
+	copy_to_pam_dword(card, (void *)TPAM_INTERRUPTACK_REGISTER, 0);
+	readl(card->bar0 + TPAM_HINTACK_REGISTER);
+
+	if (!ackupload) {
+		/* it is a new message from the board */
+		
+		dprintk("TurboPAM(tpam_irq): message received, card=%d\n", 
+			card->id);
+
+		/* get the upload pointer */
+		uploadptr = copy_from_pam_dword(card, 
+					    (void *)TPAM_UPLOADPTR_REGISTER);
+		
+		/* get the beginning of the message (pci_mpb part) */
+		copy_from_pam(card, &mpb, (void *)uploadptr, sizeof(pci_mpb));
+
+		/* allocate the sk_buff */
+		if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) + 
+				      mpb.actualBlockTLVSize + 
+				      mpb.actualDataSize, GFP_ATOMIC))) {
+			printk(KERN_ERR "TurboPAM(tpam_irq): "
+			       "alloc_skb failed\n");
+			spin_unlock(&card->lock);
+			return;
+		}
+
+		/* build the skb_header */
+		skbh = (skb_header *)skb_put(skb, sizeof(skb_header));
+		skbh->size = sizeof(pci_mpb) + mpb.actualBlockTLVSize;
+		skbh->data_size = mpb.actualDataSize;
+		skbh->ack = 0;
+		skbh->ack_size = 0;
+
+		/* copy the pci_mpb into the sk_buff */
+		memcpy(skb_put(skb, sizeof(pci_mpb)), &mpb, sizeof(pci_mpb));
+
+		/* copy the TLV block into the sk_buff */
+		copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize),
+			      (void *)uploadptr + sizeof(pci_mpb), 
+			      mpb.actualBlockTLVSize);
+
+		/* if existent, copy the data block into the sk_buff */
+		if (mpb.actualDataSize)
+			copy_from_pam(card, skb_put(skb, mpb.actualDataSize),
+				(void *)uploadptr + sizeof(pci_mpb) + 4096, 
+				mpb.actualDataSize);
+
+		/* wait for the board to become ready */
+		waiting_too_long = 0;
+		do {
+			hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
+			if (waiting_too_long++ > 0xfffffff) {
+				spin_unlock(&card->lock);
+				printk(KERN_ERR "TurboPAM(tpam_irq): "
+						"waiting too long...\n");
+				return;
+			}
+		} while (hpic & 0x00000002);
+
+		/* acknowledge the message */
+        	copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 
+				  0xffffffff);
+        	readl(card->bar0 + TPAM_DSPINT_REGISTER);
+
+		/* release the board lock */
+		spin_unlock(&card->lock);
+	
+		if (mpb.messageID == ID_U3ReadyToReceiveInd) {
+			/* this message needs immediate treatment */
+			tpam_recv_U3ReadyToReceiveInd(card, skb);
+			kfree_skb(skb);
+		}
+		else {
+			/* put the message in the receive queue */
+			skb_queue_tail(&card->recvq, skb);
+			queue_task(&card->recv_tq, &tq_immediate);
+			mark_bh(IMMEDIATE_BH);
+		}
+		return;
+	}
+	else {
+		/* it is a ack from the board */
+
+		dprintk("TurboPAM(tpam_irq): message acknowledged, card=%d\n",
+			card->id);
+
+		/* board is not busy anymore */
+		card->busy = 0;
+		
+		/* release the lock */
+		spin_unlock(&card->lock);
+
+		/* schedule the send queue for execution */
+		queue_task(&card->send_tq, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+		return;
+	}
+
+	/* not reached */
+}
+
+/*
+ * Run the board's receive task queue, dispatching each message on the queue,
+ * to its treatment function.
+ *
+ * 	card: the board.
+ */
+void tpam_recv_tq(tpam_card *card) {
+	pci_mpb *p;
+	struct sk_buff *skb;
+
+	/* for each message on the receive queue... */
+        while ((skb = skb_dequeue(&card->recvq))) {
+
+		/* point to the pci_mpb block */
+		p = (pci_mpb *)(skb->data + sizeof(skb_header));
+
+		/* dispatch the message */
+		switch (p->messageID) {
+			case ID_ACreateNCOCnf:
+				tpam_recv_ACreateNCOCnf(card, skb);
+				break;
+			case ID_ADestroyNCOCnf:
+				tpam_recv_ADestroyNCOCnf(card, skb);
+				break;
+			case ID_CConnectCnf:
+				tpam_recv_CConnectCnf(card, skb);
+				break;
+			case ID_CConnectInd:
+				tpam_recv_CConnectInd(card, skb);
+				break;
+			case ID_CDisconnectInd:
+				tpam_recv_CDisconnectInd(card, skb);
+				break;
+			case ID_CDisconnectCnf:
+				tpam_recv_CDisconnectCnf(card, skb);
+				break;
+			case ID_U3DataInd:
+				tpam_recv_U3DataInd(card, skb);
+				break;
+			default:
+				dprintk("TurboPAM(tpam_recv_tq): "
+					"unknown messageID %d, card=%d\n", 
+					p->messageID, card->id);
+				break;
+		}
+		/* free the sk_buff */
+		kfree_skb(skb);
+	}
+}
+
+/*
+ * Run the board's send task queue. If there is a message in the board's send
+ * queue, it gets sended. If not, it examines each channel (one at the time,
+ * using a round robin algorithm). For each channel, if there is a message
+ * in the channel's send queue, it gets sended. This function sends only one
+ * message, it does not consume all the queue.
+ */
+void tpam_send_tq(tpam_card *card) {
+	int i;
+
+	/* first, try to send a packet from the board's send queue */
+	if (tpam_sendpacket(card, NULL))
+		return;
+
+	/* then, try each channel, in a round-robin manner */
+	for (i=card->roundrobin; i<card->roundrobin+card->channels_used; i++) {
+		if (tpam_sendpacket(card, 
+				    &card->channels[i % card->channels_used])) {
+			card->roundrobin = (i + 1) % card->channels_used;
+			return;
+		}
+	}
+}
+
+/*
+ * Try to send a packet from the board's send queue or from the channel's
+ * send queue.
+ *
+ * 	card: the board.
+ * 	channel: the channel (if NULL, the packet will be taken from the 
+ * 		board's send queue. If not, it will be taken from the 
+ * 		channel's send queue.
+ *
+ * Return: 0 if tpam_send_tq must try another card/channel combination
+ * 	(meaning that no packet has been send), 1 if no more packets
+ * 	can be send at that time (a packet has been send or the card is
+ * 	still busy from a previous send).
+ */
+static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) {
+        struct sk_buff *skb;
+	u32 hpic;
+        u32 downloadptr;
+	skb_header *skbh;
+	u32 waiting_too_long;
+
+	dprintk("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n", 
+		card->id, channel ? channel->num : -1);
+
+	if (channel) {
+		/* dequeue a packet from the channel's send queue */
+		if (!(skb = skb_dequeue(&channel->sendq))) {
+			dprintk("TurboPAM(tpam_sendpacket): "
+				"card=%d, channel=%d, no packet\n", 
+				card->id, channel->num);
+			return 0;
+		}
+
+		/* if the channel is not ready to receive, requeue the packet
+		 * and return 0 to give a chance to another channel */
+		if (!channel->readytoreceive) {
+			dprintk("TurboPAM(tpam_sendpacket): "
+				"card=%d, channel=%d, channel not ready\n",
+				card->id, channel->num);
+			skb_queue_head(&channel->sendq, skb);
+			return 0;
+		}
+
+		/* grab the board lock */
+		spin_lock_irq(&card->lock);
+
+		/* if the board is busy, requeue the packet and return 1 since
+		 * there is no need to try another channel */
+		if (card->busy) {
+			dprintk("TurboPAM(tpam_sendpacket): "
+				"card=%d, channel=%d, card busy\n",
+				card->id, channel->num);
+			skb_queue_head(&channel->sendq, skb);
+			spin_unlock_irq(&card->lock);
+			return 1;
+		}
+	}
+	else {
+		/* dequeue a packet from the board's send queue */
+		if (!(skb = skb_dequeue(&card->sendq))) {
+			dprintk("TurboPAM(tpam_sendpacket): "
+				"card=%d, no packet\n", card->id);
+			return 0;
+		}
+
+		/* grab the board lock */
+		spin_lock_irq(&card->lock);
+
+		/* if the board is busy, requeue the packet and return 1 since
+		 * there is no need to try another channel */
+		if (card->busy) {
+			dprintk("TurboPAM(tpam_sendpacket): "
+				"card=%d, card busy\n", card->id);
+			skb_queue_head(&card->sendq, skb);
+			spin_unlock_irq(&card->lock);
+			return 1;
+		}
+	}
+
+	/* wait for the board to become ready */
+	waiting_too_long = 0;
+	do {
+		hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
+		if (waiting_too_long++ > 0xfffffff) {
+			spin_unlock_irq(&card->lock);
+			printk(KERN_ERR "TurboPAM(tpam_sendpacket): "
+					"waiting too long...\n");
+			return 1;
+		}
+	} while (hpic & 0x00000002);
+
+	skbh = (skb_header *)skb->data;
+	dprintk("TurboPAM(tpam_sendpacket): "
+		"card=%d, card ready, sending %d/%d bytes\n", 
+		card->id, skbh->size, skbh->data_size);
+
+	/* get the board's download pointer */
+       	downloadptr = copy_from_pam_dword(card, 
+					  (void *)TPAM_DOWNLOADPTR_REGISTER);
+
+	/* copy the packet to the board at the downloadptr location */
+       	copy_to_pam(card, (void *)downloadptr, skb->data + sizeof(skb_header), 
+		    skbh->size);
+	if (skbh->data_size)
+		/* if there is some data in the packet, copy it too */
+		copy_to_pam(card, (void *)downloadptr + sizeof(pci_mpb) + 4096,
+			    skb->data + sizeof(skb_header) + skbh->size, 
+			    skbh->data_size);
+
+	/* card will become busy right now */
+	card->busy = 1;
+
+	/* interrupt the board */
+	copy_to_pam_dword(card, (void *)TPAM_ACKDOWNLOAD_REGISTER, 0);
+	readl(card->bar0 + TPAM_DSPINT_REGISTER);
+
+	/* release the lock */
+	spin_unlock_irq(&card->lock);
+
+	/* if a data ack was requested by the ISDN link layer, send it now */
+	if (skbh->ack) {
+		isdn_ctrl ctrl;
+		ctrl.driver = card->id;
+		ctrl.command = ISDN_STAT_BSENT;
+		ctrl.arg = channel->num;
+		ctrl.parm.length = skbh->ack_size;
+		(* card->interface.statcallb)(&ctrl);
+	}
+
+	/* free the sk_buff */
+	kfree_skb(skb);
+
+	return 1;
+}
+
diff -urN linux-2.4.6-pre8/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- linux-2.4.6-pre8/drivers/macintosh/via-pmu.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/macintosh/via-pmu.c	Mon Dec  3 22:50:38 2001
@@ -1431,7 +1431,7 @@
  		_set_L2CR(save_l2cr);
 	
 	/* Restore userland MMU context */
-	set_context(current->mm->context, current->mm->pgd);
+	set_context(current->mm->context);
 
 	/* Re-enable DEC interrupts and kick DEC */
 	asm volatile("mtdec %0" : : "r" (0x7fffffff));
@@ -1560,7 +1560,7 @@
 	feature_wake_up();
 	pbook_pci_restore();
 
-	set_context(current->mm->context, current->mm->pgd);
+	set_context(current->mm->context);
 
 	/* Restore L2 cache */
 	if (save_l2cr)
diff -urN linux-2.4.6-pre8/drivers/md/md.c linux/drivers/md/md.c
--- linux-2.4.6-pre8/drivers/md/md.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/md/md.c	Mon Dec  3 22:50:38 2001
@@ -483,14 +483,17 @@
 	}
 }
 
-static void mark_rdev_faulty (mdk_rdev_t * rdev)
+static inline int mark_rdev_faulty (mdk_rdev_t * rdev)
 {
 	if (!rdev) {
 		MD_BUG();
-		return;
+		return 0;
 	}
+	if (rdev->faulty)
+		return 0;
 	free_disk_sb(rdev);
 	rdev->faulty = 1;
+	return 1;
 }
 
 static int read_disk_sb (mdk_rdev_t * rdev)
@@ -1645,8 +1648,7 @@
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		if (rdev->faulty)
 			continue;
-		fsync_dev(rdev->dev);
-		invalidate_buffers(rdev->dev);
+		invalidate_device(rdev->dev, 1);
 		if (get_hardsect_size(rdev->dev)
 		    > md_hardsect_sizes[mdidx(mddev)]) 
 			md_hardsect_sizes[mdidx(mddev)] =
@@ -1672,7 +1674,8 @@
 	 * twice as large as sectors.
 	 */
 	md_hd_struct[mdidx(mddev)].start_sect = 0;
-	md_hd_struct[mdidx(mddev)].nr_sects = md_size[mdidx(mddev)] << 1;
+	register_disk(&md_gendisk, MKDEV(MAJOR_NR,mdidx(mddev)),
+		      1, &md_fops, md_size[mdidx(mddev)]<<1);
 
 	read_ahead[MD_MAJOR] = 1024;
 	return (0);
@@ -1729,12 +1732,6 @@
  		printk(STILL_IN_USE, mdidx(mddev));
  		OUT(-EBUSY);
  	}
- 
- 	/* this shouldn't be needed as above would have fired */
-	if (!ro && is_mounted(dev)) {
-		printk (STILL_MOUNTED, mdidx(mddev));
-		OUT(-EBUSY);
-	}
 
 	if (mddev->pers) {
 		/*
@@ -1758,15 +1755,7 @@
 		down(&mddev->recovery_sem);
 		up(&mddev->recovery_sem);
 
-		/*
-		 *  sync and invalidate buffers because we cannot kill the
-		 *  main thread with valid IO transfers still around.
-		 *  the kernel lock protects us from new requests being
-		 *  added after invalidate_buffers().
-		 */
-		fsync_dev (mddev_to_kdev(mddev));
-		fsync_dev (dev);
-		invalidate_buffers (dev);
+		invalidate_device(dev, 1);
 
 		if (ro) {
 			if (mddev->ro)
@@ -2946,7 +2935,8 @@
 		return 0;
 	}
 	rrdev = find_rdev(mddev, rdev);
-	mark_rdev_faulty(rrdev);
+	if (!mark_rdev_faulty(rrdev))
+		return 0;
 	/*
 	 * if recovery was running, stop it now.
 	 */
@@ -3228,7 +3218,6 @@
 	mddev_t *mddev2;
 	unsigned int max_sectors, currspeed,
 		j, window, err, serialize;
-	kdev_t read_disk = mddev_to_kdev(mddev);
 	unsigned long mark[SYNC_MARKS];
 	unsigned long mark_cnt[SYNC_MARKS];	
 	int last_mark,m;
@@ -3361,7 +3350,6 @@
 		} else
 			current->nice = -20;
 	}
-	fsync_dev(read_disk);
 	printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev));
 	err = 0;
 	/*
@@ -3507,7 +3495,6 @@
 		md_size[i] = 0;
 		md_hardsect_sizes[i] = 512;
 		md_maxreadahead[i] = MD_READAHEAD;
-		register_disk(&md_gendisk, MKDEV(MAJOR_NR,i), 1, &md_fops, 0);
 	}
 	blksize_size[MAJOR_NR] = md_blocksizes;
 	blk_size[MAJOR_NR] = md_size;
diff -urN linux-2.4.6-pre8/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- linux-2.4.6-pre8/drivers/net/3c59x.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/net/3c59x.c	Mon Dec  3 22:50:38 2001
@@ -178,7 +178,13 @@
 /* "Knobs" that adjust features and parameters. */
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1512 effectively disables this feature. */
+#ifndef __arm__
 static const int rx_copybreak = 200;
+#else
+/* ARM systems perform better by disregarding the bus-master
+   transfer capability of these cards. -- rmk */
+static const int rx_copybreak = 1513;
+#endif
 /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
 static const int mtu = 1500;
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
@@ -218,6 +224,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/mii.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2646,26 +2653,32 @@
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	int phy = vp->phys[0] & 0x1f;
 	int retval;
 
 	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] = phy;
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = phy;
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		EL3WINDOW(4);
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		retval = 0;
 		break;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN)) {
 			retval = -EPERM;
 		} else {
 			EL3WINDOW(4);
-			mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+			mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 			retval = 0;
 		}
 		break;
diff -urN linux-2.4.6-pre8/drivers/net/8139too.c linux/drivers/net/8139too.c
--- linux-2.4.6-pre8/drivers/net/8139too.c	Mon Dec  3 22:50:27 2001
+++ linux/drivers/net/8139too.c	Mon Dec  3 22:50:38 2001
@@ -137,7 +137,7 @@
 */
 
 #define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.18-pre3"
+#define DRV_VERSION	"0.9.18-pre4"
 
 
 #include <linux/config.h>
@@ -613,7 +613,7 @@
 static void rtl8139_interrupt (int irq, void *dev_instance,
 			       struct pt_regs *regs);
 static int rtl8139_close (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 struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
 static inline u32 ether_crc (int length, unsigned char *data);
 static void rtl8139_set_rx_mode (struct net_device *dev);
@@ -955,7 +955,7 @@
 	dev->stop = rtl8139_close;
 	dev->get_stats = rtl8139_get_stats;
 	dev->set_multicast_list = rtl8139_set_rx_mode;
-	dev->do_ioctl = mii_ioctl;
+	dev->do_ioctl = netdev_ioctl;
 	dev->tx_timeout = rtl8139_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -1699,17 +1699,14 @@
 }
 
 
-
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
 	struct rtl8139_private *tp = dev->priv;
 	void *ioaddr = tp->mmio_addr;
 	unsigned int entry;
-	unsigned long flags;
+	u32 dma_addr;
 
-	/* XXX paranoid + sledgehammer == temporary system crash fix */
-	wmb();
-	spin_lock_irqsave (&tp->lock, flags);
+	mb();
 
 	/* Calculate the next Tx descriptor entry. */
 	entry = tp->cur_tx % NUM_TX_DESC;
@@ -1721,28 +1718,29 @@
 	if ((long) skb->data & 3) {	/* Must use alignment buffer. */
 		/* tp->tx_info[entry].mapping = 0; */
 		memcpy (tp->tx_buf[entry], skb->data, skb->len);
-		RTL_W32_F (TxAddr0 + (entry * 4),
-			   tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs));
+		dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
 	} else {
 		tp->xstats.tx_buf_mapped++;
 		tp->tx_info[entry].mapping =
 		    pci_map_single (tp->pci_dev, skb->data, skb->len,
 				    PCI_DMA_TODEVICE);
-		RTL_W32_F (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping);
+		dma_addr = tp->tx_info[entry].mapping;
 	}
 
 	/* Note: the chip doesn't have auto-pad! */
-	RTL_W32 (TxStatus0 + (entry * sizeof (u32)),
-		 tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+	spin_lock_irq(&tp->lock);
+	RTL_W32_F (TxAddr0 + (entry * 4), dma_addr);
+	RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
+		   tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+	spin_unlock_irq(&tp->lock);
 
 	dev->trans_start = jiffies;
 
 	tp->cur_tx++;
+	mb();
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
 		netif_stop_queue (dev);
 
-	spin_unlock_irqrestore (&tp->lock, flags);
-
 	DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
 		 dev->name, skb->data, skb->len, entry);
 
@@ -1779,7 +1777,7 @@
 			tp->stats.tx_errors++;
 			if (txstatus & TxAborted) {
 				tp->stats.tx_aborted_errors++;
-				RTL_W32_F (TxConfig, TxClearAbt);
+				RTL_W32_F (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));
 			}
 			if (txstatus & TxCarrierLost)
 				tp->stats.tx_carrier_errors++;
@@ -1814,7 +1812,6 @@
 
 		dirty_tx++;
 		tx_left--;
-		barrier();
 	}
 
 #ifndef RTL8139_NDEBUG
@@ -1828,6 +1825,7 @@
 	/* only wake the queue if we did work, and the queue is stopped */
 	if (tp->dirty_tx != dirty_tx) {
 		tp->dirty_tx = dirty_tx;
+		mb();
 		if (netif_queue_stopped (dev))
 			netif_wake_queue (dev);
 	}
@@ -1908,6 +1906,8 @@
 		unsigned int pkt_size;
 		struct sk_buff *skb;
 
+		rmb();
+		
 		/* read size+status of next frame from DMA ring buffer */
 		rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
 		rx_size = rx_status >> 16;
@@ -2057,6 +2057,8 @@
 	int ackstat, status;
 	int link_changed = 0; /* avoid bogus "uninit" warning */
 
+	spin_lock (&tp->lock);
+
 	do {
 		status = RTL_R16 (IntrStatus);
 
@@ -2092,11 +2094,8 @@
 			rtl8139_weird_interrupt (dev, tp, ioaddr,
 						 status, link_changed);
 
-		if (netif_running (dev) && (status & (TxOK | TxErr))) {
-			spin_lock (&tp->lock);
+		if (netif_running (dev) && (status & (TxOK | TxErr)))
 			rtl8139_tx_interrupt (dev, tp, ioaddr);
-			spin_unlock (&tp->lock);
-		}
 
 		boguscnt--;
 	} while (boguscnt > 0);
@@ -2109,6 +2108,8 @@
 		RTL_W16 (IntrStatus, 0xffff);
 	}
 
+	spin_unlock (&tp->lock);
+
 	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
 		 dev->name, RTL_R16 (IntrStatus));
 }
@@ -2174,32 +2175,69 @@
 }
 
 
-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 rtl8139_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;
+		}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct rtl8139_private *tp = dev->priv;
-	u16 *data = (u16 *) & rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	int rc = 0;
+	int phy = tp->phys[0] & 0x3f;
 
 	DPRINTK ("ENTER\n");
 
+	data->phy_id &= 0x1f;
+	data->reg_num &= 0x1f;
+
 	switch (cmd) {
-	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
-		data[0] = tp->phys[0] & 0x3f;
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
+	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */
+		data->phy_id = phy;
 		/* Fall Through */
 
-	case SIOCDEVPRIVATE + 1:	/* Read the specified MII register. */
-		data[3] = mdio_read (dev, data[0], data[1] & 0x1f);
+	case SIOCGMIIREG:	/* Read the specified MII register. */
+	case SIOCDEVPRIVATE+1:	/* binary compat, remove in 2.5 */
+		data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
 		break;
 
-	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+	case SIOCSMIIREG:	/* Write the specified MII register */
+	case SIOCDEVPRIVATE+2:	/* binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
 		}
 
-		if (data[0] == tp->phys[0]) {
-			u16 value = data[2];
-			switch (data[1]) {
+		if (data->phy_id == phy) {
+			u16 value = data->val_in;
+			switch (data->reg_num) {
 			case 0:
 				/* Check for autonegotiation on or reset. */
 				tp->medialock = (value & 0x9000) ? 0 : 1;
@@ -2209,7 +2247,7 @@
 			case 4: /* tp->advertising = value; */ break;
 			}
 		}
-		mdio_write(dev, data[0], data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
 		break;
 
 	default:
diff -urN linux-2.4.6-pre8/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.4.6-pre8/drivers/net/Config.in	Mon Dec  3 22:50:27 2001
+++ linux/drivers/net/Config.in	Mon Dec  3 22:50:38 2001
@@ -15,7 +15,7 @@
    fi
 fi
 
-if [ "$CONFIG_ISAPNP" = "y" ]; then
+if [ "$CONFIG_ISAPNP" = "y" -o "$CONFIG_ISAPNP" = "m" ]; then
    tristate 'General Instruments Surfboard 1000' CONFIG_NET_SB1000 $CONFIG_ISAPNP
 fi
 
@@ -94,9 +94,7 @@
    if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
       dep_tristate '    WD80*3 support' CONFIG_WD80x3 $CONFIG_ISA
       dep_tristate '    SMC Ultra MCA support' CONFIG_ULTRAMCA $CONFIG_MCA
-      if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ISAPNP" = "y" ]; then
-         tristate '    SMC Ultra support' CONFIG_ULTRA
-      fi
+      dep_tristate '    SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA
       dep_tristate '    SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA
       dep_tristate '    SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA
    fi
@@ -106,10 +104,8 @@
       dep_tristate '    NI5210 support' CONFIG_NI52 $CONFIG_ISA
       dep_tristate '    NI6510 support' CONFIG_NI65 $CONFIG_ISA
    fi
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      if [ "$CONFIG_ISA" = "y" -o "$CONFIG_MCA" = "y" ]; then
-         tristate '  AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
-      fi
+   if [ "$CONFIG_ISA" = "y" -o "$CONFIG_MCA" = "y" ]; then
+      dep_tristate '  AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 $CONFIG_EXPERIMENTAL
    fi
    if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_MCA" = "y" ]; then
       tristate '  DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
@@ -142,7 +138,11 @@
       tristate '  NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA
       tristate '  IBM LAN Adapter/A support' CONFIG_IBMLANA
    fi
-   dep_bool '  EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI
+   if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then
+      bool '  EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI
+   else
+      define_bool CONFIG_NET_PCI n
+   fi
    if [ "$CONFIG_NET_PCI" = "y" ]; then
       dep_tristate '    AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI
       dep_tristate '    Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI $CONFIG_EXPERIMENTAL
@@ -153,10 +153,8 @@
       dep_tristate '    Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA
       dep_tristate '    CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
       dep_tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI
-      if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
-         dep_bool '      New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL
-         bool '      Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO
-      fi
+      dep_mbool '      New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL $CONFIG_TULIP
+      dep_mbool '      Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO $CONFIG_TULIP
       if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then
          tristate '    Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
          tristate '    Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
@@ -208,9 +206,7 @@
 comment 'Ethernet (1000 Mbit)'
 
 dep_tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC $CONFIG_PCI
-if [ "$CONFIG_ACENIC" != "n" ]; then
-   bool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I
-fi
+dep_mbool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I $CONFIG_ACENIC
 dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS
 dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
 dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL
@@ -248,9 +244,7 @@
    dep_tristate '  PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
    dep_tristate '  PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
    dep_tristate '  PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
-   fi
+   dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL
 fi
 
 tristate 'SLIP (serial line) support' CONFIG_SLIP
diff -urN linux-2.4.6-pre8/drivers/net/aironet4500_proc.c linux/drivers/net/aironet4500_proc.c
--- linux-2.4.6-pre8/drivers/net/aironet4500_proc.c	Tue Feb 13 13:15:04 2001
+++ linux/drivers/net/aironet4500_proc.c	Mon Dec  3 22:50:38 2001
@@ -1,5 +1,5 @@
 /*
- *	 Aironet 4500 Pcmcia driver
+ *	 Aironet 4500 /proc interface
  *
  *		Elmer Joandi, Januar 1999
  *	Copyright GPL
diff -urN linux-2.4.6-pre8/drivers/net/declance.c linux/drivers/net/declance.c
--- linux-2.4.6-pre8/drivers/net/declance.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/declance.c	Mon Dec  3 22:50:38 2001
@@ -83,7 +83,7 @@
 #include <linux/etherdevice.h>
 
 #ifndef CONFIG_TC
-unsigned long system_base = 0;
+unsigned long system_base;
 unsigned long dmaptr;
 #endif
 static int type;
diff -urN linux-2.4.6-pre8/drivers/net/defxx.c linux/drivers/net/defxx.c
--- linux-2.4.6-pre8/drivers/net/defxx.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/defxx.c	Mon Dec  3 22:50:38 2001
@@ -2732,7 +2732,7 @@
 	for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
 		for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
 		{
-			struct sk_buff *newskb = __dev_alloc_skb(NEW_SKB_SIZE, GFP_NOFS);	/* Why not GFP_KERNEL? */
+			struct sk_buff *newskb = __dev_alloc_skb(NEW_SKB_SIZE, GFP_NOIO);
 			if (!newskb)
 				return -ENOMEM;
 			bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
diff -urN linux-2.4.6-pre8/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- linux-2.4.6-pre8/drivers/net/dmfe.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/dmfe.c	Mon Dec  3 22:50:38 2001
@@ -130,7 +130,7 @@
 #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_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(KERN_ERR "<DMFE>: %s %lx\n", (msg), (long) (value))
 
 #define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR "<DMFE>: Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half");
 
@@ -182,7 +182,7 @@
 	struct pci_dev * net_dev;	/* PCI device */
 	spinlock_t lock;
 
-	u32 ioaddr;			/* I/O base address */
+	long ioaddr;			/* I/O base address */
 	u32 cr0_data;
 	u32 cr5_data;
 	u32 cr6_data;
@@ -206,10 +206,10 @@
 	struct rx_desc *first_rx_desc;
 	struct rx_desc *rx_insert_ptr;
 	struct rx_desc *rx_ready_ptr;	/* packet come pointer */
-	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 */
+	unsigned long tx_packet_cnt;		/* transmitted packet count */
+	unsigned long tx_queue_cnt;		/* wait to send packet count */
+	unsigned long rx_avail_cnt;		/* available rx descriptor count */
+	unsigned long interval_rx_cnt;		/* rx packet count a callback time */
 
 	u16 HPNA_command;		/* For HPNA register 16 */
 	u16 HPNA_timer;			/* For HPNA remote device check */
@@ -265,20 +265,20 @@
 static char version[] __devinitdata =
 	KERN_INFO "Davicom DM9xxx net driver, version " DMFE_VERSION "\n";
 
-static int dmfe_debug = 0;
+static int dmfe_debug;
 static unsigned char dmfe_media_mode = DMFE_AUTO;
-static u32 dmfe_cr6_user_set = 0;
+static u32 dmfe_cr6_user_set;
 
 /* For module input parameter */
-static int debug = 0;
-static u32 cr6set = 0;
+static int debug;
+static u32 cr6set;
 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
+static u8 HPNA_mode;		/* Default: Low Power/High Speed */
+static u8 HPNA_rx_cmd;		/* Default: Disable Rx remote command */
+static u8 HPNA_tx_cmd;		/* Default: Don't issue remote command */
+static u8 HPNA_NoiseFloor;	/* Default: HPNA NoiseFloor */
+static u8 SF_mode;		/* Special Function: 1:VLAN, 2:RX Flow Control
 				   4: TX pause packet */
 
 unsigned long CrcTable[256] = {
@@ -357,15 +357,15 @@
 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 dmfe_descriptor_init(struct dmfe_board_info *, unsigned long);
 static void allocated_rx_buffer(struct dmfe_board_info *);
-static void update_cr6(u32, u32);
+static void update_cr6(u32, unsigned long);
 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 u16 phy_read(unsigned long, u8, u8, u32);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_write_1bit(unsigned long, u32);
+static u16 phy_read_1bit(unsigned long);
 static u8 dmfe_sense_speed(struct dmfe_board_info *);
 static void dmfe_process_mode(struct dmfe_board_info *);
 static void dmfe_timer(unsigned long);
@@ -607,7 +607,7 @@
 static void dmfe_init_dm910x(struct DEVICE *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
-	u32 ioaddr = db->ioaddr;
+	unsigned long ioaddr = db->ioaddr;
 
 	DMFE_DBUG(0, "dmfe_init_dm910x()", 0);
 
@@ -693,7 +693,7 @@
 	/* 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);
+		printk(KERN_ERR "<DMFE>: No Tx resource %ld\n", db->tx_queue_cnt);
 		return 1;
 	}
 
@@ -742,7 +742,7 @@
 static int dmfe_stop(struct DEVICE *dev)
 {
 	struct dmfe_board_info *db = dev->priv;
-	u32 ioaddr = dev->base_addr;
+	unsigned long ioaddr = dev->base_addr;
 
 	DMFE_DBUG(0, "dmfe_stop", 0);
 
@@ -785,7 +785,7 @@
 {
 	struct DEVICE *dev = dev_id;
 	struct dmfe_board_info *db = (struct dmfe_board_info *) dev->priv;
-	u32 ioaddr = dev->base_addr;
+	unsigned long ioaddr = dev->base_addr;
 	unsigned long flags;
 
 	DMFE_DBUG(0, "dmfe_interrupt()", 0);
@@ -851,7 +851,7 @@
 static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
 {
 	struct tx_desc *txptr;
-	u32 ioaddr = dev->base_addr;
+	unsigned long ioaddr = dev->base_addr;
 
 	txptr = db->tx_remove_ptr;
 	while(db->tx_packet_cnt) {
@@ -1275,7 +1275,7 @@
  *	Using Chain structure, and allocated Tx/Rx buffer
  */
 
-static void dmfe_descriptor_init(struct dmfe_board_info *db, u32 ioaddr)
+static void dmfe_descriptor_init(struct dmfe_board_info *db, unsigned long ioaddr)
 {
 	struct tx_desc *tmp_tx;
 	struct rx_desc *tmp_rx;
@@ -1334,11 +1334,11 @@
 
 
 /*
- *	Update CR6 vaule
+ *	Update CR6 value
  *	Firstly stop DM910X , then written value and start
  */
 
-static void update_cr6(u32 cr6_data, u32 ioaddr)
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
 {
 	u32 cr6_tmp;
 
@@ -1359,7 +1359,7 @@
 {
 	struct dev_mc_list *mcptr;
 	u16 * addrptr;
-	u32 ioaddr = dev->base_addr+0xc0;		/* ID Table */
+	unsigned long ioaddr = dev->base_addr+0xc0;		/* ID Table */
 	u32 hash_val;
 	u16 i, hash_table[4];
 
@@ -1470,7 +1470,7 @@
 	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->rx_skb_ptr = (u32) skb; /* FIXME */
 		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;
@@ -1663,10 +1663,10 @@
  *	Write a word to Phy register
  */
 
-static void phy_write(u32 iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data, u32 chip_id)
 {
 	u16 i;
-	u32 ioaddr;
+	unsigned long ioaddr;
 
 	if (chip_id == PCI_DM9132_ID) {
 		ioaddr = iobase + 0x80 + offset * 4;
@@ -1710,11 +1710,11 @@
  *	Read a word data from phy register
  */
 
-static u16 phy_read(u32 iobase, u8 phy_addr, u8 offset, u32 chip_id)
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
 {
 	int i;
 	u16 phy_data;
-	u32 ioaddr;
+	unsigned long ioaddr;
 
 	if (chip_id == PCI_DM9132_ID) {
 		/* DM9132 Chip */
@@ -1762,7 +1762,7 @@
  *	Write one bit data to Phy Controller
  */
 
-static void phy_write_1bit(u32 ioaddr, u32 phy_data)
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data)
 {
 	outl(phy_data, ioaddr);			/* MII Clock Low */
 	udelay(1);
@@ -1777,7 +1777,7 @@
  *	Read one bit phy data from PHY controller
  */
 
-static u16 phy_read_1bit(u32 ioaddr)
+static u16 phy_read_1bit(unsigned long ioaddr)
 {
 	u16 phy_data;
 
diff -urN linux-2.4.6-pre8/drivers/net/dummy.c linux/drivers/net/dummy.c
--- linux-2.4.6-pre8/drivers/net/dummy.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/net/dummy.c	Mon Dec  3 22:50:38 2001
@@ -54,33 +54,32 @@
 static int __init dummy_init(struct net_device *dev)
 {
 	/* Initialize the device structure. */
-	dev->hard_start_xmit	= dummy_xmit;
 
 	dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
 	if (dev->priv == NULL)
 		return -ENOMEM;
 	memset(dev->priv, 0, sizeof(struct net_device_stats));
-	dev->get_stats	= dummy_get_stats;
 
+	dev->get_stats = dummy_get_stats;
+	dev->hard_start_xmit = dummy_xmit;
 	dev->set_multicast_list = set_multicast_list;
+#ifdef CONFIG_NET_FASTROUTE
+	dev->accept_fastpath = dummy_accept_fastpath;
+#endif
 
-	/* Fill in the fields of the device structure with ethernet-generic values. */
+	/* Fill in device structure with ethernet-generic values. */
 	ether_setup(dev);
 	dev->tx_queue_len = 0;
 	dev->flags |= IFF_NOARP;
 	dev->flags &= ~IFF_MULTICAST;
-#ifdef CONFIG_NET_FASTROUTE
-	dev->accept_fastpath = dummy_accept_fastpath;
-#endif
 
 	return 0;
 }
 
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *stats;
+	struct net_device_stats *stats = dev->priv;
 
-	stats = (struct net_device_stats *)dev->priv;
 	stats->tx_packets++;
 	stats->tx_bytes+=skb->len;
 
@@ -106,8 +105,9 @@
 	err=dev_alloc_name(&dev_dummy,"dummy%d");
 	if(err<0)
 		return err;
-	if (register_netdev(&dev_dummy) != 0)
-		return -EIO;
+	err = register_netdev(&dev_dummy);
+	if (err<0)
+		return err;
 	return 0;
 }
 
diff -urN linux-2.4.6-pre8/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- linux-2.4.6-pre8/drivers/net/eepro100.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/eepro100.c	Mon Dec  3 22:50:38 2001
@@ -43,7 +43,7 @@
 
 /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
    Lower values use more memory, but are faster. */
-#if defined(__alpha__) || defined(__sparc__)
+#if defined(__alpha__) || defined(__sparc__) || defined(__arm__)
 static int rx_copybreak = 1518;
 #else
 static int rx_copybreak = 200;
@@ -102,6 +102,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/mii.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -125,16 +126,16 @@
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(multicast_filter_limit, "i");
 MODULE_PARM_DESC(debug, "eepro100 debug level (0-6)");
-MODULE_PARM_DESC(options, "epro100: Bits 0-3: tranceiver type, bit 4: full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC(full_duplex, "epro100 full duplex setting(s) (1)");
-MODULE_PARM_DESC(congenb, "epro100  Enable congestion control (1)");
-MODULE_PARM_DESC(txfifo, "epro100 Tx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(rxfifo, "epro100 Rx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(txdmaccount, "epro100 Tx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rxdmaccount, "epro100 Rx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rx_copybreak, "epro100 copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "epro100 maximum events handled per interrupt");
-MODULE_PARM_DESC(multicast_filter_limit, "epro100 maximum number of filtered multicast addresses");
+MODULE_PARM_DESC(options, "eepro100: Bits 0-3: tranceiver type, bit 4: full duplex, bit 5: 100Mbps");
+MODULE_PARM_DESC(full_duplex, "eepro100 full duplex setting(s) (1)");
+MODULE_PARM_DESC(congenb, "eepro100  Enable congestion control (1)");
+MODULE_PARM_DESC(txfifo, "eepro100 Tx FIFO threshold in 4 byte units, (0-15)");
+MODULE_PARM_DESC(rxfifo, "eepro100 Rx FIFO threshold in 4 byte units, (0-15)");
+MODULE_PARM_DESC(txdmaccount, "eepro100 Tx DMA burst length; 128 - disable (0-128)");
+MODULE_PARM_DESC(rxdmaccount, "eepro100 Rx DMA burst length; 128 - disable (0-128)");
+MODULE_PARM_DESC(rx_copybreak, "eepro100 copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(max_interrupt_work, "eepro100 maximum events handled per interrupt");
+MODULE_PARM_DESC(multicast_filter_limit, "eepro100 maximum number of filtered multicast addresses");
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -155,8 +156,6 @@
 									(dev)->tx_timeout = (tf); \
 									(dev)->watchdog_timeo = (tm); \
 								} while(0)
-#define netif_device_attach(dev) netif_start_queue(dev)
-#define netif_device_detach(dev) netif_stop_queue(dev)
 
 #ifndef PCI_DEVICE_ID_INTEL_ID1029
 #define PCI_DEVICE_ID_INTEL_ID1029 0x1029
@@ -472,7 +471,6 @@
 	dma_addr_t last_rxf_dma;
 	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */
 	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
-	const char *product_name;
 	struct net_device_stats stats;
 	struct speedo_stats *lstats;
 	dma_addr_t lstats_dma;
@@ -800,7 +798,7 @@
 	/* Return the chip to its original power state. */
 	pci_set_power_state(pdev, acpi_idle_state);
 
-	pdev->driver_data = dev;
+	pci_set_drvdata (pdev, dev);
 
 	dev->base_addr = ioaddr;
 	dev->irq = pdev->irq;
@@ -1906,32 +1904,37 @@
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	int phy = sp->phy[0] & 0x1f;
 	int saved_acpi;
 	int t;
 
     switch(cmd) {
-	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
-		data[0] = phy;
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = phy;
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		/* FIXME: these operations need to be serialized with MDIO
 		   access from the timeout handler.
 		   They are currently serialized only with MDIO access from the
 		   timer routine.  2000/05/09 SAW */
 		saved_acpi = pci_set_power_state(sp->pdev, 0);
 		t = del_timer_sync(&sp->timer);
-		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		if (t)
 			add_timer(&sp->timer); /* may be set to the past  --SAW */
 		pci_set_power_state(sp->pdev, saved_acpi);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		saved_acpi = pci_set_power_state(sp->pdev, 0);
 		t = del_timer_sync(&sp->timer);
-		mdio_write(ioaddr, data[0], data[1], data[2]);
+		mdio_write(ioaddr, data->phy_id, data->reg_num, data->val_in);
 		if (t)
 			add_timer(&sp->timer); /* may be set to the past  --SAW */
 		pci_set_power_state(sp->pdev, saved_acpi);
@@ -2143,9 +2146,12 @@
 #ifdef CONFIG_PM
 static int eepro100_suspend(struct pci_dev *pdev, u32 state)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata (pdev);
 	long ioaddr = dev->base_addr;
 
+	if (!netif_running(dev))
+		return 0;
+
 	netif_device_detach(dev);
 	outl(PortPartialReset, ioaddr + SCBPort);
 	
@@ -2155,10 +2161,13 @@
 
 static int eepro100_resume(struct pci_dev *pdev)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata (pdev);
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
+	if (!netif_running(dev))
+		return 0;
+
 	/* I'm absolutely uncertain if this part of code may work.
 	   The problems are:
 	    - correct hardware reinitialization;
@@ -2178,7 +2187,7 @@
 
 static void __devexit eepro100_remove_one (struct pci_dev *pdev)
 {
-	struct net_device *dev = pdev->driver_data;
+	struct net_device *dev = pci_get_drvdata (pdev);
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	
 	unregister_netdev(dev);
diff -urN linux-2.4.6-pre8/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.4.6-pre8/drivers/net/epic100.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/epic100.c	Mon Dec  3 22:50:38 2001
@@ -45,13 +45,16 @@
 	* { fill me in }
 
 	LK1.1.8:
-	* ethtool support (jgarzik)
+	* ethtool driver info support (jgarzik)
+
+	LK1.1.9:
+	* MII ioctl support (jgarzik)
 
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.8"
-#define DRV_RELDATE	"May 18, 2001"
+#define DRV_VERSION	"1.11+LK1.1.9"
+#define DRV_RELDATE	"July 2, 2001"
 
 
 /* The user-configurable values.
@@ -1351,27 +1354,30 @@
 	return;
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+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)))
+
+	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;
+	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;
+		}
+
+	default:
+		break;
 	}
 
-        }
-	
 	return -EOPNOTSUPP;
 }
 
@@ -1379,20 +1385,24 @@
 {
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&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;
+
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = ep->phys[0] & 0x1f;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		if (! netif_running(dev)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 		}
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 #if 0					/* Just leave on if the ioctl() is ever used. */
 		if (! netif_running(dev)) {
 			outl(0x0008, ioaddr + GENCTL);
@@ -1400,16 +1410,18 @@
 		}
 #endif
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		if (! netif_running(dev)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 		}
-		if (data[0] == ep->phys[0]) {
-			u16 value = data[2];
-			switch (data[1]) {
+		if (data->phy_id == ep->phys[0]) {
+			u16 value = data->val_in;
+			switch (data->reg_num) {
 			case 0:
 				/* Check for autonegotiation on or reset. */
 				ep->duplex_lock = (value & 0x9000) ? 0 : 1;
@@ -1420,7 +1432,7 @@
 			}
 			/* Perhaps check_duplex(dev), depending on chip semantics. */
 		}
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 #if 0					/* Leave on if the ioctl() is used. */
 		if (! netif_running(dev)) {
 			outl(0x0008, ioaddr + GENCTL);
diff -urN linux-2.4.6-pre8/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- linux-2.4.6-pre8/drivers/net/fealnx.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/fealnx.c	Mon Dec  3 22:50:38 2001
@@ -17,7 +17,7 @@
 	http://www.scyld.com/network/pci-skeleton.html
 */
 
-static int debug = 0;		/* 1-> print debug message */
+static int debug;		/* 1-> print debug message */
 static int max_interrupt_work = 20;
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */
@@ -25,7 +25,7 @@
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme. */
 /* Setting to > 1518 effectively disables this feature.          */
-static int rx_copybreak = 0;
+static int rx_copybreak;
 
 /* Used to pass the media type, etc.                            */
 /* Both 'options[]' and 'full_duplex[]' should exist for driver */
@@ -71,6 +71,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/mii.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -1742,19 +1743,24 @@
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	u16 *data = (u16 *) & rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & 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;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = ((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);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!suser())
 			return -EPERM;
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/hamachi.c linux/drivers/net/hamachi.c
--- linux-2.4.6-pre8/drivers/net/hamachi.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/hamachi.c	Mon Dec  3 22:50:38 2001
@@ -164,6 +164,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
@@ -1873,24 +1874,29 @@
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	long ioaddr = dev->base_addr;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&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;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		/* TODO: Check the sequencing of this.  Might need to stop and
 		 * restart Rx and Tx engines. -KDU
 		 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	case SIOCDEVPRIVATE+3: { /* set rx,tx intr params */
 		u32 *d = (u32 *)&rq->ifr_data;
diff -urN linux-2.4.6-pre8/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c
--- linux-2.4.6-pre8/drivers/net/lasi_82596.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/lasi_82596.c	Mon Dec  3 22:50:38 2001
@@ -1515,13 +1515,13 @@
 {0,};
 static struct net_device dev_82596 =
 {
-	devicename,	/* device name inserted by drivers/net/net_init.c */
-	0, 0, 0, 0,
-	0, 0,		/* base, irq */
-	0, 0, 0, NULL, lasi_i82596_probe};
+	name: devicename,	/* device name inserted by drivers/net/net_init.c */
+	init: lasi_i82596_probe,
+};
 
 
 MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
 static int debug = -1;
 
 int init_module(void)
diff -urN linux-2.4.6-pre8/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c
--- linux-2.4.6-pre8/drivers/net/ncr885e.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/net/ncr885e.c	Mon Dec  3 22:50:38 2001
@@ -60,7 +60,7 @@
 #define EOP           (1<<7)   /* rx: end of packet written to buffer */
 
 int ncr885e_debug = NCR885E_DEBUG;
-static int print_version = 0;
+static int print_version;
 
 struct ncr885e_private {
 
@@ -94,7 +94,7 @@
 	spinlock_t lock;
 };
 
-static struct net_device *root_dev = NULL;
+static struct net_device *root_dev;
 
 static int ncr885e_open( struct net_device *dev );
 static int ncr885e_close( struct net_device *dev );
diff -urN linux-2.4.6-pre8/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c
--- linux-2.4.6-pre8/drivers/net/pci-skeleton.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/pci-skeleton.c	Mon Dec  3 22:50:38 2001
@@ -94,6 +94,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
+#include <linux/mii.h>
 #include <asm/io.h>
 
 #define NETDRV_VERSION		"1.0.0"
@@ -1782,31 +1783,34 @@
 static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdrv_private *tp = dev->priv;
-	u16 *data = (u16 *) & rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
 	unsigned long flags;
 	int rc = 0;
 
 	DPRINTK ("ENTER\n");
 
 	switch (cmd) {
-	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
-		data[0] = tp->phys[0] & 0x3f;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = tp->phys[0] & 0x3f;
 		/* Fall Through */
 
-	case SIOCDEVPRIVATE + 1:	/* Read the specified MII register. */
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
 		spin_lock_irqsave (&tp->lock, flags);
-		data[3] = mdio_read (dev, data[0] & 0x1f, data[1] & 0x1f);
+		data->val_out = mdio_read (dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		spin_unlock_irqrestore (&tp->lock, flags);
 		break;
 
-	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN)) {
 			rc = -EPERM;
 			break;
 		}
 
 		spin_lock_irqsave (&tp->lock, flags);
-		mdio_write (dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write (dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		spin_unlock_irqrestore (&tp->lock, flags);
 		break;
 
diff -urN linux-2.4.6-pre8/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- linux-2.4.6-pre8/drivers/net/pcnet32.c	Thu Apr 19 22:57:06 2001
+++ linux/drivers/net/pcnet32.c	Mon Dec  3 22:50:38 2001
@@ -47,6 +47,16 @@
 
 static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
 
+/*
+ * PCI device identifiers for "new style" Linux PCI Device Drivers
+ */
+static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = {
+    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, 0, 0, 0 },
+    { 0, }
+};
+
 static int pcnet32_debug = 1;
 static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
 
@@ -205,16 +215,6 @@
 
 #define PCNET32_TOTAL_SIZE 0x20
 
-/* some PCI ids */
-#ifndef PCI_DEVICE_ID_AMD_LANCE
-#define PCI_VENDOR_ID_AMD	      0x1022
-#define PCI_DEVICE_ID_AMD_LANCE	      0x2000
-#endif
-#ifndef PCI_DEVICE_ID_AMD_PCNETHOME
-#define PCI_DEVICE_ID_AMD_PCNETHOME   0x2001
-#endif
-
-
 #define CRC_POLYNOMIAL_LE 0xedb88320UL	/* Ethernet CRC, little endian */
 
 /* The PCNET32 Rx and Tx ring descriptors. */
@@ -319,16 +319,6 @@
     int (*probe1) (unsigned long, unsigned char, int, int, struct pci_dev *);
 };
 
-
-/*
- * PCI device identifiers for "new style" Linux PCI Device Drivers
- */
-static struct pci_device_id pcnet32_pci_tbl[] __devinitdata = {
-    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PCNETHOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-    { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, 0, 0, 0 },
-    { 0, }
-};
 
 MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl);
 
diff -urN linux-2.4.6-pre8/drivers/net/rcif.h linux/drivers/net/rcif.h
--- linux-2.4.6-pre8/drivers/net/rcif.h	Thu Jan 14 22:58:47 1999
+++ linux/drivers/net/rcif.h	Mon Dec  3 22:50:38 2001
@@ -38,39 +38,35 @@
 
 /* The following protocol revision # should be incremented every time
    a new protocol or new structures are used in this file. */
-int USER_PROTOCOL_REV = 2;     /* used to track different protocol revisions */
+int USER_PROTOCOL_REV = 2;	/* used to track different protocol revisions */
 
 /* define a single TCB & buffer */
-typedef struct                  /* a single buffer */
-{
-     U32 context;               /* context */
-     U32 scount;                /* segment count */
-     U32 size;                  /* segment size */
-     U32 addr;                  /* segment physical address */
-}
-__attribute__((packed))
-singleB, *psingleB ;
-typedef struct                  /* a single TCB */
-{
-     /*
-     **  +-----------------------+
-     **  |         1             |  one buffer in the TCB
-     **  +-----------------------+
-     **  |  <user's Context>     |  user's buffer reference
-     **  +-----------------------+
-     **  |         1             |  one segment buffer
-     **  +-----------------------+                            _
-     **  |    <buffer size>      |  size                       \ 
-     **  +-----------------------+                              \ segment descriptor
-     **  |  <physical address>   |  physical address of buffer  /
-     **  +-----------------------+                            _/
-     */
-     U32 bcount;                /* buffer count */
-     singleB b;                 /* buffer */
-
-}
-__attribute__((packed))
-singleTCB, *psingleTCB;
+typedef struct {		/* a single buffer */
+	U32 context;		/* context */
+	U32 scount;		/* segment count */
+	U32 size;		/* segment size */
+	U32 addr;		/* segment physical address */
+} __attribute__ ((packed))
+    singleB, *psingleB;
+typedef struct {		/* a single TCB */
+	/*
+	   **  +-----------------------+
+	   **  |         1             |  one buffer in the TCB
+	   **  +-----------------------+
+	   **  |  <user's Context>     |  user's buffer reference
+	   **  +-----------------------+
+	   **  |         1             |  one segment buffer
+	   **  +-----------------------+                            _
+	   **  |    <buffer size>      |  size                       \ 
+	   **  +-----------------------+                              \ segment descriptor
+	   **  |  <physical address>   |  physical address of buffer  /
+	   **  +-----------------------+                            _/
+	 */
+	U32 bcount;		/* buffer count */
+	singleB b;		/* buffer */
+
+} __attribute__ ((packed))
+    singleTCB, *psingleTCB;
 
 /*
    When adding new entries, please add all 5 related changes, since 
@@ -104,121 +100,119 @@
 typedef struct RC_user_tag RCuser_struct;
 
 /* 1) User structure entry */
-struct RC_user_tag
-{
-    int cmd;
-    union
-    {
-        /* GETINFO structure */
-        struct RCgetinfo_tag {
-            unsigned long int mem_start;
-            unsigned long int mem_end;
-            unsigned long int base_addr;
-            unsigned char irq;
-            unsigned char dma;
-            unsigned char port;
-        } RCgetinfo;                    /* <---- RCgetinfo */
-     
-        /* GETSPEED structure */
-        struct  RCgetspeed_tag {
-            U32 LinkSpeedCode;
-        } RCgetspeed;                   /* <---- RCgetspeed */
-  
-        /* SETSPEED structure */
-        struct RCsetspeed_tag {
-            U16 LinkSpeedCode;
-        } RCsetspeed;                   /* <---- RCsetspeed */
-
-        /* GETPROM structure */
-        struct  RCgetprom_tag {
-            U32 PromMode;
-        } RCgetprom;                   /* <---- RCgetprom */
-  
-        /* SETPROM structure */
-        struct RCsetprom_tag {
-            U16 PromMode;
-        } RCsetprom;                   /* <---- RCsetprom */
-
-        /* GETBROADCAST structure */
-        struct  RCgetbroadcast_tag {
-            U32 BroadcastMode;
-        } RCgetbroadcast;                   /* <---- RCgetbroadcast */
-  
-        /* SETBROADCAST structure */
-        struct RCsetbroadcast_tag {
-            U16 BroadcastMode;
-        } RCsetbroadcast;                   /* <---- RCsetbroadcast */
-
-        /* GETFIRMWAREVER structure */
-        #define FirmStringLen 80
-        struct RCgetfwver_tag {
-            U8 FirmString[FirmStringLen];
-        } RCgetfwver;                   /* <---- RCgetfwver */
-  
-        /* GETIPANDMASK structure */
-        struct RCgetipnmask_tag {
-            U32 IpAddr;
-            U32 NetMask;
-        } RCgetipandmask;               /* <---- RCgetipandmask */
-
-        /* SETIPANDMASK structure */
-        struct RCsetipnmask_tag {
-            U32 IpAddr;
-            U32 NetMask;
-        } RCsetipandmask;               /* <---- RCsetipandmask */
-
-        /* GETMAC structure */
-        #define MAC_SIZE 10
-        struct RCgetmac_tag {
-            U8 mac[MAC_SIZE];
-        } RCgetmac;                     /* <---- RCgetmac */
-
-        /* SETMAC structure */
-        struct RCsetmac_tag {
-            U8 mac[MAC_SIZE];
-        } RCsetmac;                     /* <---- RCsetmac */
-
-        /* GETLINKSTATUS structure */
-        struct RCgetlnkstatus_tag {
-            U32 ReturnStatus;
-        } RCgetlnkstatus;               /* <---- RCgetlnkstatus */
-
-        /* GETLINKSTATISTICS structure */
-        struct RCgetlinkstats_tag {
-            RCLINKSTATS StatsReturn;
-        } RCgetlinkstats;               /* <---- RCgetlinkstats */
-
-        /* DEFAULT structure (when no command was recognized) */
-        struct RCdefault_tag {
-            int rc;
-        } RCdefault;                    /* <---- RCdefault */
+struct RC_user_tag {
+	int cmd;
+	union {
+		/* GETINFO structure */
+		struct RCgetinfo_tag {
+			unsigned long int mem_start;
+			unsigned long int mem_end;
+			unsigned long int base_addr;
+			unsigned char irq;
+			unsigned char dma;
+			unsigned char port;
+		} RCgetinfo;	/* <---- RCgetinfo */
+
+		/* GETSPEED structure */
+		struct RCgetspeed_tag {
+			U32 LinkSpeedCode;
+		} RCgetspeed;	/* <---- RCgetspeed */
+
+		/* SETSPEED structure */
+		struct RCsetspeed_tag {
+			U16 LinkSpeedCode;
+		} RCsetspeed;	/* <---- RCsetspeed */
+
+		/* GETPROM structure */
+		struct RCgetprom_tag {
+			U32 PromMode;
+		} RCgetprom;	/* <---- RCgetprom */
+
+		/* SETPROM structure */
+		struct RCsetprom_tag {
+			U16 PromMode;
+		} RCsetprom;	/* <---- RCsetprom */
+
+		/* GETBROADCAST structure */
+		struct RCgetbroadcast_tag {
+			U32 BroadcastMode;
+		} RCgetbroadcast;	/* <---- RCgetbroadcast */
+
+		/* SETBROADCAST structure */
+		struct RCsetbroadcast_tag {
+			U16 BroadcastMode;
+		} RCsetbroadcast;	/* <---- RCsetbroadcast */
+
+		/* GETFIRMWAREVER structure */
+#define FirmStringLen 80
+		struct RCgetfwver_tag {
+			U8 FirmString[FirmStringLen];
+		} RCgetfwver;	/* <---- RCgetfwver */
+
+		/* GETIPANDMASK structure */
+		struct RCgetipnmask_tag {
+			U32 IpAddr;
+			U32 NetMask;
+		} RCgetipandmask;	/* <---- RCgetipandmask */
+
+		/* SETIPANDMASK structure */
+		struct RCsetipnmask_tag {
+			U32 IpAddr;
+			U32 NetMask;
+		} RCsetipandmask;	/* <---- RCsetipandmask */
+
+		/* GETMAC structure */
+#define MAC_SIZE 10
+		struct RCgetmac_tag {
+			U8 mac[MAC_SIZE];
+		} RCgetmac;	/* <---- RCgetmac */
+
+		/* SETMAC structure */
+		struct RCsetmac_tag {
+			U8 mac[MAC_SIZE];
+		} RCsetmac;	/* <---- RCsetmac */
+
+		/* GETLINKSTATUS structure */
+		struct RCgetlnkstatus_tag {
+			U32 ReturnStatus;
+		} RCgetlnkstatus;	/* <---- RCgetlnkstatus */
+
+		/* GETLINKSTATISTICS structure */
+		struct RCgetlinkstats_tag {
+			RCLINKSTATS StatsReturn;
+		} RCgetlinkstats;	/* <---- RCgetlinkstats */
+
+		/* DEFAULT structure (when no command was recognized) */
+		struct RCdefault_tag {
+			int rc;
+		} RCdefault;	/* <---- RCdefault */
 
-    } data;
+	} data;
 
-};   /* struct RC_user_tag { ... } */
+};				/* struct RC_user_tag { ... } */
 
 /* 2) User data entry */
 /* RCUD = RedCreek User Data */
-union RC_user_data_tag {        /* structure tags used are taken from RC_user_tag structure above */
-    struct RCgetinfo_tag      *getinfo;
-    struct RCgetspeed_tag     *getspeed;
-    struct RCgetprom_tag *getprom;
-    struct RCgetbroadcast_tag   *getbroadcast;
-    struct RCgetfwver_tag     *getfwver;
-    struct RCgetipnmask_tag   *getipandmask;
-    struct RCgetmac_tag       *getmac;
-    struct RCgetlnkstatus_tag *getlinkstatus;
-    struct RCgetlinkstats_tag *getlinkstatistics;
-    struct RCdefault_tag      *rcdefault;
-    struct RCsetspeed_tag     *setspeed;
-    struct RCsetprom_tag     *setprom;
-    struct RCsetbroadcast_tag     *setbroadcast;
-    struct RCsetipnmask_tag   *setipandmask;
-    struct RCsetmac_tag       *setmac;
-} _RC_user_data;  /* declare as a global, so the defines below will work */
+union RC_user_data_tag {	/* structure tags used are taken from RC_user_tag structure above */
+	struct RCgetinfo_tag *getinfo;
+	struct RCgetspeed_tag *getspeed;
+	struct RCgetprom_tag *getprom;
+	struct RCgetbroadcast_tag *getbroadcast;
+	struct RCgetfwver_tag *getfwver;
+	struct RCgetipnmask_tag *getipandmask;
+	struct RCgetmac_tag *getmac;
+	struct RCgetlnkstatus_tag *getlinkstatus;
+	struct RCgetlinkstats_tag *getlinkstatistics;
+	struct RCdefault_tag *rcdefault;
+	struct RCsetspeed_tag *setspeed;
+	struct RCsetprom_tag *setprom;
+	struct RCsetbroadcast_tag *setbroadcast;
+	struct RCsetipnmask_tag *setipandmask;
+	struct RCsetmac_tag *setmac;
+} _RC_user_data;		/* declare as a global, so the defines below will work */
 
 /* 3) Structure short-cut entry */
-/* define structure short-cuts */   /* structure names are taken from RC_user_tag structure above */
+/* define structure short-cuts *//* structure names are taken from RC_user_tag structure above */
 #define RCUS_GETINFO           data.RCgetinfo;
 #define RCUS_GETSPEED          data.RCgetspeed;
 #define RCUS_GETPROM           data.RCgetprom;
@@ -236,7 +230,7 @@
 #define RCUS_SETMAC            data.RCsetmac;
 
 /* 4) Data short-cut entry */
-/* define data short-cuts */    /* pointer names are from RC_user_data_tag union (just below RC_user_tag) */
+/* define data short-cuts *//* pointer names are from RC_user_data_tag union (just below RC_user_tag) */
 #define RCUD_GETINFO           _RC_user_data.getinfo
 #define RCUD_GETSPEED          _RC_user_data.getspeed
 #define RCUD_GETPROM           _RC_user_data.getprom
@@ -295,5 +289,4 @@
               RCUD_GETINFO->base_addr, RCUD_GETINFO->irq);
 */
 
-#endif   /* RCIF_H */
-
+#endif				/* RCIF_H */
diff -urN linux-2.4.6-pre8/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c
--- linux-2.4.6-pre8/drivers/net/rclanmtl.c	Sun Feb  4 10:05:30 2001
+++ linux/drivers/net/rclanmtl.c	Mon Dec  3 22:50:38 2001
@@ -42,10 +42,9 @@
 #include "rclanmtl.h"
 
  /* RedCreek LAN device Target ID */
-#define RC_LAN_TARGET_ID  0x10 
+#define RC_LAN_TARGET_ID  0x10
  /* RedCreek's OSM default LAN receive Initiator */
-#define DEFAULT_RECV_INIT_CONTEXT  0xA17  
-
+#define DEFAULT_RECV_INIT_CONTEXT  0xA17
 
 /*
 ** I2O message structures
@@ -102,17 +101,14 @@
 #define    I2O_EXEC_SYS_QUIESCE                        0xC3
 #define    I2O_EXEC_SYS_TAB_SET                        0xA3
 
-
  /* Init Outbound Q status */
 #define    I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS          0x01
 #define    I2O_EXEC_OUTBOUND_INIT_REJECTED             0x02
 #define    I2O_EXEC_OUTBOUND_INIT_FAILED               0x03
 #define    I2O_EXEC_OUTBOUND_INIT_COMPLETE             0x04
 
-
 #define    I2O_UTIL_NOP                                0x00
 
-
 /* I2O Get Status State values */
 
 #define    I2O_IOP_STATE_INITIALIZING                  0x01
@@ -123,7 +119,6 @@
 #define    I2O_IOP_STATE_FAILED                        0x10
 #define    I2O_IOP_STATE_FAULTED                       0x11
 
-
 /* Defines for Request Status Codes:  Table 3-1 Reply Status Codes.  */
 
 #define    I2O_REPLY_STATUS_SUCCESS                    0x00
@@ -139,7 +134,6 @@
 #define    I2O_REPLY_STATUS_TRANSACTION_ERROR          0x0A
 #define    I2O_REPLY_STATUS_PROGRESS_REPORT            0x80
 
-
 /* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/
 
 #define    I2O_DETAIL_STATUS_SUCCESS                        0x0000
@@ -203,17 +197,17 @@
 #define I2O_HOST_TID  0xB91
 
  /* RedCreek I2O private message codes */
-#define RC_PRIVATE_GET_MAC_ADDR     0x0001/**/ /* OBSOLETE */
+#define RC_PRIVATE_GET_MAC_ADDR     0x0001/**/	/* OBSOLETE */
 #define RC_PRIVATE_SET_MAC_ADDR     0x0002
 #define RC_PRIVATE_GET_NIC_STATS    0x0003
 #define RC_PRIVATE_GET_LINK_STATUS  0x0004
 #define RC_PRIVATE_SET_LINK_SPEED   0x0005
 #define RC_PRIVATE_SET_IP_AND_MASK  0x0006
-/* #define RC_PRIVATE_GET_IP_AND_MASK  0x0007 */ /* OBSOLETE */
+/* #define RC_PRIVATE_GET_IP_AND_MASK  0x0007 *//* OBSOLETE */
 #define RC_PRIVATE_GET_LINK_SPEED   0x0008
 #define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
 /* #define RC_PRIVATE_GET_MAC_ADDR     0x000A */
-#define RC_PRIVATE_GET_IP_AND_MASK  0x000B 
+#define RC_PRIVATE_GET_IP_AND_MASK  0x000B
 #define RC_PRIVATE_DEBUG_MSG        0x000C
 #define RC_PRIVATE_REPORT_DRIVER_CAPABILITY  0x000D
 #define RC_PRIVATE_SET_PROMISCUOUS_MODE  0x000e
@@ -223,30 +217,26 @@
 
 #define RC_PRIVATE_REBOOT           0x00FF
 
-
 /* I2O message header */
-typedef struct _I2O_MESSAGE_FRAME 
-{
-    U8                          VersionOffset;
-    U8                          MsgFlags;
-    U16                         MessageSize;
-    BF                          TargetAddress:I2O_TID_SZ;
-    BF                          InitiatorAddress:I2O_TID_SZ;
-    BF                          Function:I2O_FUNCTION_SZ;
-    U32                         InitiatorContext;
-    /* SGL[] */ 
-}
-I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME;
-
+typedef struct _I2O_MESSAGE_FRAME {
+	U8 VersionOffset;
+	U8 MsgFlags;
+	U16 MessageSize;
+	BF TargetAddress:I2O_TID_SZ;
+	BF InitiatorAddress:I2O_TID_SZ;
+	BF Function:I2O_FUNCTION_SZ;
+	U32 InitiatorContext;
+	/* SGL[] */
+} I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME;
 
  /* assumed a 16K minus 256 byte space for outbound queue message frames */
 #define MSG_FRAME_SIZE  512
 #define NMBR_MSG_FRAMES 30
 
  /* 
- ** in reserved space right after PAB in host memory is area for returning
- ** values from card 
- */
+    ** in reserved space right after PAB in host memory is area for returning
+    ** values from card 
+  */
 
 /*
 ** typedef NICSTAT
@@ -254,43 +244,37 @@
 ** Data structure for NIC statistics retruned from PCI card.  Data copied from
 ** here to user allocated RCLINKSTATS (see rclanmtl.h) structure.
 */
-typedef struct tag_NicStat 
-{
-    unsigned long   TX_good; 
-    unsigned long   TX_maxcol;
-    unsigned long   TX_latecol;
-    unsigned long   TX_urun;
-    unsigned long   TX_crs;         /* lost carrier sense */
-    unsigned long   TX_def;         /* transmit deferred */
-    unsigned long   TX_singlecol;   /* single collisions */
-    unsigned long   TX_multcol;
-    unsigned long   TX_totcol;
-    unsigned long   Rcv_good;
-    unsigned long   Rcv_CRCerr;
-    unsigned long   Rcv_alignerr;
-    unsigned long   Rcv_reserr;     /* rnr'd pkts */
-    unsigned long   Rcv_orun;
-    unsigned long   Rcv_cdt;
-    unsigned long   Rcv_runt;
-    unsigned long   dump_status;    /* last field directly from the chip */
-} 
-NICSTAT, *P_NICSTAT;
- 
-
-#define DUMP_DONE   0x0000A005      /* completed statistical dump */
-#define DUMP_CLEAR  0x0000A007      /* completed stat dump and clear counters */
+typedef struct tag_NicStat {
+	unsigned long TX_good;
+	unsigned long TX_maxcol;
+	unsigned long TX_latecol;
+	unsigned long TX_urun;
+	unsigned long TX_crs;	/* lost carrier sense */
+	unsigned long TX_def;	/* transmit deferred */
+	unsigned long TX_singlecol;	/* single collisions */
+	unsigned long TX_multcol;
+	unsigned long TX_totcol;
+	unsigned long Rcv_good;
+	unsigned long Rcv_CRCerr;
+	unsigned long Rcv_alignerr;
+	unsigned long Rcv_reserr;	/* rnr'd pkts */
+	unsigned long Rcv_orun;
+	unsigned long Rcv_cdt;
+	unsigned long Rcv_runt;
+	unsigned long dump_status;	/* last field directly from the chip */
+} NICSTAT, *P_NICSTAT;
 
+#define DUMP_DONE   0x0000A005	/* completed statistical dump */
+#define DUMP_CLEAR  0x0000A007	/* completed stat dump and clear counters */
 
 static volatile int msgFlag;
 
-
 /* local function prototypes */
-static void ProcessOutboundI2OMsg(PPAB pPab, U32 phyMsgAddr);
-static int FillI2OMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock);
-static int GetI2OStatus(PPAB pPab);
-static int SendI2OOutboundQInitMsg(PPAB pPab);
-static int SendEnableSysMsg(PPAB pPab);
-
+static void ProcessOutboundI2OMsg (PPAB pPab, U32 phyMsgAddr);
+static int FillI2OMsgSGLFromTCB (PU32 pMsg, PRCTCB pXmitCntrlBlock);
+static int GetI2OStatus (PPAB pPab);
+static int SendI2OOutboundQInitMsg (PPAB pPab);
+static int SendEnableSysMsg (PPAB pPab);
 
 /*
 ** =========================================================================
@@ -308,85 +292,89 @@
 ** =========================================================================
 */
 RC_RETURN
-RCInitI2OMsgLayer(struct net_device *dev,
-                  PFNTXCALLBACK  TransmitCallbackFunction,
-                  PFNRXCALLBACK  ReceiveCallbackFunction,
-                  PFNCALLBACK    RebootCallbackFunction)
-{
-    int result;
-    PPAB pPab; 
-    U32 pciBaseAddr = dev->base_addr;
-    PDPA pDpa = dev->priv;
-    PU8 p_msgbuf = pDpa->PLanApiPA;
-    PU8 p_phymsgbuf = (PU8)virt_to_bus((void *) p_msgbuf);    
-    
-    dprintk("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n"
-            "TransmitCallbackFunction:0x%08ulx  ReceiveCallbackFunction:0x%08ulx\n",
-            pDpa->id, pciBaseAddr, (u32)p_msgbuf, (u32)p_phymsgbuf, 
-	    (u32)TransmitCallbackFunction, (u32)ReceiveCallbackFunction);
-
-    
-    /* Check if this interface already initialized - if so, shut it down */
-    if (pDpa->pPab != NULL) {
-	    printk(KERN_WARNING "(rcpci45 driver:) pDpa->pPab [%d] != NULL\n", pDpa->id);
+RCInitI2OMsgLayer (struct net_device *dev,
+		   PFNTXCALLBACK TransmitCallbackFunction,
+		   PFNRXCALLBACK ReceiveCallbackFunction,
+		   PFNCALLBACK RebootCallbackFunction)
+{
+	int result;
+	PPAB pPab;
+	U32 pciBaseAddr = dev->base_addr;
+	PDPA pDpa = dev->priv;
+	PU8 p_msgbuf = pDpa->PLanApiPA;
+	PU8 p_phymsgbuf = (PU8) virt_to_bus ((void *) p_msgbuf);
+
+	dprintk
+	    ("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n"
+	     "TransmitCallbackFunction:0x%08ulx  ReceiveCallbackFunction:0x%08ulx\n",
+	     pDpa->id, pciBaseAddr, (u32) p_msgbuf, (u32) p_phymsgbuf,
+	     (u32) TransmitCallbackFunction, (u32) ReceiveCallbackFunction);
+
+	/* Check if this interface already initialized - if so, shut it down */
+	if (pDpa->pPab != NULL) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:) pDpa->pPab [%d] != NULL\n",
+			pDpa->id);
 /*          RCResetLANCard(pDpa->id, 0, (PU32)NULL, (PFNCALLBACK)NULL); */
-	    pDpa->pPab = NULL;
-    }
+		pDpa->pPab = NULL;
+	}
+
+	/* store adapter instance values in adapter block.
+	 * Adapter block is at beginning of message buffer */
 
-    /* store adapter instance values in adapter block.
-     * Adapter block is at beginning of message buffer */  
-    
-    pPab = kmalloc(sizeof(*pPab), GFP_KERNEL);
-    if (!pPab) {
-	    printk(KERN_ERR "(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n");
-	    result = RC_RTN_MALLOC_ERROR;
-	    goto err_out;
-    }
-
-    memset(pPab, 0, sizeof(*pPab));
-    pDpa->pPab = pPab;
-    pPab->p_atu = (PATU)pciBaseAddr;
-    pPab->pPci45LinBaseAddr =  (PU8)pciBaseAddr;
-    
-    /* Set outbound message frame addr */
-    pPab->outMsgBlockPhyAddr = (U32)p_phymsgbuf;
-    pPab->pLinOutMsgBlock    = (PU8)p_msgbuf;
-
-    /* store callback function addresses */
-    pPab->pTransCallbackFunc = TransmitCallbackFunction;
-    pPab->pRecvCallbackFunc  = ReceiveCallbackFunction;
-    pPab->pRebootCallbackFunc  = RebootCallbackFunction;
-    pPab->pCallbackFunc  = (PFNCALLBACK)NULL;
-
-    /*
-    ** Initialize I2O IOP
-    */
-    result = GetI2OStatus(pPab);
-    
-    if (result != RC_RTN_NO_ERROR)
-	    goto err_out_dealloc;
-
-    if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL) {
-        printk(KERN_INFO "(rcpci45 driver:) pPab->IOPState == op: resetting adapter\n");
-        RCResetLANCard(dev, 0, (PU32)NULL, (PFNCALLBACK)NULL);
-    }
-        
-    result = SendI2OOutboundQInitMsg(pPab);
-    
-    if (result != RC_RTN_NO_ERROR)
-	    goto err_out_dealloc;
-
-    result = SendEnableSysMsg(pPab);
-   
-    if (result != RC_RTN_NO_ERROR)
-	    goto err_out_dealloc;
-   
-    return RC_RTN_NO_ERROR;
-
- err_out_dealloc:
-    kfree(pPab);
- err_out:
-    return result;
+	pPab = kmalloc (sizeof (*pPab), GFP_KERNEL);
+	if (!pPab) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n");
+		result = RC_RTN_MALLOC_ERROR;
+		goto err_out;
+	}
+
+	memset (pPab, 0, sizeof (*pPab));
+	pDpa->pPab = pPab;
+	pPab->p_atu = (PATU) pciBaseAddr;
+	pPab->pPci45LinBaseAddr = (PU8) pciBaseAddr;
+
+	/* Set outbound message frame addr */
+	pPab->outMsgBlockPhyAddr = (U32) p_phymsgbuf;
+	pPab->pLinOutMsgBlock = (PU8) p_msgbuf;
+
+	/* store callback function addresses */
+	pPab->pTransCallbackFunc = TransmitCallbackFunction;
+	pPab->pRecvCallbackFunc = ReceiveCallbackFunction;
+	pPab->pRebootCallbackFunc = RebootCallbackFunction;
+	pPab->pCallbackFunc = (PFNCALLBACK) NULL;
+
+	/*
+	   ** Initialize I2O IOP
+	 */
+	result = GetI2OStatus (pPab);
+
+	if (result != RC_RTN_NO_ERROR)
+		goto err_out_dealloc;
+
+	if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL) {
+		printk (KERN_INFO
+			"(rcpci45 driver:) pPab->IOPState == op: resetting adapter\n");
+		RCResetLANCard (dev, 0, (PU32) NULL, (PFNCALLBACK) NULL);
+	}
+
+	result = SendI2OOutboundQInitMsg (pPab);
+
+	if (result != RC_RTN_NO_ERROR)
+		goto err_out_dealloc;
+
+	result = SendEnableSysMsg (pPab);
+
+	if (result != RC_RTN_NO_ERROR)
+		goto err_out_dealloc;
+
+	return RC_RTN_NO_ERROR;
+
+      err_out_dealloc:
+	kfree (pPab);
+      err_out:
+	return result;
 }
 
 /*
@@ -399,35 +387,34 @@
 ** queue is not emtpy.
 ** =========================================================================
 */
-#define i960_OUT_POST_Q_INT_BIT        0x0008 /* bit set masks interrupts */
+#define i960_OUT_POST_Q_INT_BIT        0x0008	/* bit set masks interrupts */
 
-RC_RETURN RCDisableI2OInterrupts(struct net_device *dev)
+RC_RETURN
+RCDisableI2OInterrupts (struct net_device * dev)
 {
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
 
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-        
-    pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT;
+	pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT;
 
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
 
-RC_RETURN RCEnableI2OInterrupts(struct net_device *dev)
+RC_RETURN
+RCEnableI2OInterrupts (struct net_device * dev)
 {
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
 
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT;
-    
-    return RC_RTN_NO_ERROR;
+	pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT;
 
-}
+	return RC_RTN_NO_ERROR;
 
+}
 
 /*
 ** =========================================================================
@@ -435,55 +422,53 @@
 ** =========================================================================
 */
 RC_RETURN
-RCI2OSendPacket(struct net_device *dev, U32 InitiatorContext, 
-		PRCTCB pTransCtrlBlock)
+RCI2OSendPacket (struct net_device * dev, U32 InitiatorContext,
+		 PRCTCB pTransCtrlBlock)
 {
-    U32 msgOffset;
-    PU32 pMsg;
-    int size;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    dprintk("RCI2OSendPacket()...\n");
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    /* get Inbound free Q entry - reading from In Q gets free Q entry */
-    /* offset to Msg Frame in PCI msg block */
-
-    msgOffset = pPab->p_atu->InQueue; 
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("RCI2OSendPacket(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-        
-    /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
-
-    if (size == -1) /* error processing TCB - send NOP msg */
-    {
-        dprintk("RCI2OSendPacket(): Error Rrocess TCB!\n");
-        pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
-        pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-        return RC_RTN_TCB_ERROR;
-    }
-    else /* send over msg header */
-    {    
-        pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
-        pMsg[1] = I2O_LAN_PACKET_SEND << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-        pMsg[2] = InitiatorContext;
-        pMsg[3] = 0;  /* batch reply */
-        /* post to Inbound Post Q */   
-        pPab->p_atu->InQueue = msgOffset;
-        return RC_RTN_NO_ERROR;
-    }
+	U32 msgOffset;
+	PU32 pMsg;
+	int size;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	dprintk ("RCI2OSendPacket()...\n");
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	/* get Inbound free Q entry - reading from In Q gets free Q entry */
+	/* offset to Msg Frame in PCI msg block */
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("RCI2OSendPacket(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	size = FillI2OMsgSGLFromTCB (pMsg + 4, pTransCtrlBlock);
+
+	if (size == -1) {	/* error processing TCB - send NOP msg */
+		dprintk ("RCI2OSendPacket(): Error Rrocess TCB!\n");
+		pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+		pMsg[1] =
+		    I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+		return RC_RTN_TCB_ERROR;
+	} else {		/* send over msg header */
+
+		pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST;	/* send over message size and flags */
+		pMsg[1] =
+		    I2O_LAN_PACKET_SEND << 24 | I2O_HOST_TID << 12 |
+		    RC_LAN_TARGET_ID;
+		pMsg[2] = InitiatorContext;
+		pMsg[3] = 0;	/* batch reply */
+		/* post to Inbound Post Q */
+		pPab->p_atu->InQueue = msgOffset;
+		return RC_RTN_NO_ERROR;
+	}
 }
- 
 
 /*
 ** =========================================================================
@@ -495,56 +480,57 @@
 ** =========================================================================
 */
 RC_RETURN
-RCPostRecvBuffers(struct net_device *dev, PRCTCB pTransCtrlBlock)
+RCPostRecvBuffers (struct net_device * dev, PRCTCB pTransCtrlBlock)
 {
-    U32 msgOffset;
-    PU32 pMsg;
-    int size;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-    dprintk("RCPostRecvBuffers()...\n");
-    
-    /* search for DeviceHandle */
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    /* get Inbound free Q entry - reading from In Q gets free Q entry */
-    /* offset to Msg Frame in PCI msg block */
-    msgOffset = pPab->p_atu->InQueue; 
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("RCPostRecvBuffers(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-    /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
-
-    if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */
-    {
-        dprintk("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
-        pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
-        pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-        /* post to Post Q */   
-        pPab->p_atu->InQueue = msgOffset;
-        return RC_RTN_TCB_ERROR;
-    }
-    else /* send over size msg header */
-    {    
-        pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
-        pMsg[1] = I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-        pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-        pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */
-        /* post to Post Q */   
-        pPab->p_atu->InQueue = msgOffset;
-        return RC_RTN_NO_ERROR;
-    }
+	U32 msgOffset;
+	PU32 pMsg;
+	int size;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	dprintk ("RCPostRecvBuffers()...\n");
+
+	/* search for DeviceHandle */
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	/* get Inbound free Q entry - reading from In Q gets free Q entry */
+	/* offset to Msg Frame in PCI msg block */
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("RCPostRecvBuffers(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	size = FillI2OMsgSGLFromTCB (pMsg + 4, pTransCtrlBlock);
+
+	if (size == -1) {	/* error prcessing TCB - send 3 DWORD private msg == NOP */
+		dprintk
+		    ("RCPostRecvBuffers(): Error Processing TCB! size = %d\n",
+		     size);
+		pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+		pMsg[1] =
+		    I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+		/* post to Post Q */
+		pPab->p_atu->InQueue = msgOffset;
+		return RC_RTN_TCB_ERROR;
+	} else {		/* send over size msg header */
+
+		pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST;	/* send over message size and flags */
+		pMsg[1] =
+		    I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 |
+		    RC_LAN_TARGET_ID;
+		pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+		pMsg[3] = *(PU32) pTransCtrlBlock;	/* number of packet buffers */
+		/* post to Post Q */
+		pPab->p_atu->InQueue = msgOffset;
+		return RC_RTN_NO_ERROR;
+	}
 }
 
-
 /*
 ** =========================================================================
 ** RCProcI2OMsgQ()
@@ -552,106 +538,112 @@
 ** Process I2O outbound message queue until empty.
 ** =========================================================================
 */
-void 
-RCProcI2OMsgQ(struct net_device *dev)
+void
+RCProcI2OMsgQ (struct net_device *dev)
 {
-    U32 phyAddrMsg;
-    PU8 p8Msg;
-    PU32 p32;
-    U16 count;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-    unsigned char debug_msg[20];
-    
-
-    if (pPab == NULL)
-        return;
-    
-    phyAddrMsg = pPab->p_atu->OutQueue;
-
-    while (phyAddrMsg != 0xFFFFFFFF)
-    {
-        p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
-        p32 = (PU32)p8Msg;
-        
-        dprintk("msg: 0x%x  0x%x \n", p8Msg[7], p32[5]);
-
-        /* Send Packet Reply Msg */
-        if (I2O_LAN_PACKET_SEND == p8Msg[7]) {  /* function code byte */
-            count = *(PU16)(p8Msg+2);
-            count -= p8Msg[0] >> 4;
-            /* status, count, context[], adapter */
-            (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, dev);
-        } else if (I2O_LAN_RECEIVE_POST == p8Msg[7]) { /* Receive Packet Reply Msg */
-		dprintk("I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx\n", (u32)pPab, (u32)p8Msg, (u32)p32);
-		dprintk("msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
-			p32[0], p32[1], p32[2], p32[3]);
-		dprintk("     0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
-			p32[4], p32[5], p32[6], p32[7]);
-		dprintk("     0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx\n",
-			p32[8], p32[9], p32[10], p32[11]);
-		/*  status, count, buckets remaining, packetParmBlock, adapter */
-		(*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, dev);      
-        } else if (I2O_LAN_RESET == p8Msg[7] || I2O_LAN_SHUTDOWN == p8Msg[7])
-		if (pPab->pCallbackFunc)
-			(*pPab->pCallbackFunc)(p8Msg[19],0,0,dev);
-		else		
-			pPab->pCallbackFunc = (PFNCALLBACK) 1;
-        else if (I2O_PRIVATE == p8Msg[7]) {
-	    dprintk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
-            switch (p32[5])
-            {
-            case RC_PRIVATE_DEBUG_MSG:
-                msgFlag = 1;
-                dprintk("Received I2O_PRIVATE msg\n");
-                debug_msg[15] = (p32[6]&0xff000000) >> 24;
-                debug_msg[14] = (p32[6]&0x00ff0000) >> 16;
-                debug_msg[13] = (p32[6]&0x0000ff00) >> 8;
-                debug_msg[12] = (p32[6]&0x000000ff);
-			      
-                debug_msg[11] = (p32[7]&0xff000000) >> 24;
-                debug_msg[10] = (p32[7]&0x00ff0000) >> 16;
-                debug_msg[ 9] = (p32[7]&0x0000ff00) >> 8;
-                debug_msg[ 8] = (p32[7]&0x000000ff);
-			      
-                debug_msg[ 7] = (p32[8]&0xff000000) >> 24;
-                debug_msg[ 6] = (p32[8]&0x00ff0000) >> 16;
-                debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8;
-                debug_msg[ 4] = (p32[8]&0x000000ff);
-			      
-                debug_msg[ 3] = (p32[9]&0xff000000) >> 24;
-                debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16;
-                debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8;
-                debug_msg[ 0] = (p32[9]&0x000000ff);
-
-                debug_msg[16] = '\0';
-                dprintk("%s", debug_msg);
-                break;
-            case RC_PRIVATE_REBOOT:
-                dprintk("Adapter reboot initiated...\n");
-                if (pPab->pRebootCallbackFunc)
-                    (*pPab->pRebootCallbackFunc)(0,0,0,dev);
-                break;
-            default:
-                printk(KERN_WARNING "(rcpci45 driver:) Unknown private I2O msg received: 0x%x\n", p32[5]);
-                break;
-            }
-        }
-
-        /* 
-        ** Process other Msg's
-        */
-        else
-            ProcessOutboundI2OMsg(pPab, phyAddrMsg);
-        
-        /* return MFA to outbound free Q*/
-        pPab->p_atu->OutQueue = phyAddrMsg;
-    
-        /* any more msgs? */
-        phyAddrMsg = pPab->p_atu->OutQueue;
-    }
+	U32 phyAddrMsg;
+	PU8 p8Msg;
+	PU32 p32;
+	U16 count;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+	unsigned char debug_msg[20];
+
+	if (pPab == NULL)
+		return;
+
+	phyAddrMsg = pPab->p_atu->OutQueue;
+
+	while (phyAddrMsg != 0xFFFFFFFF) {
+		p8Msg =
+		    pPab->pLinOutMsgBlock + (phyAddrMsg -
+					     pPab->outMsgBlockPhyAddr);
+		p32 = (PU32) p8Msg;
+
+		dprintk ("msg: 0x%x  0x%x \n", p8Msg[7], p32[5]);
+
+		/* Send Packet Reply Msg */
+		if (I2O_LAN_PACKET_SEND == p8Msg[7]) {	/* function code byte */
+			count = *(PU16) (p8Msg + 2);
+			count -= p8Msg[0] >> 4;
+			/* status, count, context[], adapter */
+			(*pPab->pTransCallbackFunc) (p8Msg[19], count, p32 + 5,
+						     dev);
+		} else if (I2O_LAN_RECEIVE_POST == p8Msg[7]) {	/* Receive Packet Reply Msg */
+			dprintk
+			    ("I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx\n",
+			     (u32) pPab, (u32) p8Msg, (u32) p32);
+			dprintk ("msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+				 p32[0], p32[1], p32[2], p32[3]);
+			dprintk ("     0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+				 p32[4], p32[5], p32[6], p32[7]);
+			dprintk ("     0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx\n",
+				 p32[8], p32[9], p32[10], p32[11]);
+			/*  status, count, buckets remaining, packetParmBlock, adapter */
+			(*pPab->pRecvCallbackFunc) (p8Msg[19], p8Msg[12],
+						    p32[5], p32 + 6, dev);
+		} else if (I2O_LAN_RESET == p8Msg[7]
+			   || I2O_LAN_SHUTDOWN == p8Msg[7])
+			if (pPab->pCallbackFunc)
+				(*pPab->pCallbackFunc) (p8Msg[19], 0, 0, dev);
+			else
+				pPab->pCallbackFunc = (PFNCALLBACK) 1;
+		else if (I2O_PRIVATE == p8Msg[7]) {
+			dprintk ("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
+			switch (p32[5]) {
+			case RC_PRIVATE_DEBUG_MSG:
+				msgFlag = 1;
+				dprintk ("Received I2O_PRIVATE msg\n");
+				debug_msg[15] = (p32[6] & 0xff000000) >> 24;
+				debug_msg[14] = (p32[6] & 0x00ff0000) >> 16;
+				debug_msg[13] = (p32[6] & 0x0000ff00) >> 8;
+				debug_msg[12] = (p32[6] & 0x000000ff);
+
+				debug_msg[11] = (p32[7] & 0xff000000) >> 24;
+				debug_msg[10] = (p32[7] & 0x00ff0000) >> 16;
+				debug_msg[9] = (p32[7] & 0x0000ff00) >> 8;
+				debug_msg[8] = (p32[7] & 0x000000ff);
+
+				debug_msg[7] = (p32[8] & 0xff000000) >> 24;
+				debug_msg[6] = (p32[8] & 0x00ff0000) >> 16;
+				debug_msg[5] = (p32[8] & 0x0000ff00) >> 8;
+				debug_msg[4] = (p32[8] & 0x000000ff);
+
+				debug_msg[3] = (p32[9] & 0xff000000) >> 24;
+				debug_msg[2] = (p32[9] & 0x00ff0000) >> 16;
+				debug_msg[1] = (p32[9] & 0x0000ff00) >> 8;
+				debug_msg[0] = (p32[9] & 0x000000ff);
+
+				debug_msg[16] = '\0';
+				dprintk ("%s", debug_msg);
+				break;
+			case RC_PRIVATE_REBOOT:
+				dprintk ("Adapter reboot initiated...\n");
+				if (pPab->pRebootCallbackFunc)
+					(*pPab->pRebootCallbackFunc) (0, 0, 0,
+								      dev);
+				break;
+			default:
+				printk (KERN_WARNING
+					"(rcpci45 driver:) Unknown private I2O msg received: 0x%x\n",
+					p32[5]);
+				break;
+			}
+		}
+
+		/* 
+		   ** Process other Msg's
+		 */
+		else
+			ProcessOutboundI2OMsg (pPab, phyAddrMsg);
+
+		/* return MFA to outbound free Q */
+		pPab->p_atu->OutQueue = phyAddrMsg;
+
+		/* any more msgs? */
+		phyAddrMsg = pPab->p_atu->OutQueue;
+	}
 }
 
-
 /*
 ** =========================================================================
 **  Returns LAN interface statistical counters to space provided by caller at
@@ -661,79 +653,75 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkStatistics(struct net_device *dev, 
-                    P_RCLINKSTATS StatsReturnAddr,
-                    PFNWAITCALLBACK WaitCallback)
-{
-    U32 msgOffset;
-    volatile U32 timeout;
-    volatile PU32 pMsg;
-    volatile PU32 p32, pReturnAddr;
-    P_NICSTAT pStats;
-    int i;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
+RCGetLinkStatistics (struct net_device *dev,
+		     P_RCLINKSTATS StatsReturnAddr,
+		     PFNWAITCALLBACK WaitCallback)
+{
+	U32 msgOffset;
+	volatile U32 timeout;
+	volatile PU32 pMsg;
+	volatile PU32 p32, pReturnAddr;
+	P_NICSTAT pStats;
+	int i;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
 /*dprintk("Get82558Stats() StatsReturnAddr:0x%08ulx\n", StatsReturnAddr); */
 
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    msgOffset = pPab->p_atu->InQueue;
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("Get8255XStats(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("Get8255XStats(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
 
-    /* calc virual address of msg - virual already mapped to physical */
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
 /*dprintk("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
 /*dprintk("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-    pMsg[3] = 0x112; /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-    
-    p32 = (PU32) pPab->outMsgBlockPhyAddr;
-    pStats = (P_NICSTAT)pPab->pLinOutMsgBlock;
-    pStats->dump_status = 0xFFFFFFFF;
-
-    /* post to Inbound Post Q */
-    pPab->p_atu->InQueue = msgOffset;
-
-    timeout = 100000;
-    while (1)
-    {
-        if (WaitCallback)
-            (*WaitCallback)();
-        
-	udelay(10);
-
-        if (pStats->dump_status != 0xFFFFFFFF)
-            break;
-
-        if (!timeout--)
-        {
-            dprintk("RCGet82558Stats() Timeout waiting for NIC statistics\n");
-            return RC_RTN_MSG_REPLY_TIMEOUT;
-        }
-    }
-    
-    pReturnAddr = (PU32)StatsReturnAddr;
-    
-    /* copy Nic stats to user's structure */
-    for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++)
-        pReturnAddr[i] = p32[i];
-   
-    return RC_RTN_NO_ERROR;     
-}
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+	pMsg[3] = 0x112;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	p32 = (PU32) pPab->outMsgBlockPhyAddr;
+	pStats = (P_NICSTAT) pPab->pLinOutMsgBlock;
+	pStats->dump_status = 0xFFFFFFFF;
+
+	/* post to Inbound Post Q */
+	pPab->p_atu->InQueue = msgOffset;
+
+	timeout = 100000;
+	while (1) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);
+
+		if (pStats->dump_status != 0xFFFFFFFF)
+			break;
+
+		if (!timeout--) {
+			dprintk
+			    ("RCGet82558Stats() Timeout waiting for NIC statistics\n");
+			return RC_RTN_MSG_REPLY_TIMEOUT;
+		}
+	}
+
+	pReturnAddr = (PU32) StatsReturnAddr;
+
+	/* copy Nic stats to user's structure */
+	for (i = 0; i < (int) sizeof (RCLINKSTATS) / 4; i++)
+		pReturnAddr[i] = p32[i];
 
+	return RC_RTN_NO_ERROR;
+}
 
 /*
 ** =========================================================================
@@ -741,67 +729,66 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkStatus(struct net_device *dev, PU32 ReturnAddr, 
-		PFNWAITCALLBACK WaitCallback)
+RCGetLinkStatus (struct net_device * dev, PU32 ReturnAddr,
+		 PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset;
-    volatile U32 timeout;
-    volatile PU32 pMsg;
-    volatile PU32 p32;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    dprintk("Get82558LinkStatus() ReturnPhysAddr:0x%08ulx\n", (u32)ReturnAddr);
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    msgOffset = pPab->p_atu->InQueue;
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("Get82558LinkStatus(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
+	U32 msgOffset;
+	volatile U32 timeout;
+	volatile PU32 pMsg;
+	volatile PU32 p32;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	dprintk ("Get82558LinkStatus() ReturnPhysAddr:0x%08ulx\n",
+		 (u32) ReturnAddr);
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("Get82558LinkStatus(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
 
-    /* calc virual address of msg - virual already mapped to physical */
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 /*dprintk("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
 /*dprintk("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-    pMsg[3] = 0x112; /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-
-    p32 = (PU32)pPab->pLinOutMsgBlock;
-    *p32 = 0xFFFFFFFF;
-    
-    /* post to Inbound Post Q */
-    pPab->p_atu->InQueue = msgOffset;
-
-    timeout = 100000;
-    while (1) {
-        if (WaitCallback)
-            (*WaitCallback)();
-        
-	udelay(10);
-
-        if (*p32 != 0xFFFFFFFF)
-            break;
-
-        if (!timeout--) {
-            dprintk("Timeout waiting for link status\n");
-            return RC_RTN_MSG_REPLY_TIMEOUT;
-        }
-    }
-    
-    *ReturnAddr = *p32; /* 1 = up 0 = down */
-    
-    return RC_RTN_NO_ERROR;
-    
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+	pMsg[3] = 0x112;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	p32 = (PU32) pPab->pLinOutMsgBlock;
+	*p32 = 0xFFFFFFFF;
+
+	/* post to Inbound Post Q */
+	pPab->p_atu->InQueue = msgOffset;
+
+	timeout = 100000;
+	while (1) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);
+
+		if (*p32 != 0xFFFFFFFF)
+			break;
+
+		if (!timeout--) {
+			dprintk ("Timeout waiting for link status\n");
+			return RC_RTN_MSG_REPLY_TIMEOUT;
+		}
+	}
+
+	*ReturnAddr = *p32;	/* 1 = up 0 = down */
+
+	return RC_RTN_NO_ERROR;
+
 }
 
 /*
@@ -813,73 +800,68 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetMAC(struct net_device *dev, PFNWAITCALLBACK WaitCallback)
+RCGetMAC (struct net_device * dev, PFNWAITCALLBACK WaitCallback)
 {
-    unsigned timeout;
-    U32      off;
-    PU8      mac = dev->dev_addr;
-    PU32     p;
-    U32      temp[2];
-    PPAB     pPab = ((PDPA)dev->priv)->pPab;
-    PATU     p_atu;
-    
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    p_atu = pPab->p_atu;
-
-    p_atu->EtherMacLow = 0;     /* first zero return data */
-    p_atu->EtherMacHi = 0;
-    
-    off = p_atu->InQueue;   /* get addresss of message */
- 
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-
-    p = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    dprintk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
-           (uint)p_atu, (uint)off, (uint)p);
-    /* setup private message */
-    p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
-    p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    p[2] = 0;               /* initiator context */
-    p[3] = 0x218;           /* transaction context */
-    p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR;
-
-
-    p_atu->InQueue = off;   /* send it to the I2O device */
-    dprintk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
-           (uint)p_atu, (uint)off, (uint)p);
-
-    /* wait for the rcpci45 board to update the info */
-    timeout = 1000000;
-    while (0 == p_atu->EtherMacLow) 
-    {
-        if (WaitCallback)
-            (*WaitCallback)();
-    
-	udelay(10);
-
-        if (!timeout--)
-        {
-            printk("rc_getmac: Timeout\n");
-            return RC_RTN_MSG_REPLY_TIMEOUT;
-        }
-    }
-    
-    /* read the mac address  */
-    temp[0] = p_atu->EtherMacLow;
-    temp[1] = p_atu->EtherMacHi;
-    memcpy((char *)mac, (char *)temp, 6);
+	unsigned timeout;
+	U32 off;
+	PU8 mac = dev->dev_addr;
+	PU32 p;
+	U32 temp[2];
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+	PATU p_atu;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	p_atu = pPab->p_atu;
+
+	p_atu->EtherMacLow = 0;	/* first zero return data */
+	p_atu->EtherMacHi = 0;
+
+	off = p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	p = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	dprintk ("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
+		 (uint) p_atu, (uint) off, (uint) p);
+	/* setup private message */
+	p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+	p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	p[2] = 0;		/* initiator context */
+	p[3] = 0x218;		/* transaction context */
+	p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR;
+
+	p_atu->InQueue = off;	/* send it to the I2O device */
+	dprintk ("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
+		 (uint) p_atu, (uint) off, (uint) p);
+
+	/* wait for the rcpci45 board to update the info */
+	timeout = 1000000;
+	while (0 == p_atu->EtherMacLow) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);
+
+		if (!timeout--) {
+			printk ("rc_getmac: Timeout\n");
+			return RC_RTN_MSG_REPLY_TIMEOUT;
+		}
+	}
+
+	/* read the mac address  */
+	temp[0] = p_atu->EtherMacLow;
+	temp[1] = p_atu->EtherMacHi;
+	memcpy ((char *) mac, (char *) temp, 6);
 
+	dprintk ("rc_getmac: 0x%x\n", (u32) mac);
 
-    dprintk("rc_getmac: 0x%x\n", (u32)mac);
-
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
 
- 
 /*
 ** =========================================================================
 ** RCSetMAC()
@@ -889,37 +871,35 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetMAC(struct net_device *dev, PU8 mac)
+RCSetMAC (struct net_device * dev, PU8 mac)
 {
-    U32  off;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup private message */
-    pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR;
-    pMsg[5] = *(unsigned *)mac;  /* first four bytes */
-    pMsg[6] = *(unsigned *)(mac + 4); /* last two bytes */
-    
-    pPab->p_atu->InQueue = off;   /* send it to the I2O device */
+	U32 off;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
-    return RC_RTN_NO_ERROR ;
-}
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	/* setup private message */
+	pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR;
+	pMsg[5] = *(unsigned *) mac;	/* first four bytes */
+	pMsg[6] = *(unsigned *) (mac + 4);	/* last two bytes */
 
+	pPab->p_atu->InQueue = off;	/* send it to the I2O device */
+
+	return RC_RTN_NO_ERROR;
+}
 
 /*
 ** =========================================================================
@@ -936,35 +916,35 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetLinkSpeed(struct net_device *dev, U16 LinkSpeedCode)
+RCSetLinkSpeed (struct net_device * dev, U16 LinkSpeedCode)
 {
-    U32  off;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-    
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED;
-    pMsg[5] = LinkSpeedCode;     /* link speed code */
+	U32 off;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED;
+	pMsg[5] = LinkSpeedCode;	/* link speed code */
 
-    pPab->p_atu->InQueue = off;   /* send it to the I2O device */
+	pPab->p_atu->InQueue = off;	/* send it to the I2O device */
 
-    return RC_RTN_NO_ERROR ;
+	return RC_RTN_NO_ERROR;
 }
+
 /*
 ** =========================================================================
 ** RCSetPromiscuousMode()
@@ -976,34 +956,35 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetPromiscuousMode(struct net_device *dev, U16 Mode)
+RCSetPromiscuousMode (struct net_device * dev, U16 Mode)
 {
-    U32  off;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-    
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_PROMISCUOUS_MODE;
-    pMsg[5] = Mode;     /* promiscuous mode setting */
+	U32 off;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_PROMISCUOUS_MODE;
+	pMsg[5] = Mode;		/* promiscuous mode setting */
 
-    pPab->p_atu->InQueue = off;   /* send it to the device */
+	pPab->p_atu->InQueue = off;	/* send it to the device */
 
-    return RC_RTN_NO_ERROR ;
+	return RC_RTN_NO_ERROR;
 }
+
 /*
 ** =========================================================================
 ** RCGetPromiscuousMode()
@@ -1017,67 +998,67 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, 
-		     PFNWAITCALLBACK WaitCallback)
+RCGetPromiscuousMode (struct net_device * dev, PU32 pMode,
+		      PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    msgOffset = pPab->p_atu->InQueue;
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-	printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-
-    /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0xff;
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE;
-    /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-   
-    /* post to Inbound Post Q */   
-
-    pPab->p_atu->InQueue = msgOffset;
-
-    /* wait for response */
-    timeout = 1000000;
-    while(1) {
-        if (WaitCallback)
-            (*WaitCallback)();
-
-	udelay(10);  /* please don't hog the bus!!! */
-
-        if (p32[0] != 0xff)
-            break;
-            
-        if (!timeout--)
-        {
-	    dprintk("Timeout waiting for promiscuous mode from adapter\n");
-            dprintk("0x%8x\n", p32[0]);
-            return RC_RTN_NO_LINK_SPEED;
-        }
-    }
+	U32 msgOffset, timeout;
+	PU32 pMsg;
+	volatile PU32 p32;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virtual address of msg - virtual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	/* virtual pointer to return buffer - clear first two dwords */
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0xff;
+
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE;
+	/* phys address to return status - area right after PAB */
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	/* post to Inbound Post Q */
+
+	pPab->p_atu->InQueue = msgOffset;
+
+	/* wait for response */
+	timeout = 1000000;
+	while (1) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] != 0xff)
+			break;
+
+		if (!timeout--) {
+			dprintk
+			    ("Timeout waiting for promiscuous mode from adapter\n");
+			dprintk ("0x%8x\n", p32[0]);
+			return RC_RTN_NO_LINK_SPEED;
+		}
+	}
 
-    /* get mode */
-    *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+	/* get mode */
+	*pMode = (U8) ((volatile PU8) p32)[0] & 0x0f;
 
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
+
 /*
 ** =========================================================================
 ** RCSetBroadcastMode()
@@ -1089,35 +1070,35 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetBroadcastMode(struct net_device *dev, U16 Mode)
+RCSetBroadcastMode (struct net_device * dev, U16 Mode)
 {
-    U32  off;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-    
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_BROADCAST_MODE;
-    pMsg[5] = Mode;     /* promiscuous mode setting */
+	U32 off;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
 
-    pPab->p_atu->InQueue = off;   /* send it to the device */
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_BROADCAST_MODE;
+	pMsg[5] = Mode;		/* promiscuous mode setting */
 
-    return RC_RTN_NO_ERROR ;
+	pPab->p_atu->InQueue = off;	/* send it to the device */
+
+	return RC_RTN_NO_ERROR;
 }
+
 /*
 ** =========================================================================
 ** RCGetBroadcastMode()
@@ -1131,66 +1112,66 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetBroadcastMode(struct net_device *dev, PU32 pMode, 
-		   PFNWAITCALLBACK WaitCallback)
+RCGetBroadcastMode (struct net_device * dev, PU32 pMode,
+		    PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    msgOffset = pPab->p_atu->InQueue;
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-
-    /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0xff;
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE;
-    /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-   
-    /* post to Inbound Post Q */   
-
-    pPab->p_atu->InQueue = msgOffset;
-
-    /* wait for response */
-    timeout = 1000000;
-    while(1) {
-        if (WaitCallback)
-            (*WaitCallback)();
-
-        udelay(10);      /* please don't hog the bus!!! */
-            
-        if (p32[0] != 0xff)
-            break;
-            
-        if (!timeout--)
-        {
-            printk(KERN_WARNING "(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter\n");
-            printk(KERN_WARNING "(rcpci45 driver:) 0x%8x\n", p32[0]);
-            return RC_RTN_NO_LINK_SPEED;
-        }
-    }
+	U32 msgOffset, timeout;
+	PU32 pMsg;
+	volatile PU32 p32;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virtual address of msg - virtual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	/* virtual pointer to return buffer - clear first two dwords */
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0xff;
+
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE;
+	/* phys address to return status - area right after PAB */
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	/* post to Inbound Post Q */
+
+	pPab->p_atu->InQueue = msgOffset;
+
+	/* wait for response */
+	timeout = 1000000;
+	while (1) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] != 0xff)
+			break;
+
+		if (!timeout--) {
+			printk (KERN_WARNING
+				"(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter\n");
+			printk (KERN_WARNING "(rcpci45 driver:) 0x%8x\n",
+				p32[0]);
+			return RC_RTN_NO_LINK_SPEED;
+		}
+	}
 
-    /* get mode */
-    *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+	/* get mode */
+	*pMode = (U8) ((volatile PU8) p32)[0] & 0x0f;
 
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
 
 /*
@@ -1208,69 +1189,67 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkSpeed(struct net_device *dev, PU32 pLinkSpeedCode, 
-	       PFNWAITCALLBACK WaitCallback)
+RCGetLinkSpeed (struct net_device * dev, PU32 pLinkSpeedCode,
+		PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
-    U8 IOPLinkSpeed;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    msgOffset = pPab->p_atu->InQueue;
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-
-    /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0xff;
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
-    /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-   
-    /* post to Inbound Post Q */   
-
-    pPab->p_atu->InQueue = msgOffset;
-
-    /* wait for response */
-    timeout = 1000000;
-    while(1) {
-        if (WaitCallback)
-            (*WaitCallback)();
-
-        udelay(10);      /* please don't hog the bus!!! */
-            
-        if (p32[0] != 0xff)
-            break;
-            
-        if (!timeout--)
-        {
-            dprintk("Timeout waiting for link speed from IOP\n");
-            dprintk("0x%8x\n", p32[0]);
-            return RC_RTN_NO_LINK_SPEED;
-        }
-    }
+	U32 msgOffset, timeout;
+	PU32 pMsg;
+	volatile PU32 p32;
+	U8 IOPLinkSpeed;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virtual address of msg - virtual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	/* virtual pointer to return buffer - clear first two dwords */
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0xff;
+
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
+	/* phys address to return status - area right after PAB */
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	/* post to Inbound Post Q */
+
+	pPab->p_atu->InQueue = msgOffset;
+
+	/* wait for response */
+	timeout = 1000000;
+	while (1) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] != 0xff)
+			break;
+
+		if (!timeout--) {
+			dprintk ("Timeout waiting for link speed from IOP\n");
+			dprintk ("0x%8x\n", p32[0]);
+			return RC_RTN_NO_LINK_SPEED;
+		}
+	}
 
-    /* get Link speed */
-    IOPLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f;
+	/* get Link speed */
+	IOPLinkSpeed = (U8) ((volatile PU8) p32)[0] & 0x0f;
 
-    *pLinkSpeedCode= IOPLinkSpeed;
+	*pLinkSpeedCode = IOPLinkSpeed;
 
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
 
 /*
@@ -1283,33 +1262,34 @@
 ** =========================================================================
 */
 RC_RETURN
-RCReportDriverCapability(struct net_device *dev, U32 capability)
+RCReportDriverCapability (struct net_device * dev, U32 capability)
 {
-    U32  off;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY;
-    pMsg[5] = capability;
+	U32 off;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
 
-    pPab->p_atu->InQueue = off;   /* send it to the I2O device */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
 
-    return RC_RTN_NO_ERROR ;
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] =
+	    RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY;
+	pMsg[5] = capability;
+
+	pPab->p_atu->InQueue = off;	/* send it to the I2O device */
+
+	return RC_RTN_NO_ERROR;
 }
 
 /*
@@ -1321,65 +1301,59 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetFirmwareVer(struct net_device *dev, PU8 pFirmString, 
-		 PFNWAITCALLBACK WaitCallback)
+RCGetFirmwareVer (struct net_device * dev, PU8 pFirmString,
+		  PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-
-    msgOffset = pPab->p_atu->InQueue;
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("RCGetFirmwareVer(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-
-    /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0xff;
-
-    /* setup private message */
-    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
-    /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-
-
-   
-    /* post to Inbound Post Q */   
-
-    pPab->p_atu->InQueue = msgOffset;
-
-    
-    /* wait for response */
-    timeout = 1000000;
-    while(1) {
-	if (WaitCallback)
-            (*WaitCallback)();
-            
-        udelay(10);     /* please don't hog the bus!!! */
-
-        if (p32[0] != 0xff)
-            break;
-            
-        if (!timeout--)
-        {
-            dprintk("Timeout waiting for link speed from IOP\n");
-            return RC_RTN_NO_FIRM_VER;
-        }
-    }
+	U32 msgOffset, timeout;
+	PU32 pMsg;
+	volatile PU32 p32;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	msgOffset = pPab->p_atu->InQueue;
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("RCGetFirmwareVer(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virtual address of msg - virtual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	/* virtual pointer to return buffer - clear first two dwords */
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0xff;
+
+	/* setup private message */
+	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
+	/* phys address to return status - area right after PAB */
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	/* post to Inbound Post Q */
+
+	pPab->p_atu->InQueue = msgOffset;
+
+	/* wait for response */
+	timeout = 1000000;
+	while (1) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] != 0xff)
+			break;
+
+		if (!timeout--) {
+			dprintk ("Timeout waiting for link speed from IOP\n");
+			return RC_RTN_NO_FIRM_VER;
+		}
+	}
 
-    strcpy(pFirmString, (PU8)p32);
-    return RC_RTN_NO_ERROR;
+	strcpy (pFirmString, (PU8) p32);
+	return RC_RTN_NO_ERROR;
 }
 
 /*
@@ -1395,56 +1369,53 @@
 **
 ** =========================================================================
 */
-RC_RETURN 
-RCResetLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, 
-	       PFNCALLBACK CallbackFunction)
-{
-    unsigned long off;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-    long timeout = 0;
-
-    
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pPab->pCallbackFunc = CallbackFunction;
-
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup message */
-    pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_LAN_RESET << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-    pMsg[3] = ResourceFlags << 16;   /* resource flags */
-
-    pPab->p_atu->InQueue = off;   /* send it to the I2O device */
-
-    if (CallbackFunction == (PFNCALLBACK)NULL)
-    {
-        /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
-           or until timer goes off */
-        while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
-        {
-            RCProcI2OMsgQ(dev);
-            udelay(1000);    /* please don't hog the bus!!! */
-            timeout++;
-            if (timeout > 10000)
-            {
-                break;
-            }
-        }
-        if (ReturnAddr != (PU32)NULL)
-            *ReturnAddr = (U32)pPab->pCallbackFunc;
-    }
+RC_RETURN
+RCResetLANCard (struct net_device * dev, U16 ResourceFlags, PU32 ReturnAddr,
+		PFNCALLBACK CallbackFunction)
+{
+	unsigned long off;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+	long timeout = 0;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	pPab->pCallbackFunc = CallbackFunction;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	/* setup message */
+	pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_LAN_RESET << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+	pMsg[3] = ResourceFlags << 16;	/* resource flags */
+
+	pPab->p_atu->InQueue = off;	/* send it to the I2O device */
+
+	if (CallbackFunction == (PFNCALLBACK) NULL) {
+		/* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
+		   or until timer goes off */
+		while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) {
+			RCProcI2OMsgQ (dev);
+			udelay (1000);	/* please don't hog the bus!!! */
+			timeout++;
+			if (timeout > 10000) {
+				break;
+			}
+		}
+		if (ReturnAddr != (PU32) NULL)
+			*ReturnAddr = (U32) pPab->pCallbackFunc;
+	}
 
-    return RC_RTN_NO_ERROR ;
+	return RC_RTN_NO_ERROR;
 }
+
 /*
 ** =========================================================================
 ** RCResetIOP()
@@ -1453,59 +1424,57 @@
 **
 ** =========================================================================
 */
-RC_RETURN 
-RCResetIOP(struct net_device *dev)
+RC_RETURN
+RCResetIOP (struct net_device * dev)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-    volatile PU32 p32;
-    
-    msgOffset = pPab->p_atu->InQueue;
-
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-
-    /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
-    pMsg[2] = 0; /* universal context */
-    pMsg[3] = 0; /* universal context */
-    pMsg[4] = 0; /* universal context */
-    pMsg[5] = 0; /* universal context */
-    /* phys address to return status - area right after PAB */
-    pMsg[6] = pPab->outMsgBlockPhyAddr;
-    pMsg[7] = 0;
-    pMsg[8] = 1;  /*  return 1 byte */
-
-    /* virual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0;
-    p32[1] = 0;
-
-    /* post to Inbound Post Q */   
-
-    pPab->p_atu->InQueue = msgOffset;
-
-    /* wait for response */
-    timeout = 1000000;
-    while(1) {        
-        udelay(10);     /* please don't hog the bus!!! */
-            
-        if (p32[0] || p32[1])
-            break;
-            
-        if (!timeout--)
-        {
-            dprintk("RCResetIOP timeout\n");
-            return RC_RTN_MSG_REPLY_TIMEOUT;
-        }
-    }
-    return RC_RTN_NO_ERROR;
+	U32 msgOffset, timeout;
+	PU32 pMsg;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+	volatile PU32 p32;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virtual address of msg - virtual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+	pMsg[2] = 0;		/* universal context */
+	pMsg[3] = 0;		/* universal context */
+	pMsg[4] = 0;		/* universal context */
+	pMsg[5] = 0;		/* universal context */
+	/* phys address to return status - area right after PAB */
+	pMsg[6] = pPab->outMsgBlockPhyAddr;
+	pMsg[7] = 0;
+	pMsg[8] = 1;		/*  return 1 byte */
+
+	/* virual pointer to return buffer - clear first two dwords */
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0;
+	p32[1] = 0;
+
+	/* post to Inbound Post Q */
+
+	pPab->p_atu->InQueue = msgOffset;
+
+	/* wait for response */
+	timeout = 1000000;
+	while (1) {
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] || p32[1])
+			break;
+
+		if (!timeout--) {
+			dprintk ("RCResetIOP timeout\n");
+			return RC_RTN_MSG_REPLY_TIMEOUT;
+		}
+	}
+	return RC_RTN_NO_ERROR;
 }
 
 /*
@@ -1521,57 +1490,55 @@
 **
 ** =========================================================================
 */
-RC_RETURN 
-RCShutdownLANCard(struct net_device *dev, U16 ResourceFlags, 
-		  PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
-{
-    volatile PU32 pMsg;
-    U32 off;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-    long timeout = 0;
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-
-    pPab->pCallbackFunc = CallbackFunction;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup message */
-    pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_LAN_SHUTDOWN << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-    pMsg[3] = ResourceFlags << 16;   /* resource flags */
-
-    pPab->p_atu->InQueue = off;   /* send it to the I2O device */
-
-    if (CallbackFunction == (PFNCALLBACK)NULL)
-    {
-        /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
-           or until timer goes off */
-        while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
-        {
-            RCProcI2OMsgQ(dev);
-            udelay(1000);     /* please don't hog the bus!!! */
-            timeout++;
-            if (timeout > 10000)
-            {
-		printk(KERN_WARNING "(rcpci45 driver:) RCShutdownLANCard(): timeout\n");
-                break;
-            }
-        }
-        if (ReturnAddr != (PU32)NULL)
-            *ReturnAddr = (U32)pPab->pCallbackFunc;
-    }
-    return RC_RTN_NO_ERROR ;
+RC_RETURN
+RCShutdownLANCard (struct net_device * dev, U16 ResourceFlags,
+		   PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+	volatile PU32 pMsg;
+	U32 off;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+	long timeout = 0;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	pPab->pCallbackFunc = CallbackFunction;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	/* setup message */
+	pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] =
+	    I2O_LAN_SHUTDOWN << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+	pMsg[3] = ResourceFlags << 16;	/* resource flags */
+
+	pPab->p_atu->InQueue = off;	/* send it to the I2O device */
+
+	if (CallbackFunction == (PFNCALLBACK) NULL) {
+		/* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
+		   or until timer goes off */
+		while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) {
+			RCProcI2OMsgQ (dev);
+			udelay (1000);	/* please don't hog the bus!!! */
+			timeout++;
+			if (timeout > 10000) {
+				printk (KERN_WARNING
+					"(rcpci45 driver:) RCShutdownLANCard(): timeout\n");
+				break;
+			}
+		}
+		if (ReturnAddr != (PU32) NULL)
+			*ReturnAddr = (U32) pPab->pCallbackFunc;
+	}
+	return RC_RTN_NO_ERROR;
 }
 
-
 /*
 ** =========================================================================
 ** RCSetRavlinIPandMask()
@@ -1585,34 +1552,33 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetRavlinIPandMask(struct net_device *dev, U32 ipAddr, U32 netMask)
+RCSetRavlinIPandMask (struct net_device * dev, U32 ipAddr, U32 netMask)
 {
-    volatile PU32 pMsg;
-    U32 off;
-    PPAB pPab = ((PDPA)dev->priv)->pPab;
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-
-    off = pPab->p_atu->InQueue; /* get addresss of message */
-    
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    /* setup private message */
-    pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;                 /* initiator context */
-    pMsg[3] = 0x219;             /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK;
-    pMsg[5] = ipAddr; 
-    pMsg[6] = netMask;
+	volatile PU32 pMsg;
+	U32 off;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	off = pPab->p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
 
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
 
-    pPab->p_atu->InQueue = off;   /* send it to the I2O device */
-    return RC_RTN_NO_ERROR ;
+	/* setup private message */
+	pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x219;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK;
+	pMsg[5] = ipAddr;
+	pMsg[6] = netMask;
+
+	pPab->p_atu->InQueue = off;	/* send it to the I2O device */
+	return RC_RTN_NO_ERROR;
 
 }
 
@@ -1625,69 +1591,76 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetRavlinIPandMask(struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, 
-                     PFNWAITCALLBACK WaitCallback)
+RCGetRavlinIPandMask (struct net_device * dev, PU32 pIpAddr, PU32 pNetMask,
+		      PFNWAITCALLBACK WaitCallback)
 {
-    unsigned timeout;
-    U32      off;
-    PU32     pMsg, p32;
-    PPAB     pPab = ((PDPA)dev->priv)->pPab;
-    PATU     p_atu;
-    
-    dprintk("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", (u32)pIpAddr, *pIpAddr);
-
-    if (pPab == NULL)
-        return RC_RTN_ADPTR_NOT_REGISTERED;
-    
-    p_atu = pPab->p_atu;
-    off = p_atu->InQueue;   /* get addresss of message */
- 
-    if (0xFFFFFFFF == off)
-        return RC_RTN_FREE_Q_EMPTY;
-
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    *p32 = 0xFFFFFFFF;
-
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
-
-    dprintk("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", (u32)p_atu, off, (u32)p32);
-    /* setup private message */
-    pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
-    pMsg[2] = 0;               /* initiator context */
-    pMsg[3] = 0x218;           /* transaction context */
-    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
-    pMsg[5] = pPab->outMsgBlockPhyAddr;
-
-    p_atu->InQueue = off;   /* send it to the I2O device */
-    dprintk("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", (u32)p_atu, off, (u32)p32);
-
-    /* wait for the rcpci45 board to update the info */
-    timeout = 100000;
-    while (0xffffffff == *p32)
-    {
-        if (WaitCallback)
-            (*WaitCallback)();
-
-	udelay(10);
-
-        if (!timeout--)
-        {
-            dprintk("RCGetRavlinIPandMask: Timeout\n");
-            return RC_RTN_MSG_REPLY_TIMEOUT;
-        }
-    }
-
-    dprintk("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx\n", p32[0], p32[1]);
-    
-    /* send IP and mask to user's space  */
-    *pIpAddr  = p32[0];
-    *pNetMask = p32[1];
-
+	unsigned timeout;
+	U32 off;
+	PU32 pMsg, p32;
+	PPAB pPab = ((PDPA) dev->priv)->pPab;
+	PATU p_atu;
+
+	dprintk
+	    ("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n",
+	     (u32) pIpAddr, *pIpAddr);
+
+	if (pPab == NULL)
+		return RC_RTN_ADPTR_NOT_REGISTERED;
+
+	p_atu = pPab->p_atu;
+	off = p_atu->InQueue;	/* get addresss of message */
+
+	if (0xFFFFFFFF == off)
+		return RC_RTN_FREE_Q_EMPTY;
+
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	*p32 = 0xFFFFFFFF;
+
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
+
+	dprintk
+	    ("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n",
+	     (u32) p_atu, off, (u32) p32);
+	/* setup private message */
+	pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+	pMsg[2] = 0;		/* initiator context */
+	pMsg[3] = 0x218;	/* transaction context */
+	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
+	pMsg[5] = pPab->outMsgBlockPhyAddr;
+
+	p_atu->InQueue = off;	/* send it to the I2O device */
+	dprintk
+	    ("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n",
+	     (u32) p_atu, off, (u32) p32);
+
+	/* wait for the rcpci45 board to update the info */
+	timeout = 100000;
+	while (0xffffffff == *p32) {
+		if (WaitCallback)
+			(*WaitCallback) ();
+
+		udelay (10);
+
+		if (!timeout--) {
+			dprintk ("RCGetRavlinIPandMask: Timeout\n");
+			return RC_RTN_MSG_REPLY_TIMEOUT;
+		}
+	}
+
+	dprintk
+	    ("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx\n",
+	     p32[0], p32[1]);
+
+	/* send IP and mask to user's space  */
+	*pIpAddr = p32[0];
+	*pNetMask = p32[1];
+
+	dprintk
+	    ("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n",
+	     (u32) pIpAddr, *pIpAddr);
 
-    dprintk("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", (u32)pIpAddr, *pIpAddr);
-
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
 
 /* 
@@ -1706,90 +1679,84 @@
 **
 ** =========================================================================
 */
-static int 
-SendI2OOutboundQInitMsg(PPAB pPab)
+static int
+SendI2OOutboundQInitMsg (PPAB pPab)
 {
-    U32 msgOffset, timeout, phyOutQFrames, i;
-    volatile PU32 pMsg;
-    volatile PU32 p32;
-    
-    
-    
-    msgOffset = pPab->p_atu->InQueue;
-
-    
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-    
-    
-    /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    dprintk("SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", (u32)pMsg, msgOffset);
-
-    pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
-    pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
-    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-    pMsg[3] = 0x106; /* transaction context */
-    pMsg[4] = 4096; /* Host page frame size */
-    pMsg[5] = MSG_FRAME_SIZE  << 16 | 0x80; /* outbound msg frame size and Initcode */
-    pMsg[6] = 0xD0000004;       /* simple sgl element LE, EOB */
-    /* phys address to return status - area right after PAB */
-    pMsg[7] = pPab->outMsgBlockPhyAddr;
-
-    /* virual pointer to return buffer - clear first two dwords */
-    p32 = (PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0;
-    
-    /* post to Inbound Post Q */   
-    pPab->p_atu->InQueue = msgOffset;
-    
-    /* wait for response */
-    timeout = 100000;
-    while(1)
-    {
-        udelay(10);      /* please don't hog the bus!!! */
-            
-        if (p32[0])
-            break;
-            
-        if (!timeout--)
-        {
-            dprintk("Timeout wait for InitOutQ InPrgress status from IOP\n");
-            return RC_RTN_NO_I2O_STATUS;
-        }
-    }
-
-    timeout = 100000;
-    while(1)
-    {
-	udelay(10);    /* please don't hog the bus!!! */
-            
-        if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE)
-            break;
-
-        if (!timeout--)
-        {
-            dprintk("Timeout wait for InitOutQ Complete status from IOP\n");
-            return RC_RTN_NO_I2O_STATUS;
-        }
-    }
-
-    /* load PCI outbound free Q with MF physical addresses */
-    phyOutQFrames = pPab->outMsgBlockPhyAddr;
-
-    for (i = 0; i < NMBR_MSG_FRAMES; i++)
-    {
-        pPab->p_atu->OutQueue = phyOutQFrames;
-        phyOutQFrames += MSG_FRAME_SIZE;
-    }
-    return RC_RTN_NO_ERROR;
+	U32 msgOffset, timeout, phyOutQFrames, i;
+	volatile PU32 pMsg;
+	volatile PU32 p32;
+
+	msgOffset = pPab->p_atu->InQueue;
+
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	dprintk
+	    ("SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n",
+	     (u32) pMsg, msgOffset);
+
+	pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
+	pMsg[1] =
+	    I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+	pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+	pMsg[3] = 0x106;	/* transaction context */
+	pMsg[4] = 4096;		/* Host page frame size */
+	pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80;	/* outbound msg frame size and Initcode */
+	pMsg[6] = 0xD0000004;	/* simple sgl element LE, EOB */
+	/* phys address to return status - area right after PAB */
+	pMsg[7] = pPab->outMsgBlockPhyAddr;
+
+	/* virual pointer to return buffer - clear first two dwords */
+	p32 = (PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0;
+
+	/* post to Inbound Post Q */
+	pPab->p_atu->InQueue = msgOffset;
+
+	/* wait for response */
+	timeout = 100000;
+	while (1) {
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0])
+			break;
+
+		if (!timeout--) {
+			dprintk
+			    ("Timeout wait for InitOutQ InPrgress status from IOP\n");
+			return RC_RTN_NO_I2O_STATUS;
+		}
+	}
+
+	timeout = 100000;
+	while (1) {
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE)
+			break;
+
+		if (!timeout--) {
+			dprintk
+			    ("Timeout wait for InitOutQ Complete status from IOP\n");
+			return RC_RTN_NO_I2O_STATUS;
+		}
+	}
+
+	/* load PCI outbound free Q with MF physical addresses */
+	phyOutQFrames = pPab->outMsgBlockPhyAddr;
+
+	for (i = 0; i < NMBR_MSG_FRAMES; i++) {
+		pPab->p_atu->OutQueue = phyOutQFrames;
+		phyOutQFrames += MSG_FRAME_SIZE;
+	}
+	return RC_RTN_NO_ERROR;
 }
 
-
 /*
 ** =========================================================================
 ** GetI2OStatus()
@@ -1798,80 +1765,83 @@
 **
 ** =========================================================================
 */
-static int 
-GetI2OStatus(PPAB pPab)
+static int
+GetI2OStatus (PPAB pPab)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
-    
-    
-    msgOffset = pPab->p_atu->InQueue; 
-    dprintk("GetI2OStatus: msg offset = 0x%x\n", msgOffset);
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("GetI2OStatus(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
-
-    /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-
-    pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
-    pMsg[2] = 0; /* universal context */
-    pMsg[3] = 0; /* universal context */
-    pMsg[4] = 0; /* universal context */
-    pMsg[5] = 0; /* universal context */
-    /* phys address to return status - area right after PAB */
-    pMsg[6] = pPab->outMsgBlockPhyAddr;
-    pMsg[7] = 0;
-    pMsg[8] = 88;  /*  return 88 bytes */
-
-    /* virual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
-    p32[0] = 0;
-    p32[1] = 0;
-
-    dprintk("GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx\n",
-            (u32)pMsg, msgOffset, pMsg[1], pMsg[6]);
-   
-    /* post to Inbound Post Q */   
-    pPab->p_atu->InQueue = msgOffset;
-    
-    dprintk("Return status to p32 = 0x%08ulx\n", (u32)p32);
-    
-    /* wait for response */
-    timeout = 1000000;
-    while(1) {
-        udelay(10);      /* please don't hog the bus!!! */
-            
-        if (p32[0] && p32[1])
-            break;
-            
-        if (!timeout--)
-        {
-            dprintk("Timeout waiting for status from IOP\n");
-            dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]);
-            dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]);
-            dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], p32[10], p32[11]);
-            return RC_RTN_NO_I2O_STATUS;
-        }
-    }
-            
-    dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]);
-    dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]);
-    dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], p32[10], p32[11]);
-    /* get IOP state */
-    pPab->IOPState = ((volatile PU8)p32)[10];
-    pPab->InboundMFrameSize  = ((volatile PU16)p32)[6];
-    
-    dprintk("IOP state 0x%02x InFrameSize = 0x%04x\n", 
-            pPab->IOPState, pPab->InboundMFrameSize);
-    return RC_RTN_NO_ERROR;
+	U32 msgOffset, timeout;
+	PU32 pMsg;
+	volatile PU32 p32;
+
+	msgOffset = pPab->p_atu->InQueue;
+	dprintk ("GetI2OStatus: msg offset = 0x%x\n", msgOffset);
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("GetI2OStatus(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
+
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
+
+	pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+	pMsg[2] = 0;		/* universal context */
+	pMsg[3] = 0;		/* universal context */
+	pMsg[4] = 0;		/* universal context */
+	pMsg[5] = 0;		/* universal context */
+	/* phys address to return status - area right after PAB */
+	pMsg[6] = pPab->outMsgBlockPhyAddr;
+	pMsg[7] = 0;
+	pMsg[8] = 88;		/*  return 88 bytes */
+
+	/* virual pointer to return buffer - clear first two dwords */
+	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
+	p32[0] = 0;
+	p32[1] = 0;
+
+	dprintk
+	    ("GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx\n",
+	     (u32) pMsg, msgOffset, pMsg[1], pMsg[6]);
+
+	/* post to Inbound Post Q */
+	pPab->p_atu->InQueue = msgOffset;
+
+	dprintk ("Return status to p32 = 0x%08ulx\n", (u32) p32);
+
+	/* wait for response */
+	timeout = 1000000;
+	while (1) {
+		udelay (10);	/* please don't hog the bus!!! */
+
+		if (p32[0] && p32[1])
+			break;
+
+		if (!timeout--) {
+			dprintk ("Timeout waiting for status from IOP\n");
+			dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+				 p32[0], p32[1], p32[2], p32[3]);
+			dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+				 p32[4], p32[5], p32[6], p32[7]);
+			dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+				 p32[8], p32[9], p32[10], p32[11]);
+			return RC_RTN_NO_I2O_STATUS;
+		}
+	}
+
+	dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1],
+		 p32[2], p32[3]);
+	dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5],
+		 p32[6], p32[7]);
+	dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9],
+		 p32[10], p32[11]);
+	/* get IOP state */
+	pPab->IOPState = ((volatile PU8) p32)[10];
+	pPab->InboundMFrameSize = ((volatile PU16) p32)[6];
+
+	dprintk ("IOP state 0x%02x InFrameSize = 0x%04x\n",
+		 pPab->IOPState, pPab->InboundMFrameSize);
+	return RC_RTN_NO_ERROR;
 }
 
-
 /*
 ** =========================================================================
 ** SendEnableSysMsg()
@@ -1879,38 +1849,38 @@
 **
 ** =========================================================================
 */
-static int 
-SendEnableSysMsg(PPAB pPab)
+static int
+SendEnableSysMsg (PPAB pPab)
 {
-    U32 msgOffset; 
-    volatile PU32 pMsg;
+	U32 msgOffset;
+	volatile PU32 pMsg;
 
-    msgOffset = pPab->p_atu->InQueue;
+	msgOffset = pPab->p_atu->InQueue;
 
-    if (msgOffset == 0xFFFFFFFF)
-    {
-        dprintk("SendEnableSysMsg(): Inbound Free Q empty!\n");
-        return RC_RTN_FREE_Q_EMPTY;
-    }
+	if (msgOffset == 0xFFFFFFFF) {
+		dprintk ("SendEnableSysMsg(): Inbound Free Q empty!\n");
+		return RC_RTN_FREE_Q_EMPTY;
+	}
 
-    /* calc virual address of msg - virual already mapped to physical */
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+	/* calc virual address of msg - virual already mapped to physical */
+	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
-    dprintk("SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", (u32)pMsg, msgOffset);
+	dprintk
+	    ("SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n",
+	     (u32) pMsg, msgOffset);
 
-    pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
-    pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
-    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-    pMsg[3] = 0x110; /* transaction context */
-    pMsg[4] = 0x50657465; /*  RedCreek Private */
+	pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+	pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+	pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+	pMsg[3] = 0x110;	/* transaction context */
+	pMsg[4] = 0x50657465;	/*  RedCreek Private */
 
-    /* post to Inbound Post Q */
-    pPab->p_atu->InQueue = msgOffset;
+	/* post to Inbound Post Q */
+	pPab->p_atu->InQueue = msgOffset;
 
-    return RC_RTN_NO_ERROR;
+	return RC_RTN_NO_ERROR;
 }
 
-
 /*
 ** =========================================================================
 ** FillI2OMsgFromTCB()
@@ -1921,91 +1891,82 @@
 ** fills in LAN SGL after Transaction Control Word or Bucket Count.
 ** =========================================================================
 */
-static int 
-FillI2OMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
+static int
+FillI2OMsgSGLFromTCB (PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
 {
-    unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
-    PU32 pTCB, pMsg;
+	unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
+	PU32 pTCB, pMsg;
 
-    /* SGL element flags */   
+	/* SGL element flags */
 #define EOB        0x40000000
 #define LE         0x80000000
 #define SIMPLE_SGL 0x10000000
 #define BC_PRESENT 0x01000000
 
-    pTCB = (PU32)pTransCtrlBlock;
-    pMsg = pMsgFrame;
-    nmbrDwords = 0;
-
-    dprintk("FillI2OMsgSGLFromTCBX\n");
-    dprintk("TCB  0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
-            pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
-    dprintk("pTCB 0x%08ulx, pMsg 0x%08ulx\n", (u32)pTCB, (u32)pMsg);
-    
-    nmbrBuffers = *pTCB++;
-    
-    if (!nmbrBuffers)
-    {
-        return -1;
-    }
-
-    do
-    {
-        context = *pTCB++; /* buffer tag (context) */
-        nmbrSeg = *pTCB++; /* number of segments */
-
-        if (!nmbrSeg)
-        {
-            return -1;
-        }
-        
-        flags = SIMPLE_SGL | BC_PRESENT;
-
-        if (1 == nmbrSeg)
-        {
-            flags |= EOB;
-        
-            if (1 == nmbrBuffers)
-                flags |= LE;
-        }    
-
-        /* 1st SGL buffer element has context */
-        pMsg[0] = pTCB[0] | flags ; /* send over count (segment size) */
-        pMsg[1] = context;
-        pMsg[2] = pTCB[1]; /* send buffer segment physical address */
-        nmbrDwords += 3;
-        pMsg += 3;
-        pTCB += 2;
-
-        
-        if (--nmbrSeg)
-        {
-            do
-            {
-                flags = SIMPLE_SGL;
-                
-                if (1 == nmbrSeg)
-                {
-                    flags |= EOB;
-                
-                    if (1 == nmbrBuffers)
-                        flags |= LE;
-                }    
-                
-                pMsg[0] = pTCB[0] | flags;  /* send over count */
-                pMsg[1] = pTCB[1];   /* send buffer segment physical address */
-                nmbrDwords += 2;
-                pTCB += 2;
-                pMsg += 2;
-        
-            } while (--nmbrSeg);
-        }
-        
-    } while (--nmbrBuffers);
-    
-    return nmbrDwords;
-}
+	pTCB = (PU32) pTransCtrlBlock;
+	pMsg = pMsgFrame;
+	nmbrDwords = 0;
+
+	dprintk ("FillI2OMsgSGLFromTCBX\n");
+	dprintk ("TCB  0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+		 pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
+	dprintk ("pTCB 0x%08ulx, pMsg 0x%08ulx\n", (u32) pTCB, (u32) pMsg);
+
+	nmbrBuffers = *pTCB++;
+
+	if (!nmbrBuffers) {
+		return -1;
+	}
+
+	do {
+		context = *pTCB++;	/* buffer tag (context) */
+		nmbrSeg = *pTCB++;	/* number of segments */
+
+		if (!nmbrSeg) {
+			return -1;
+		}
+
+		flags = SIMPLE_SGL | BC_PRESENT;
 
+		if (1 == nmbrSeg) {
+			flags |= EOB;
+
+			if (1 == nmbrBuffers)
+				flags |= LE;
+		}
+
+		/* 1st SGL buffer element has context */
+		pMsg[0] = pTCB[0] | flags;	/* send over count (segment size) */
+		pMsg[1] = context;
+		pMsg[2] = pTCB[1];	/* send buffer segment physical address */
+		nmbrDwords += 3;
+		pMsg += 3;
+		pTCB += 2;
+
+		if (--nmbrSeg) {
+			do {
+				flags = SIMPLE_SGL;
+
+				if (1 == nmbrSeg) {
+					flags |= EOB;
+
+					if (1 == nmbrBuffers)
+						flags |= LE;
+				}
+
+				pMsg[0] = pTCB[0] | flags;	/* send over count */
+				pMsg[1] = pTCB[1];	/* send buffer segment physical address */
+				nmbrDwords += 2;
+				pTCB += 2;
+				pMsg += 2;
+
+			} while (--nmbrSeg);
+		}
+
+	} while (--nmbrBuffers);
+
+	return nmbrDwords;
+}
 
 /*
 ** =========================================================================
@@ -2015,51 +1976,52 @@
 ** * change to msg structure *
 ** =========================================================================
 */
-static void 
-ProcessOutboundI2OMsg(PPAB pPab, U32 phyAddrMsg)
+static void
+ProcessOutboundI2OMsg (PPAB pPab, U32 phyAddrMsg)
 {
-    PU8 p8Msg;
-    PU32 p32;
+	PU8 p8Msg;
+	PU32 p32;
 /*      U16 count; */
-    
-    
-    p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
-    p32 = (PU32)p8Msg;
-    
-    dprintk("VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx\n", (u32)pPab, phyAddrMsg, (u32)p8Msg);
-    dprintk("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]);
-    dprintk("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]);
-
-    if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS)
-    {
-        dprintk("Message reply status not success\n");
-        return;
-    }
-    
-    switch (p8Msg[7] )  /* function code byte */
-    {
-    case I2O_EXEC_SYS_TAB_SET:
-        msgFlag = 1;
-        dprintk("Received I2O_EXEC_SYS_TAB_SET reply\n");
-        break;
-
-    case I2O_EXEC_HRT_GET:
-        msgFlag = 1;
-        dprintk("Received I2O_EXEC_HRT_GET reply\n");
-        break;
-        
-    case I2O_EXEC_LCT_NOTIFY:
-        msgFlag = 1;
-        dprintk("Received I2O_EXEC_LCT_NOTIFY reply\n");
-        break;
-        
-    case I2O_EXEC_SYS_ENABLE:
-        msgFlag = 1;
-        dprintk("Received I2O_EXEC_SYS_ENABLE reply\n");
-        break;
-
-    default:    
-        dprintk("Received UNKNOWN reply\n");
-        break;
-    }
+
+	p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+	p32 = (PU32) p8Msg;
+
+	dprintk
+	    ("VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx\n",
+	     (u32) pPab, phyAddrMsg, (u32) p8Msg);
+	dprintk ("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1],
+		 p32[2], p32[3]);
+	dprintk ("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5],
+		 p32[6], p32[7]);
+
+	if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS) {
+		dprintk ("Message reply status not success\n");
+		return;
+	}
+
+	switch (p8Msg[7]) {	/* function code byte */
+	case I2O_EXEC_SYS_TAB_SET:
+		msgFlag = 1;
+		dprintk ("Received I2O_EXEC_SYS_TAB_SET reply\n");
+		break;
+
+	case I2O_EXEC_HRT_GET:
+		msgFlag = 1;
+		dprintk ("Received I2O_EXEC_HRT_GET reply\n");
+		break;
+
+	case I2O_EXEC_LCT_NOTIFY:
+		msgFlag = 1;
+		dprintk ("Received I2O_EXEC_LCT_NOTIFY reply\n");
+		break;
+
+	case I2O_EXEC_SYS_ENABLE:
+		msgFlag = 1;
+		dprintk ("Received I2O_EXEC_SYS_ENABLE reply\n");
+		break;
+
+	default:
+		dprintk ("Received UNKNOWN reply\n");
+		break;
+	}
 }
diff -urN linux-2.4.6-pre8/drivers/net/rclanmtl.h linux/drivers/net/rclanmtl.h
--- linux-2.4.6-pre8/drivers/net/rclanmtl.h	Tue Mar  6 19:28:34 2001
+++ linux/drivers/net/rclanmtl.h	Mon Dec  3 22:50:38 2001
@@ -39,12 +39,12 @@
 
 /* Linux specific includes */
 #include <asm/types.h>
-#ifdef RC_LINUX_MODULE     /* linux modules need non-library version of string functions */
+#ifdef RC_LINUX_MODULE		/* linux modules need non-library version of string functions */
 #include <linux/string.h>
 #else
 #include <string.h>
 #endif
-#include <linux/delay.h> /* for udelay() */
+#include <linux/delay.h>	/* for udelay() */
 
 #include <linux/netdevice.h>
 #include <linux/if_ether.h>
@@ -62,152 +62,141 @@
 #define dprintk(args...) { }
 #endif
 
-
 /* Typedefs */
 
  /* scalar data types */
-typedef __u8		U8;
-typedef __u16		U16;
-typedef __u32		U32;
-typedef __u8*		PU8;
-typedef __u16*		PU16;
-typedef __u32*		PU32;
-typedef unsigned long   BF;
-typedef int             RC_RETURN;
+typedef __u8 U8;
+typedef __u16 U16;
+typedef __u32 U32;
+typedef __u8 *PU8;
+typedef __u16 *PU16;
+typedef __u32 *PU32;
+typedef unsigned long BF;
+typedef int RC_RETURN;
 
  /* 
- ** type PFNWAITCALLBACK
- **
- ** pointer to void function - type used for WaitCallback in some functions 
- */
-typedef void (*PFNWAITCALLBACK)(void);  /* void argument avoids compiler complaint */
-
- /*
- ** type PFNTXCALLBACK 
- **
- ** Pointer to user's transmit callback function.  This user function is
- ** called from RCProcI2OMsgQ() when packet have been transmitted from buffers
- ** given in the RCI2OSendPacket() function.  BufferContext is a pointer to
- ** an array of 32 bit context values.  These are the values the user assigned
- ** and passed in the TCB to the RCI2OSendPacket() function.  PcktCount
- ** indicates the number of buffer context values in the BufferContext[] array.
- ** The User's TransmitCallbackFunction should recover (put back in free queue)
- ** the packet buffers associated with the buffer context values.
- */
-typedef void (*PFNTXCALLBACK)(U32  Status,
-                              U16  PcktCount,
-                              PU32 BufferContext,
-                              struct net_device *);
+    ** type PFNWAITCALLBACK
+    **
+    ** pointer to void function - type used for WaitCallback in some functions 
+  */
+typedef void (*PFNWAITCALLBACK) (void);	/* void argument avoids compiler complaint */
+
+ /*
+    ** type PFNTXCALLBACK 
+    **
+    ** Pointer to user's transmit callback function.  This user function is
+    ** called from RCProcI2OMsgQ() when packet have been transmitted from buffers
+    ** given in the RCI2OSendPacket() function.  BufferContext is a pointer to
+    ** an array of 32 bit context values.  These are the values the user assigned
+    ** and passed in the TCB to the RCI2OSendPacket() function.  PcktCount
+    ** indicates the number of buffer context values in the BufferContext[] array.
+    ** The User's TransmitCallbackFunction should recover (put back in free queue)
+    ** the packet buffers associated with the buffer context values.
+  */
+typedef void (*PFNTXCALLBACK) (U32 Status,
+			       U16 PcktCount,
+			       PU32 BufferContext, struct net_device *);
 
  /* 
- ** type PFNRXCALLBACK 
- **
- ** Pointer to user's receive callback function.  This user function
- ** is called from RCProcI2OMsgQ() when packets have been received into
- ** previously posted packet buffers throught the RCPostRecvBuffers() function.
- ** The received callback function should process the Packet Descriptor Block
- ** pointed to by PacketDescBlock. See Packet Decription Block below.
- */
-typedef void (*PFNRXCALLBACK)(U32  Status,
-                              U8   PktCount,
-                              U32  BucketsRemain,
-                              PU32 PacketDescBlock,
-                              struct net_device *);
+    ** type PFNRXCALLBACK 
+    **
+    ** Pointer to user's receive callback function.  This user function
+    ** is called from RCProcI2OMsgQ() when packets have been received into
+    ** previously posted packet buffers throught the RCPostRecvBuffers() function.
+    ** The received callback function should process the Packet Descriptor Block
+    ** pointed to by PacketDescBlock. See Packet Decription Block below.
+  */
+typedef void (*PFNRXCALLBACK) (U32 Status,
+			       U8 PktCount,
+			       U32 BucketsRemain,
+			       PU32 PacketDescBlock, struct net_device *);
 
  /* 
- ** type PFNCALLBACK 
- **
- ** Pointer to user's generic callback function.  This user function
- ** can be passed to LANReset or LANShutdown and is called when the 
- ** the reset or shutdown is complete.
- ** Param1 and Param2 are invalid for LANReset and LANShutdown.
- */
-typedef void (*PFNCALLBACK)(U32  Status,
-                              U32  Param1,
-                              U32  Param2,
-                              struct net_device *dev);
+    ** type PFNCALLBACK 
+    **
+    ** Pointer to user's generic callback function.  This user function
+    ** can be passed to LANReset or LANShutdown and is called when the 
+    ** the reset or shutdown is complete.
+    ** Param1 and Param2 are invalid for LANReset and LANShutdown.
+  */
+typedef void (*PFNCALLBACK) (U32 Status,
+			     U32 Param1, U32 Param2, struct net_device * dev);
 
 /*
 **  Message Unit CSR definitions for RedCreek PCI45 board
 */
-typedef struct tag_rcatu 
-{
-    volatile unsigned long APICRegSel;  /* APIC Register Select */
-    volatile unsigned long reserved0;
-    volatile unsigned long APICWinReg;  /* APIC Window Register */
-    volatile unsigned long reserved1;
-    volatile unsigned long InMsgReg0;   /* inbound message register 0 */
-    volatile unsigned long InMsgReg1;   /* inbound message register 1 */
-    volatile unsigned long OutMsgReg0;  /* outbound message register 0 */
-    volatile unsigned long OutMsgReg1;  /* outbound message register 1 */
-    volatile unsigned long InDoorReg;   /* inbound doorbell register */
-    volatile unsigned long InIntStat;   /* inbound interrupt status register */
-    volatile unsigned long InIntMask;   /* inbound interrupt mask register */
-    volatile unsigned long OutDoorReg;  /* outbound doorbell register */
-    volatile unsigned long OutIntStat;  /* outbound interrupt status register */
-    volatile unsigned long OutIntMask;  /* outbound interrupt mask register */
-    volatile unsigned long reserved2;
-    volatile unsigned long reserved3;
-    volatile unsigned long InQueue;     /* inbound queue port */
-    volatile unsigned long OutQueue;    /* outbound queue port */
-    volatile unsigned long reserved4;
-    volatile unsigned long reserver5;
-    /* RedCreek extension */
-    volatile unsigned long EtherMacLow;
-    volatile unsigned long EtherMacHi;
-    volatile unsigned long IPaddr;
-    volatile unsigned long IPmask;
+typedef struct tag_rcatu {
+	volatile unsigned long APICRegSel;	/* APIC Register Select */
+	volatile unsigned long reserved0;
+	volatile unsigned long APICWinReg;	/* APIC Window Register */
+	volatile unsigned long reserved1;
+	volatile unsigned long InMsgReg0;	/* inbound message register 0 */
+	volatile unsigned long InMsgReg1;	/* inbound message register 1 */
+	volatile unsigned long OutMsgReg0;	/* outbound message register 0 */
+	volatile unsigned long OutMsgReg1;	/* outbound message register 1 */
+	volatile unsigned long InDoorReg;	/* inbound doorbell register */
+	volatile unsigned long InIntStat;	/* inbound interrupt status register */
+	volatile unsigned long InIntMask;	/* inbound interrupt mask register */
+	volatile unsigned long OutDoorReg;	/* outbound doorbell register */
+	volatile unsigned long OutIntStat;	/* outbound interrupt status register */
+	volatile unsigned long OutIntMask;	/* outbound interrupt mask register */
+	volatile unsigned long reserved2;
+	volatile unsigned long reserved3;
+	volatile unsigned long InQueue;	/* inbound queue port */
+	volatile unsigned long OutQueue;	/* outbound queue port */
+	volatile unsigned long reserved4;
+	volatile unsigned long reserver5;
+	/* RedCreek extension */
+	volatile unsigned long EtherMacLow;
+	volatile unsigned long EtherMacHi;
+	volatile unsigned long IPaddr;
+	volatile unsigned long IPmask;
 } *PATU;
 
  /* 
- ** typedef PAB
- **
- ** PCI Adapter Block - holds instance specific information.
- */
-typedef struct
-{
-    PATU             p_atu;                /* ptr to  ATU register block */
-    PU8              pPci45LinBaseAddr;
-    PU8              pLinOutMsgBlock;
-    U32              outMsgBlockPhyAddr; 
-    PFNTXCALLBACK    pTransCallbackFunc;
-    PFNRXCALLBACK    pRecvCallbackFunc;
-    PFNCALLBACK      pRebootCallbackFunc;
-    PFNCALLBACK      pCallbackFunc;
-    U16              IOPState;
-    U16              InboundMFrameSize;
+    ** typedef PAB
+    **
+    ** PCI Adapter Block - holds instance specific information.
+  */
+typedef struct {
+	PATU p_atu;		/* ptr to  ATU register block */
+	PU8 pPci45LinBaseAddr;
+	PU8 pLinOutMsgBlock;
+	U32 outMsgBlockPhyAddr;
+	PFNTXCALLBACK pTransCallbackFunc;
+	PFNRXCALLBACK pRecvCallbackFunc;
+	PFNCALLBACK pRebootCallbackFunc;
+	PFNCALLBACK pCallbackFunc;
+	U16 IOPState;
+	U16 InboundMFrameSize;
 } *PPAB;
 
 /*
  * Driver Private Area, DPA.
  */
-typedef struct
-{
-    U8     id;                        /* the AdapterID */
-
-    /* These two field are basically for the RCioctl function.
-     * I could not determine if they could be avoided. (RAA)*/
-    U32    pci_addr;               /* the pci address of the adapter */
-    U32    pci_addr_len;
-
-    struct timer_list timer;        /*  timer */
-    struct net_device_stats  stats; /* the statistics structure */
-    unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
-    unsigned char shutdown;
-    unsigned char reboot;
-    unsigned char nexus;
-    PU8    msgbuf;            /* Pointer to Lan Api Private Area */
-    PU8    PLanApiPA;         /* Pointer to Lan Api Private Area (aligned) */
-    PPAB   pPab;              /* Pointer to the PCI Adapter Block */
-} *PDPA;
-
+typedef struct {
+	U8 id;			/* the AdapterID */
 
+	/* These two field are basically for the RCioctl function.
+	 * I could not determine if they could be avoided. (RAA)*/
+	U32 pci_addr;		/* the pci address of the adapter */
+	U32 pci_addr_len;
+
+	struct timer_list timer;	/*  timer */
+	struct net_device_stats stats;	/* the statistics structure */
+	unsigned long numOutRcvBuffers;	/* number of outstanding receive buffers */
+	unsigned char shutdown;
+	unsigned char reboot;
+	unsigned char nexus;
+	PU8 msgbuf;		/* Pointer to Lan Api Private Area */
+	PU8 PLanApiPA;		/* Pointer to Lan Api Private Area (aligned) */
+	PPAB pPab;		/* Pointer to the PCI Adapter Block */
+} *PDPA;
 
 /* PCI/45 Configuration space values */
 #define RC_PCI45_VENDOR_ID  0x4916
 #define RC_PCI45_DEVICE_ID  0x1960
 
-
  /* RedCreek API function return values */
 #define RC_RTN_NO_ERROR             0
 #define RC_RTN_I2O_NOT_INIT         1
@@ -244,7 +233,6 @@
 #define    I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER     0x02
 #define    I2O_REPLY_STATUS_TRANSACTION_ERROR          0x0A
 
-
 /* DetailedStatusCode defines */
 #define    I2O_LAN_DSC_SUCCESS                         0x0000
 #define    I2O_LAN_DSC_DEVICE_FAILURE                  0x0001
@@ -264,7 +252,6 @@
 #define    I2O_LAN_DSC_DESTINATION_ADDRESS_OMITTED     0x000F
 #define    I2O_LAN_DSC_PARTIAL_PACKET_RETURNED         0x0010
 
-
 /*
 ** Packet Description Block   (Received packets)
 **
@@ -301,8 +288,6 @@
 **  
 */
 
-
-
 /*
 ** Transaction Control Block (TCB) structure
 **
@@ -368,13 +353,11 @@
 */
 
  /* Buffer Segment Descriptor */
-typedef struct
-{
-    U32 size;
-    U32 phyAddress;
-}
- BSD, *PBSD;
- 
+typedef struct {
+	U32 size;
+	U32 phyAddress;
+} BSD, *PBSD;
+
 typedef PU32 PRCTCB;
 /*
 ** -------------------------------------------------------------------------
@@ -382,41 +365,40 @@
 ** -------------------------------------------------------------------------
 */
 
-
  /*
- ** InitRCI2OMsgLayer()
- ** 
- ** Called once prior to using the I2O LAN message transport layer.  User 
- ** provides both the physical and virual address of a locked page buffer 
- ** that is used as a private buffer for the RedCreek I2O message
- ** transport layer.  This buffer must be a contigous memory block of a 
- ** minimum of 16K bytes and long word aligned.  The user also must provide
- ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
- ** system.  
- **
- ** Inputs:  dev - the net_device struct for the device.
- **          TransmitCallbackFunction - address of user's TX callback function
- **          ReceiveCallbackFunction  - address of user's RX callback function
- **          RebootCallbackFunction  - address of user's reboot callback function
- **
- */
-RC_RETURN RCInitI2OMsgLayer(struct net_device *dev,
-                            PFNTXCALLBACK TransmitCallbackFunction,
-                            PFNRXCALLBACK ReceiveCallbackFunction,
-                            PFNCALLBACK   RebootCallbackFunction);
-
- /*
- ** RCSetRavlinIPandMask()
- **
- ** Set the Ravlin 45/PCI cards IP address and network mask.
- **
- ** IP address and mask must be in network byte order.
- ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
- ** 0x04030201 and 0x00FFFFFF on a little endian machine.
- **
- */
-RC_RETURN RCSetRavlinIPandMask(struct net_device *dev, U32 ipAddr, U32 netMask);
-
+    ** InitRCI2OMsgLayer()
+    ** 
+    ** Called once prior to using the I2O LAN message transport layer.  User 
+    ** provides both the physical and virual address of a locked page buffer 
+    ** that is used as a private buffer for the RedCreek I2O message
+    ** transport layer.  This buffer must be a contigous memory block of a 
+    ** minimum of 16K bytes and long word aligned.  The user also must provide
+    ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
+    ** system.  
+    **
+    ** Inputs:  dev - the net_device struct for the device.
+    **          TransmitCallbackFunction - address of user's TX callback function
+    **          ReceiveCallbackFunction  - address of user's RX callback function
+    **          RebootCallbackFunction  - address of user's reboot callback function
+    **
+  */
+RC_RETURN RCInitI2OMsgLayer (struct net_device *dev,
+			     PFNTXCALLBACK TransmitCallbackFunction,
+			     PFNRXCALLBACK ReceiveCallbackFunction,
+			     PFNCALLBACK RebootCallbackFunction);
+
+ /*
+    ** RCSetRavlinIPandMask()
+    **
+    ** Set the Ravlin 45/PCI cards IP address and network mask.
+    **
+    ** IP address and mask must be in network byte order.
+    ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+    ** 0x04030201 and 0x00FFFFFF on a little endian machine.
+    **
+  */
+RC_RETURN RCSetRavlinIPandMask (struct net_device *dev, U32 ipAddr,
+				U32 netMask);
 
 /*
 ** =========================================================================
@@ -427,136 +409,130 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetRavlinIPandMask(struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, 
-                        PFNWAITCALLBACK WaitCallback);
+RCGetRavlinIPandMask (struct net_device *dev, PU32 pIpAddr, PU32 pNetMask,
+		      PFNWAITCALLBACK WaitCallback);
 
  /* 
- ** RCProcI2OMsgQ()
- ** 
- ** Called from user's polling loop or Interrupt Service Routine for a PCI 
- ** interrupt from the RedCreek PCI adapter.  User responsible for determining
- ** and hooking the PCI interrupt. This function will call the registered
- ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
- ** if a TX or RX transaction has completed.
- */
-void RCProcI2OMsgQ(struct net_device *dev);
-
-
- /*
- ** Disable and Enable I2O interrupts.  I2O interrupts are enabled at Init time
- ** but can be disabled and re-enabled through these two function calls.
- ** Packets will still be put into any posted received buffers and packets will
- ** be sent through RCI2OSendPacket() functions.  Disabling I2O interrupts
- ** will prevent hardware interrupt to host even though the outbound I2O msg
- ** queue is not emtpy.
- */
-RC_RETURN RCEnableI2OInterrupts(struct net_device *dev);
-RC_RETURN RCDisableI2OInterrupts(struct net_device *dev);
-
+    ** RCProcI2OMsgQ()
+    ** 
+    ** Called from user's polling loop or Interrupt Service Routine for a PCI 
+    ** interrupt from the RedCreek PCI adapter.  User responsible for determining
+    ** and hooking the PCI interrupt. This function will call the registered
+    ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
+    ** if a TX or RX transaction has completed.
+  */
+void RCProcI2OMsgQ (struct net_device *dev);
+
+ /*
+    ** Disable and Enable I2O interrupts.  I2O interrupts are enabled at Init time
+    ** but can be disabled and re-enabled through these two function calls.
+    ** Packets will still be put into any posted received buffers and packets will
+    ** be sent through RCI2OSendPacket() functions.  Disabling I2O interrupts
+    ** will prevent hardware interrupt to host even though the outbound I2O msg
+    ** queue is not emtpy.
+  */
+RC_RETURN RCEnableI2OInterrupts (struct net_device *dev);
+RC_RETURN RCDisableI2OInterrupts (struct net_device *dev);
 
  /* 
- ** RCPostRecvBuffers()
- ** 
- ** Post user's page locked buffers for use by the PCI adapter to
- ** return ethernet packets received from the LAN.  Transaction Control Block,
- ** provided by user, contains buffer descriptor(s) which includes a buffer
- ** context number along with buffer size and physical address.  See TCB above.
- ** The buffer context and actual packet length are returned to the 
- ** ReceiveCallbackFunction when packets have been received.  Buffers posted
- ** to the RedCreek adapter are considered owned by the adapter until the
- ** context is return to user through the ReceiveCallbackFunction.
- */
-RC_RETURN RCPostRecvBuffers(struct net_device *dev, PRCTCB pTransactionCtrlBlock);
+    ** RCPostRecvBuffers()
+    ** 
+    ** Post user's page locked buffers for use by the PCI adapter to
+    ** return ethernet packets received from the LAN.  Transaction Control Block,
+    ** provided by user, contains buffer descriptor(s) which includes a buffer
+    ** context number along with buffer size and physical address.  See TCB above.
+    ** The buffer context and actual packet length are returned to the 
+    ** ReceiveCallbackFunction when packets have been received.  Buffers posted
+    ** to the RedCreek adapter are considered owned by the adapter until the
+    ** context is return to user through the ReceiveCallbackFunction.
+  */
+RC_RETURN RCPostRecvBuffers (struct net_device *dev,
+			     PRCTCB pTransactionCtrlBlock);
 #define MAX_NMBR_POST_BUFFERS_PER_MSG 32
 
  /*
- ** RCI2OSendPacket()
- ** 
- ** Send user's ethernet packet from a locked page buffer.  
- ** Packet must have full MAC header, however without a CRC.  
- ** Initiator context is a user provided value that is returned 
- ** to the TransmitCallbackFunction when packet buffer is free.
- ** Transmit buffer are considered owned by the adapter until context's
- ** returned to user through the TransmitCallbackFunction.
- */
-RC_RETURN RCI2OSendPacket(struct net_device *dev, 
-                          U32 context, 
-                          PRCTCB pTransactionCtrlBlock);
-
+    ** RCI2OSendPacket()
+    ** 
+    ** Send user's ethernet packet from a locked page buffer.  
+    ** Packet must have full MAC header, however without a CRC.  
+    ** Initiator context is a user provided value that is returned 
+    ** to the TransmitCallbackFunction when packet buffer is free.
+    ** Transmit buffer are considered owned by the adapter until context's
+    ** returned to user through the TransmitCallbackFunction.
+  */
+RC_RETURN RCI2OSendPacket (struct net_device *dev,
+			   U32 context, PRCTCB pTransactionCtrlBlock);
 
  /* Ethernet Link Statistics structure */
-typedef struct tag_RC_link_stats
-{
-    U32 TX_good;      /* good transmit frames */
-    U32 TX_maxcol;    /* frames not TX due to MAX collisions */
-    U32 TX_latecol;   /* frames not TX due to late collisions */
-    U32 TX_urun;      /* frames not TX due to DMA underrun */
-    U32 TX_crs;       /* frames TX with lost carrier sense */
-    U32 TX_def;       /* frames deferred due to activity on link */
-    U32 TX_singlecol; /* frames TX with one and only on collision */
-    U32 TX_multcol;   /* frames TX with more than one collision */
-    U32 TX_totcol;    /* total collisions detected during TX */
-    U32 Rcv_good;     /* good frames received */
-    U32 Rcv_CRCerr;   /* frames RX and discarded with CRC errors */
-    U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
-    U32 Rcv_reserr;   /* good frames discarded due to no RX buffer */
-    U32 Rcv_orun;     /* RX frames lost due to FIFO overrun */
-    U32 Rcv_cdt;      /* RX frames with collision during RX */
-    U32 Rcv_runt;     /* RX frames shorter than 64 bytes */
-}
- RCLINKSTATS, *P_RCLINKSTATS;
-
- /*
- ** RCGetLinkStatistics()
- **
- ** Returns link statistics in user's structure at address StatsReturnAddr
- ** If given, not NULL, the function WaitCallback is called during the wait
- ** loop while waiting for the adapter to respond.
- */
-RC_RETURN RCGetLinkStatistics(struct net_device *dev,
-                              P_RCLINKSTATS StatsReturnAddr,
-                              PFNWAITCALLBACK WaitCallback);
+typedef struct tag_RC_link_stats {
+	U32 TX_good;		/* good transmit frames */
+	U32 TX_maxcol;		/* frames not TX due to MAX collisions */
+	U32 TX_latecol;		/* frames not TX due to late collisions */
+	U32 TX_urun;		/* frames not TX due to DMA underrun */
+	U32 TX_crs;		/* frames TX with lost carrier sense */
+	U32 TX_def;		/* frames deferred due to activity on link */
+	U32 TX_singlecol;	/* frames TX with one and only on collision */
+	U32 TX_multcol;		/* frames TX with more than one collision */
+	U32 TX_totcol;		/* total collisions detected during TX */
+	U32 Rcv_good;		/* good frames received */
+	U32 Rcv_CRCerr;		/* frames RX and discarded with CRC errors */
+	U32 Rcv_alignerr;	/* frames RX with alignment and CRC errors */
+	U32 Rcv_reserr;		/* good frames discarded due to no RX buffer */
+	U32 Rcv_orun;		/* RX frames lost due to FIFO overrun */
+	U32 Rcv_cdt;		/* RX frames with collision during RX */
+	U32 Rcv_runt;		/* RX frames shorter than 64 bytes */
+} RCLINKSTATS, *P_RCLINKSTATS;
+
+ /*
+    ** RCGetLinkStatistics()
+    **
+    ** Returns link statistics in user's structure at address StatsReturnAddr
+    ** If given, not NULL, the function WaitCallback is called during the wait
+    ** loop while waiting for the adapter to respond.
+  */
+RC_RETURN RCGetLinkStatistics (struct net_device *dev,
+			       P_RCLINKSTATS StatsReturnAddr,
+			       PFNWAITCALLBACK WaitCallback);
+
+ /*
+    ** RCGetLinkStatus()
+    **
+    ** Return link status, up or down, to user's location addressed by ReturnAddr.
+    ** If given, not NULL, the function WaitCallback is called during the wait
+    ** loop while waiting for the adapter to respond.
+  */
+RC_RETURN RCGetLinkStatus (struct net_device *dev,
+			   PU32 pReturnStatus, PFNWAITCALLBACK WaitCallback);
 
- /*
- ** RCGetLinkStatus()
- **
- ** Return link status, up or down, to user's location addressed by ReturnAddr.
- ** If given, not NULL, the function WaitCallback is called during the wait
- ** loop while waiting for the adapter to respond.
- */
-RC_RETURN RCGetLinkStatus(struct net_device *dev, 
-                          PU32 pReturnStatus,
-                          PFNWAITCALLBACK WaitCallback);
-                               
  /* Link Status defines - value returned in pReturnStatus */
 #define RC_LAN_LINK_STATUS_DOWN     0
 #define RC_LAN_LINK_STATUS_UP       1
 
  /*
- ** RCGetMAC()
- **
- ** Get the current MAC address assigned to user.  RedCreek Ravlin 45/PCI 
- ** has two MAC addresses.  One which is private to the PCI Card, and 
- ** another MAC which is given to the user as its link layer MAC address. The
- ** adapter runs in promiscous mode because of the dual address requirement.
- ** The MAC address is returned to the unsigned char array pointer to by mac.
- */
-RC_RETURN RCGetMAC(struct net_device *dev, PFNWAITCALLBACK WaitCallback);
-
- /*
- ** RCSetMAC()
- **
- ** Set a new user port MAC address.  This address will be returned on
- ** subsequent RCGetMAC() calls.
- */
-RC_RETURN RCSetMAC(struct net_device *dev, PU8 mac);
-
- /*
- ** RCSetLinkSpeed()
- **
- ** set adapter's link speed based on given input code.
- */
-RC_RETURN RCSetLinkSpeed(struct net_device *dev, U16 LinkSpeedCode);
+    ** RCGetMAC()
+    **
+    ** Get the current MAC address assigned to user.  RedCreek Ravlin 45/PCI 
+    ** has two MAC addresses.  One which is private to the PCI Card, and 
+    ** another MAC which is given to the user as its link layer MAC address. The
+    ** adapter runs in promiscous mode because of the dual address requirement.
+    ** The MAC address is returned to the unsigned char array pointer to by mac.
+  */
+RC_RETURN RCGetMAC (struct net_device *dev, PFNWAITCALLBACK WaitCallback);
+
+ /*
+    ** RCSetMAC()
+    **
+    ** Set a new user port MAC address.  This address will be returned on
+    ** subsequent RCGetMAC() calls.
+  */
+RC_RETURN RCSetMAC (struct net_device *dev, PU8 mac);
+
+ /*
+    ** RCSetLinkSpeed()
+    **
+    ** set adapter's link speed based on given input code.
+  */
+RC_RETURN RCSetLinkSpeed (struct net_device *dev, U16 LinkSpeedCode);
  /* Set link speed codes */
 #define LNK_SPD_AUTO_NEG_NWAY   0
 #define LNK_SPD_100MB_FULL      1
@@ -564,14 +540,11 @@
 #define LNK_SPD_10MB_FULL       3
 #define LNK_SPD_10MB_HALF       4
 
-
-
-
  /*
- ** RCGetLinkSpeed()
- **
- ** Return link speed code.
- */
+    ** RCGetLinkSpeed()
+    **
+    ** Return link speed code.
+  */
  /* Return link speed codes */
 #define LNK_SPD_UNKNOWN         0
 #define LNK_SPD_100MB_FULL      1
@@ -580,7 +553,8 @@
 #define LNK_SPD_10MB_HALF       4
 
 RC_RETURN
-RCGetLinkSpeed(struct net_device *dev, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
+RCGetLinkSpeed (struct net_device *dev, PU32 pLinkSpeedCode,
+		PFNWAITCALLBACK WaitCallback);
 /*
 ** =========================================================================
 ** RCSetPromiscuousMode(struct net_device *dev, U16 Mode)
@@ -593,8 +567,7 @@
 */
 #define PROMISCUOUS_MODE_OFF 0
 #define PROMISCUOUS_MODE_ON  1
-RC_RETURN
-RCSetPromiscuousMode(struct net_device *dev, U16 Mode);
+RC_RETURN RCSetPromiscuousMode (struct net_device *dev, U16 Mode);
 /*
 ** =========================================================================
 ** RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback)
@@ -608,7 +581,8 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+RCGetPromiscuousMode (struct net_device *dev, PU32 pMode,
+		      PFNWAITCALLBACK WaitCallback);
 
 /*
 ** =========================================================================
@@ -622,8 +596,7 @@
 */
 #define BROADCAST_MODE_OFF 0
 #define BROADCAST_MODE_ON  1
-RC_RETURN
-RCSetBroadcastMode(struct net_device *dev, U16 Mode);
+RC_RETURN RCSetBroadcastMode (struct net_device *dev, U16 Mode);
 /*
 ** =========================================================================
 ** RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback)
@@ -637,7 +610,8 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+RCGetBroadcastMode (struct net_device *dev, PU32 pMode,
+		    PFNWAITCALLBACK WaitCallback);
 /*
 ** =========================================================================
 ** RCReportDriverCapability(struct net_device *dev, U32 capability)
@@ -647,8 +621,7 @@
 **
 ** =========================================================================
 */
-RC_RETURN
-RCReportDriverCapability(struct net_device *dev, U32 capability);
+RC_RETURN RCReportDriverCapability (struct net_device *dev, U32 capability);
 
 /*
 ** RCGetFirmwareVer()
@@ -658,7 +631,8 @@
 ** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
 */
 RC_RETURN
-RCGetFirmwareVer(struct net_device *dev, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
+RCGetFirmwareVer (struct net_device *dev, PU8 pFirmString,
+		  PFNWAITCALLBACK WaitCallback);
 
 /*
 ** ----------------------------------------------
@@ -666,61 +640,61 @@
 ** ----------------------------------------------
 */
  /* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */
-#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS  0x0001 
+#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS  0x0001
 #define RC_RESOURCE_RETURN_PEND_TX_BUFFERS    0x0002
 
  /*
- ** RCResetLANCard()
- **
- ** Reset LAN card operation.  Causes a software reset of the ethernet
- ** controller and restarts the command and receive units. Depending on 
- ** the ResourceFlags given, the buffers are either returned to the
- ** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
- ** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
- ** posted after issuing this) OR the buffers are kept and reused by
- ** the ethernet controller. If CallbackFunction is not NULL, the function
- ** will be called when the reset is complete.  If the CallbackFunction is
- ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset 
- ** to complete (please disable I2O interrupts during this method).
- ** Any outstanding transmit or receive buffers that are complete will be
- ** returned via the normal reply messages before the requested resource
- ** buffers are returned.
- ** A call to RCPostRecvBuffers() is needed to return the ethernet to full
- ** operation if the receive buffers were returned during LANReset.
- ** Note: The IOP status is not affected by a LAN reset.
- */
-RC_RETURN RCResetLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
-
+    ** RCResetLANCard()
+    **
+    ** Reset LAN card operation.  Causes a software reset of the ethernet
+    ** controller and restarts the command and receive units. Depending on 
+    ** the ResourceFlags given, the buffers are either returned to the
+    ** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
+    ** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
+    ** posted after issuing this) OR the buffers are kept and reused by
+    ** the ethernet controller. If CallbackFunction is not NULL, the function
+    ** will be called when the reset is complete.  If the CallbackFunction is
+    ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset 
+    ** to complete (please disable I2O interrupts during this method).
+    ** Any outstanding transmit or receive buffers that are complete will be
+    ** returned via the normal reply messages before the requested resource
+    ** buffers are returned.
+    ** A call to RCPostRecvBuffers() is needed to return the ethernet to full
+    ** operation if the receive buffers were returned during LANReset.
+    ** Note: The IOP status is not affected by a LAN reset.
+  */
+RC_RETURN RCResetLANCard (struct net_device *dev, U16 ResourceFlags,
+			  PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+ /*
+    ** RCShutdownLANCard()
+    **
+    ** Shutdown LAN card operation and put into an idle (suspended) state.
+    ** The LAN card is restarted with RCResetLANCard() function.
+    ** Depending on the ResourceFlags given, the buffers are either returned 
+    ** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 
+    ** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
+    ** posted after issuing this) OR the buffers are kept and reused by
+    ** the ethernet controller. If CallbackFunction is not NULL, the function
+    ** will be called when the reset is complete.  If the CallbackFunction is
+    ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset 
+    ** to complete (please disable I2O interrupts during this method).
+    ** Any outstanding transmit or receive buffers that are complete will be
+    ** returned via the normal reply messages before the requested resource
+    ** buffers are returned.
+    ** Note: The IOP status is not affected by a LAN shutdown.
+  */
+RC_RETURN
+RCShutdownLANCard (struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr,
+		   PFNCALLBACK CallbackFunction);
 
  /*
- ** RCShutdownLANCard()
- **
- ** Shutdown LAN card operation and put into an idle (suspended) state.
- ** The LAN card is restarted with RCResetLANCard() function.
- ** Depending on the ResourceFlags given, the buffers are either returned 
- ** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 
- ** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
- ** posted after issuing this) OR the buffers are kept and reused by
- ** the ethernet controller. If CallbackFunction is not NULL, the function
- ** will be called when the reset is complete.  If the CallbackFunction is
- ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset 
- ** to complete (please disable I2O interrupts during this method).
- ** Any outstanding transmit or receive buffers that are complete will be
- ** returned via the normal reply messages before the requested resource
- ** buffers are returned.
- ** Note: The IOP status is not affected by a LAN shutdown.
- */                                      
-RC_RETURN 
-RCShutdownLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
-
- /*
- ** RCResetIOP();
- **     Initializes IOPState to I2O_IOP_STATE_RESET.
- **     Stops access to outbound message Q.
- **     Discards any outstanding transmit or posted receive buffers.
- **     Clears outbound message Q. 
- */
-RC_RETURN 
-RCResetIOP(struct net_device *dev);
+    ** RCResetIOP();
+    **     Initializes IOPState to I2O_IOP_STATE_RESET.
+    **     Stops access to outbound message Q.
+    **     Discards any outstanding transmit or posted receive buffers.
+    **     Clears outbound message Q. 
+  */
+RC_RETURN RCResetIOP (struct net_device *dev);
 
-#endif /* RCLANMTL_H */
+#endif				/* RCLANMTL_H */
diff -urN linux-2.4.6-pre8/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- linux-2.4.6-pre8/drivers/net/rcpci45.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/rcpci45.c	Mon Dec  3 22:50:38 2001
@@ -57,14 +57,12 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/timer.h>
-#include <asm/irq.h>            /* For NR_IRQS only. */
+#include <asm/irq.h>		/* For NR_IRQS only. */
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
-
-
 static char version[] __initdata =
-"RedCreek Communications PCI linux driver version 2.03\n";
+    "RedCreek Communications PCI linux driver version 2.03\n";
 
 #define RC_LINUX_MODULE
 #include "rclanmtl.h"
@@ -78,339 +76,349 @@
 #define RC_PCI45_VENDOR_ID  0x4916
 #define RC_PCI45_DEVICE_ID  0x1960
 
-#define MAX_ETHER_SIZE        1520  
+#define MAX_ETHER_SIZE        1520
 #define MAX_NMBR_RCV_BUFFERS    96
 #define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16
-#define BD_SIZE 3           /* Bucket Descriptor size */
-#define BD_LEN_OFFSET 2     /* Bucket Descriptor offset to length field */
-
+#define BD_SIZE 3		/* Bucket Descriptor size */
+#define BD_LEN_OFFSET 2		/* Bucket Descriptor offset to length field */
 
 /* RedCreek LAN device Target ID */
-#define RC_LAN_TARGET_ID  0x10 
+#define RC_LAN_TARGET_ID  0x10
 /* RedCreek's OSM default LAN receive Initiator */
-#define DEFAULT_RECV_INIT_CONTEXT  0xA17  
-
+#define DEFAULT_RECV_INIT_CONTEXT  0xA17
 
 static U32 DriverControlWord;
 
-static void rc_timer(unsigned long);
-
-static int RCinit(struct net_device *);
+static void rc_timer (unsigned long);
 
-static int RCopen(struct net_device *);
-static int RC_xmit_packet(struct sk_buff *, struct net_device *);
-static void RCinterrupt(int, void *, struct pt_regs *);
-static int RCclose(struct net_device *dev);
-static struct net_device_stats *RCget_stats(struct net_device *);
-static int RCioctl(struct net_device *, struct ifreq *, int);
-static int RCconfig(struct net_device *, struct ifmap *);
-static void RCxmit_callback(U32, U16, PU32, struct net_device *);
-static void RCrecv_callback(U32, U8, U32, PU32, struct net_device *);
-static void RCreset_callback(U32, U32, U32, struct net_device *);
-static void RCreboot_callback(U32, U32, U32, struct net_device *);
-static int RC_allocate_and_post_buffers(struct net_device *, int);
+static int RCinit (struct net_device *);
 
+static int RCopen (struct net_device *);
+static int RC_xmit_packet (struct sk_buff *, struct net_device *);
+static void RCinterrupt (int, void *, struct pt_regs *);
+static int RCclose (struct net_device *dev);
+static struct net_device_stats *RCget_stats (struct net_device *);
+static int RCioctl (struct net_device *, struct ifreq *, int);
+static int RCconfig (struct net_device *, struct ifmap *);
+static void RCxmit_callback (U32, U16, PU32, struct net_device *);
+static void RCrecv_callback (U32, U8, U32, PU32, struct net_device *);
+static void RCreset_callback (U32, U32, U32, struct net_device *);
+static void RCreboot_callback (U32, U32, U32, struct net_device *);
+static int RC_allocate_and_post_buffers (struct net_device *, int);
 
 static struct pci_device_id rcpci45_pci_table[] __devinitdata = {
-	{ RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
-	{ }
+	{RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{}
 };
-MODULE_DEVICE_TABLE(pci, rcpci45_pci_table);
+MODULE_DEVICE_TABLE (pci, rcpci45_pci_table);
 
-static void __exit rcpci45_remove_one(struct pci_dev *pdev)
+static void __exit
+rcpci45_remove_one (struct pci_dev *pdev)
 {
-	struct net_device *dev = pci_get_drvdata(pdev);
+	struct net_device *dev = pci_get_drvdata (pdev);
 	PDPA pDpa = dev->priv;
 
-        if (!dev) {
-                printk (KERN_ERR "(rcpci45 driver:) remove non-existent device\n");
-                return;
-        }
+	if (!dev) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) remove non-existent device\n");
+		return;
+	}
 
-	dprintk("remove_one: IOP reset: 0x%x\n", RCResetIOP(dev));
+	dprintk ("remove_one: IOP reset: 0x%x\n", RCResetIOP (dev));
 
 	/* RAA Inspired by starfire.c and yellowfin.c we keep these
 	 * here. */
-  	unregister_netdev(dev);
-	free_irq(dev->irq, dev); 
-	iounmap((void *)dev->base_addr);
-	pci_release_regions(pdev);
-	kfree(pDpa->PLanApiPA);
-	kfree(pDpa->pPab);
-	kfree(pDpa);
-	kfree(dev);
-	pci_set_drvdata(pdev, NULL);
+	unregister_netdev (dev);
+	free_irq (dev->irq, dev);
+	iounmap ((void *) dev->base_addr);
+	pci_release_regions (pdev);
+	kfree (pDpa->PLanApiPA);
+	kfree (pDpa->pPab);
+	kfree (pDpa);
+	kfree (dev);
+	pci_set_drvdata (pdev, NULL);
 }
 
-static int RCinit(struct net_device *dev)
+static int
+RCinit (struct net_device *dev)
 {
-    dev->open = &RCopen;
-    dev->hard_start_xmit = &RC_xmit_packet;
-    dev->stop = &RCclose;
-    dev->get_stats = &RCget_stats;
-    dev->do_ioctl = &RCioctl;
-    dev->set_config = &RCconfig;
-    return 0;
+	dev->open = &RCopen;
+	dev->hard_start_xmit = &RC_xmit_packet;
+	dev->stop = &RCclose;
+	dev->get_stats = &RCget_stats;
+	dev->do_ioctl = &RCioctl;
+	dev->set_config = &RCconfig;
+	return 0;
 }
 
-static int rcpci45_init_one(struct pci_dev *pdev, 
-			    const struct pci_device_id *ent)
+static int
+rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-    unsigned long *vaddr;
-    PDPA pDpa;
-    int error;
-    static int card_idx = -1;
-    struct net_device *dev;
-    unsigned long pci_start, pci_len;
-
-    card_idx++;
-
-    /* 
-     * Allocate and fill new device structure. 
-     * We need enough for struct net_device plus DPA plus the LAN API private
-     * area, which requires a minimum of 16KB.  The top of the allocated
-     * area will be assigned to struct net_device; the next chunk will be
-     * assigned to DPA; and finally, the rest will be assigned to the
-     * the LAN API layer.
-     */
-
-    dev = init_etherdev(NULL, sizeof(*pDpa));
-    if (!dev) {
-	printk(KERN_ERR "(rcpci45 driver:) unable to allocate in init_etherdev\n");
-        error = -ENOMEM;
-	goto err_out;
-    }
-
-    error = pci_enable_device(pdev);
-    if (error) {
-        printk(KERN_ERR "(rcpci45 driver:) %d: unable to enable pci device, aborting\n",card_idx);
-	goto err_out;
-    }
-    error = -ENOMEM;
-    pci_start = pci_resource_start(pdev,0);
-    pci_len = pci_resource_len(pdev,0);
-
-    pci_set_drvdata(pdev, dev);
-    
-    pDpa = dev->priv;
-    pDpa->id = card_idx;
-    pDpa->pci_addr = pci_start;
-
-    if (!pci_start || !(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-	printk(KERN_ERR "(rcpci45 driver:) No PCI memory resources! Aborting.\n");
-	error = -EBUSY;
-	goto err_out_free_dev;
-    }    
-
-    /*
-     * Save the starting address of the LAN API private area.  We'll
-     * pass that to RCInitI2OMsgLayer().
-     */
-    /* RAA FIXME: This size should be a #define somewhere after I
-     * clear up some questions: What flags are neeeded in the alloc below
-     * and what needs to be done before the memarea is long word aligned?
-     * (Look in old code for an approach.) (Also note that the 16K below
-     * is substantially less than the 32K allocated before (even though
-     * some of the spacce was used for data structures.) */
-    pDpa->msgbuf = kmalloc(16384, GFP_KERNEL);
-    if (!pDpa->msgbuf) {
-        printk(KERN_ERR "(rcpci45 driver:) Could not allocate %d byte memory for the private msgbuf!\n", 16384); /* RAA FIXME not hardcoded! */
-	goto err_out_free_dev;
-    }
-    pDpa->PLanApiPA = (void *)(((long)pDpa->msgbuf + 0xff) & ~0xff);
-
-    dprintk("pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
-    
-    /* The adapter is accessible through memory-access read/write, not
-     * I/O read/write.  Thus, we need to map it to some virtual address
-     * area in order to access the registers as normal memory.
-     */
-    error = pci_request_regions(pdev, dev->name);
-    if (error)
-    	goto err_out_free_msgbuf;
-
-    vaddr = (ulong *) ioremap (pci_start, pci_len); 
-    if (!vaddr) {
-        printk(KERN_ERR "(rcpci45 driver:) Unable to remap address range from %lu to %lu\n", pci_start, pci_start+pci_len);
-	goto err_out_free_region;
-    }
-
-    dprintk("rcpci45_init_one: 0x%x, priv = 0x%x, vaddr = 0x%x\n", 
-           (uint)dev, (uint)dev->priv, (uint)vaddr);
-    dev->base_addr = (unsigned long)vaddr;
-    dev->irq = pdev->irq;
-
-    dev->init = &RCinit;
-
-    return 0; /* success */
-
- err_out_free_region:
-    pci_release_regions(pdev);
- err_out_free_msgbuf:
-    kfree(pDpa->msgbuf);
- err_out_free_dev:
-    unregister_netdev(dev);
-    kfree(dev);
- err_out:
-    card_idx--;
-    return error;
+	unsigned long *vaddr;
+	PDPA pDpa;
+	int error;
+	static int card_idx = -1;
+	struct net_device *dev;
+	unsigned long pci_start, pci_len;
+
+	card_idx++;
+
+	/* 
+	 * Allocate and fill new device structure. 
+	 * We need enough for struct net_device plus DPA plus the LAN API private
+	 * area, which requires a minimum of 16KB.  The top of the allocated
+	 * area will be assigned to struct net_device; the next chunk will be
+	 * assigned to DPA; and finally, the rest will be assigned to the
+	 * the LAN API layer.
+	 */
+
+	dev = init_etherdev (NULL, sizeof (*pDpa));
+	if (!dev) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) unable to allocate in init_etherdev\n");
+		error = -ENOMEM;
+		goto err_out;
+	}
+
+	error = pci_enable_device (pdev);
+	if (error) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) %d: unable to enable pci device, aborting\n",
+			card_idx);
+		goto err_out;
+	}
+	error = -ENOMEM;
+	pci_start = pci_resource_start (pdev, 0);
+	pci_len = pci_resource_len (pdev, 0);
+
+	pci_set_drvdata (pdev, dev);
+
+	pDpa = dev->priv;
+	pDpa->id = card_idx;
+	pDpa->pci_addr = pci_start;
+
+	if (!pci_start || !(pci_resource_flags (pdev, 0) & IORESOURCE_MEM)) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) No PCI memory resources! Aborting.\n");
+		error = -EBUSY;
+		goto err_out_free_dev;
+	}
+
+	/*
+	 * Save the starting address of the LAN API private area.  We'll
+	 * pass that to RCInitI2OMsgLayer().
+	 */
+	/* RAA FIXME: This size should be a #define somewhere after I
+	 * clear up some questions: What flags are neeeded in the alloc below
+	 * and what needs to be done before the memarea is long word aligned?
+	 * (Look in old code for an approach.) (Also note that the 16K below
+	 * is substantially less than the 32K allocated before (even though
+	 * some of the spacce was used for data structures.) */
+	pDpa->msgbuf = kmalloc (16384, GFP_KERNEL);
+	if (!pDpa->msgbuf) {
+		printk (KERN_ERR "(rcpci45 driver:) Could not allocate %d byte memory for the private msgbuf!\n", 16384);	/* RAA FIXME not hardcoded! */
+		goto err_out_free_dev;
+	}
+	pDpa->PLanApiPA = (void *) (((long) pDpa->msgbuf + 0xff) & ~0xff);
+
+	dprintk ("pDpa->PLanApiPA = 0x%x\n", (uint) pDpa->PLanApiPA);
+
+	/* The adapter is accessible through memory-access read/write, not
+	 * I/O read/write.  Thus, we need to map it to some virtual address
+	 * area in order to access the registers as normal memory.
+	 */
+	error = pci_request_regions (pdev, dev->name);
+	if (error)
+		goto err_out_free_msgbuf;
+
+	vaddr = (ulong *) ioremap (pci_start, pci_len);
+	if (!vaddr) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) Unable to remap address range from %lu to %lu\n",
+			pci_start, pci_start + pci_len);
+		goto err_out_free_region;
+	}
+
+	dprintk ("rcpci45_init_one: 0x%x, priv = 0x%x, vaddr = 0x%x\n",
+		 (uint) dev, (uint) dev->priv, (uint) vaddr);
+	dev->base_addr = (unsigned long) vaddr;
+	dev->irq = pdev->irq;
+
+	dev->init = &RCinit;
+
+	return 0;		/* success */
+
+err_out_free_region:
+	pci_release_regions (pdev);
+err_out_free_msgbuf:
+	kfree (pDpa->msgbuf);
+err_out_free_dev:
+	unregister_netdev (dev);
+	kfree (dev);
+err_out:
+	card_idx--;
+	return error;
 }
 
 static struct pci_driver rcpci45_driver = {
-	name: "rcpci45",
-	id_table: rcpci45_pci_table,
-	probe: rcpci45_init_one,
-	remove: rcpci45_remove_one,
+	name:		"rcpci45",
+	id_table:	rcpci45_pci_table,
+	probe:		rcpci45_init_one,
+	remove:		rcpci45_remove_one,
 };
 
-static int __init rcpci_init_module(void)
+static int __init
+rcpci_init_module (void)
 {
-	int rc = pci_module_init(&rcpci45_driver);
+	int rc = pci_module_init (&rcpci45_driver);
 
 	if (!rc)
-		printk(KERN_INFO "%s",version);
+		printk (KERN_INFO "%s", version);
 	return rc;
 }
 
 static int
-RCopen(struct net_device *dev)
+RCopen (struct net_device *dev)
 {
-    int post_buffers = MAX_NMBR_RCV_BUFFERS;
-    PDPA pDpa = dev->priv;
-    int count = 0;
-    int requested = 0;
-    int error;
-
-    dprintk("(rcpci45 driver:) RCopen\n");
-
-    /* Request a shared interrupt line. */
-    error=request_irq(dev->irq, RCinterrupt, SA_SHIRQ, dev->name, dev);
-    if (error) {
-        printk(KERN_ERR "(rcpci45 driver:) %s: unable to get IRQ %d\n", dev->name, dev->irq );
-	goto err_out;
-    }
-
-    error = RCInitI2OMsgLayer(dev, (PFNTXCALLBACK)RCxmit_callback,
-			      (PFNRXCALLBACK)RCrecv_callback,
-			      (PFNCALLBACK)RCreboot_callback);
-    if (error) {
-        printk(KERN_ERR "(rcpci45 driver:) Unable to initialize msg layer\n");
-	goto err_out_free_irq;
-    }
-    if ( (error=RCGetMAC(dev, NULL)) ) {
-        printk(KERN_ERR "(rcpci45 driver:) Unable to get adapter MAC\n");
-	goto err_out_free_irq;
-    }
-
-    DriverControlWord |= WARM_REBOOT_CAPABLE;
-    RCReportDriverCapability(dev, DriverControlWord);
-
-    printk(KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n",
-        dev->name);
-
-
-    /* RAA: Old RCopen starts here */
-    RCEnableI2OInterrupts(dev);
-
-    /* RAA Hmm, how does the comment below jibe with the newly imported
-     * code above? A FIXME!!*/
-    if (pDpa->nexus) {
-        /* This is not the first time RCopen is called.  Thus,
-         * the interface was previously opened and later closed
-         * by RCclose().  RCclose() does a Shutdown; to wake up
-         * the adapter, a reset is mandatory before we can post
-         * receive buffers.  However, if the adapter initiated 
-         * a reboot while the interface was closed -- and interrupts
-         * were turned off -- we need will need to reinitialize
-         * the adapter, rather than simply waking it up.  
-         */
-	dprintk(KERN_INFO "Waking up adapter...\n");
-        RCResetLANCard(dev,0,0,0);
-    } else
-        pDpa->nexus = 1;
-
-    while(post_buffers) {
-        if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
-            requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
-        else
-            requested = post_buffers;
-        count = RC_allocate_and_post_buffers(dev, requested);
-
-        if ( count < requested )
-        {
-            /*
-             * Check to see if we were able to post any buffers at all.
-             */
-            if (post_buffers == MAX_NMBR_RCV_BUFFERS) {
-                printk(KERN_ERR "(rcpci45 driver:) Error RCopen: not able to allocate any buffers\r\n");
-                return(-ENOMEM);                    
-            }
-            printk(KERN_WARNING "(rcpci45 driver:) Warning RCopen: not able to allocate all requested buffers\r\n");
-            break;            /* we'll try to post more buffers later */
-        } else
-            post_buffers -= count;
-    }
-    pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
-    pDpa->shutdown = 0;        /* just in case */
-    dprintk("RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
-    MOD_INC_USE_COUNT;
-    netif_start_queue(dev);
-    return 0;
-
- err_out_free_irq:
-    free_irq(dev->irq, dev);
- err_out:
-    return error;
+	int post_buffers = MAX_NMBR_RCV_BUFFERS;
+	PDPA pDpa = dev->priv;
+	int count = 0;
+	int requested = 0;
+	int error;
+
+	dprintk ("(rcpci45 driver:) RCopen\n");
+
+	/* Request a shared interrupt line. */
+	error = request_irq (dev->irq, RCinterrupt, SA_SHIRQ, dev->name, dev);
+	if (error) {
+		printk (KERN_ERR "(rcpci45 driver:) %s: unable to get IRQ %d\n",
+			dev->name, dev->irq);
+		goto err_out;
+	}
+
+	error = RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback,
+				   (PFNRXCALLBACK) RCrecv_callback,
+				   (PFNCALLBACK) RCreboot_callback);
+	if (error) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) Unable to initialize msg layer\n");
+		goto err_out_free_irq;
+	}
+	if ((error = RCGetMAC (dev, NULL))) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) Unable to get adapter MAC\n");
+		goto err_out_free_irq;
+	}
+
+	DriverControlWord |= WARM_REBOOT_CAPABLE;
+	RCReportDriverCapability (dev, DriverControlWord);
+
+	printk (KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n",
+		dev->name);
+
+	/* RAA: Old RCopen starts here */
+	RCEnableI2OInterrupts (dev);
+
+	/* RAA Hmm, how does the comment below jibe with the newly imported
+	 * code above? A FIXME!!*/
+	if (pDpa->nexus) {
+		/* This is not the first time RCopen is called.  Thus,
+		 * the interface was previously opened and later closed
+		 * by RCclose().  RCclose() does a Shutdown; to wake up
+		 * the adapter, a reset is mandatory before we can post
+		 * receive buffers.  However, if the adapter initiated 
+		 * a reboot while the interface was closed -- and interrupts
+		 * were turned off -- we need will need to reinitialize
+		 * the adapter, rather than simply waking it up.  
+		 */
+		dprintk (KERN_INFO "Waking up adapter...\n");
+		RCResetLANCard (dev, 0, 0, 0);
+	} else
+		pDpa->nexus = 1;
+
+	while (post_buffers) {
+		if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+			requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
+		else
+			requested = post_buffers;
+		count = RC_allocate_and_post_buffers (dev, requested);
+
+		if (count < requested) {
+			/*
+			 * Check to see if we were able to post any buffers at all.
+			 */
+			if (post_buffers == MAX_NMBR_RCV_BUFFERS) {
+				printk (KERN_ERR
+					"(rcpci45 driver:) Error RCopen: not able to allocate any buffers\r\n");
+				return (-ENOMEM);
+			}
+			printk (KERN_WARNING
+				"(rcpci45 driver:) Warning RCopen: not able to allocate all requested buffers\r\n");
+			break;	/* we'll try to post more buffers later */
+		} else
+			post_buffers -= count;
+	}
+	pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
+	pDpa->shutdown = 0;	/* just in case */
+	dprintk ("RCopen: posted %d buffers\n", (uint) pDpa->numOutRcvBuffers);
+	MOD_INC_USE_COUNT;
+	netif_start_queue (dev);
+	return 0;
+
+err_out_free_irq:
+	free_irq (dev->irq, dev);
+err_out:
+	return error;
 }
 
 static int
-RC_xmit_packet(struct sk_buff *skb, struct net_device *dev)
+RC_xmit_packet (struct sk_buff *skb, struct net_device *dev)
 {
 
-    PDPA pDpa = dev->priv;
-    singleTCB tcb;
-    psingleTCB ptcb = &tcb;
-    RC_RETURN status = 0;
-   
-    netif_stop_queue(dev);
-     
-    if (pDpa->shutdown || pDpa->reboot) {
-            dprintk("RC_xmit_packet: tbusy!\n");
-            return 1;
-    }
-      
-    /*
-     * The user is free to reuse the TCB after RCI2OSendPacket() returns, since
-     * the function copies the necessary info into its own private space.  Thus,
-     * our TCB can be a local structure.  The skb, on the other hand, will be
-     * freed up in our interrupt handler.
-     */
-
-    ptcb->bcount = 1;
-
-    /* 
-     * we'll get the context when the adapter interrupts us to tell us that
-     * the transmission is done. At that time, we can free skb.
-     */
-    ptcb->b.context = (U32)skb;    
-    ptcb->b.scount = 1;
-    ptcb->b.size = skb->len;
-    ptcb->b.addr = virt_to_bus((void *)skb->data);
-
-    dprintk("RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", 
-           (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
-    if ( (status = RCI2OSendPacket(dev, (U32)NULL, (PRCTCB)ptcb))
-         != RC_RTN_NO_ERROR) {
-        dprintk("RC send error 0x%x\n", (uint)status);
-        return 1;
-    } else {
-        dev->trans_start = jiffies;
-        netif_wake_queue(dev);
-    }
-    /*
-     * That's it!
-     */
-    return 0;
+	PDPA pDpa = dev->priv;
+	singleTCB tcb;
+	psingleTCB ptcb = &tcb;
+	RC_RETURN status = 0;
+
+	netif_stop_queue (dev);
+
+	if (pDpa->shutdown || pDpa->reboot) {
+		dprintk ("RC_xmit_packet: tbusy!\n");
+		return 1;
+	}
+
+	/*
+	 * The user is free to reuse the TCB after RCI2OSendPacket() returns, since
+	 * the function copies the necessary info into its own private space.  Thus,
+	 * our TCB can be a local structure.  The skb, on the other hand, will be
+	 * freed up in our interrupt handler.
+	 */
+
+	ptcb->bcount = 1;
+
+	/* 
+	 * we'll get the context when the adapter interrupts us to tell us that
+	 * the transmission is done. At that time, we can free skb.
+	 */
+	ptcb->b.context = (U32) skb;
+	ptcb->b.scount = 1;
+	ptcb->b.size = skb->len;
+	ptcb->b.addr = virt_to_bus ((void *) skb->data);
+
+	dprintk ("RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n",
+		 (uint) skb, (uint) pDpa, (uint) pDpa->id, (uint) ptcb);
+	if ((status = RCI2OSendPacket (dev, (U32) NULL, (PRCTCB) ptcb))
+	    != RC_RTN_NO_ERROR) {
+		dprintk ("RC send error 0x%x\n", (uint) status);
+		return 1;
+	} else {
+		dev->trans_start = jiffies;
+		netif_wake_queue (dev);
+	}
+	/*
+	 * That's it!
+	 */
+	return 0;
 }
 
 /*
@@ -423,107 +431,110 @@
  * RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag. 
  * All we need to do is free the buffers.
  */
-static void 
-RCxmit_callback(U32 Status, 
-                U16 PcktCount, 
-                PU32 BufferContext, 
-                struct net_device *dev)
+static void
+RCxmit_callback (U32 Status,
+		 U16 PcktCount, PU32 BufferContext, struct net_device *dev)
 {
-    struct sk_buff *skb;
-    PDPA pDpa = dev->priv;
+	struct sk_buff *skb;
+	PDPA pDpa = dev->priv;
 
-    if (!pDpa) {
-            printk(KERN_ERR "(rcpci45 driver:) Fatal error: xmit callback, !pDpa\n");
-            return;
-    }
+	if (!pDpa) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) Fatal error: xmit callback, !pDpa\n");
+		return;
+	}
 
 /*      dprintk("xmit_callback: Status = 0x%x\n", (uint)Status); */
-    if (Status != I2O_REPLY_STATUS_SUCCESS)
-            dprintk("xmit_callback: Status = 0x%x\n", (uint)Status);
-    if (pDpa->shutdown || pDpa->reboot)
-            dprintk("xmit callback: shutdown||reboot\n");
-
-    dprintk("xmit_callback: PcktCount = %d, BC = 0x%x\n", 
-	   (uint)PcktCount, (uint)BufferContext);
-
-    while (PcktCount--) {
-            skb = (struct sk_buff *)(BufferContext[0]);
-            dprintk("skb = 0x%x\n", (uint)skb);
-            BufferContext++;
-            dev_kfree_skb_irq(skb);
-    }
-    netif_wake_queue(dev);
+	if (Status != I2O_REPLY_STATUS_SUCCESS)
+		dprintk ("xmit_callback: Status = 0x%x\n", (uint) Status);
+	if (pDpa->shutdown || pDpa->reboot)
+		dprintk ("xmit callback: shutdown||reboot\n");
+
+	dprintk ("xmit_callback: PcktCount = %d, BC = 0x%x\n",
+		 (uint) PcktCount, (uint) BufferContext);
+
+	while (PcktCount--) {
+		skb = (struct sk_buff *) (BufferContext[0]);
+		dprintk ("skb = 0x%x\n", (uint) skb);
+		BufferContext++;
+		dev_kfree_skb_irq (skb);
+	}
+	netif_wake_queue (dev);
 }
 
 static void
-RCreset_callback(U32 Status, U32 p1, U32 p2, struct net_device *dev)
+RCreset_callback (U32 Status, U32 p1, U32 p2, struct net_device *dev)
 {
-    PDPA pDpa = dev->priv;
-     
-    dprintk("RCreset_callback Status 0x%x\n", (uint)Status);
-    /*
-     * Check to see why we were called.
-     */
-    if (pDpa->shutdown) {
-        printk(KERN_INFO "(rcpci45 driver:) Shutting down interface\n");
-        pDpa->shutdown = 0;
-        pDpa->reboot = 0;
-        MOD_DEC_USE_COUNT; 
-    } else if (pDpa->reboot) {
-        printk(KERN_INFO "(rcpci45 driver:) reboot, shutdown adapter\n");
-        /*
-         * We don't set any of the flags in RCShutdownLANCard()
-         * and we don't pass a callback routine to it.
-         * The adapter will have already initiated the reboot by
-         * the time the function returns.
-         */
-        RCDisableI2OInterrupts(dev);
-        RCShutdownLANCard(dev,0,0,0);
-        printk(KERN_INFO "(rcpci45 driver:) scheduling timer...\n");
-        init_timer(&pDpa->timer);
-        pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 4 sec. */
-        pDpa->timer.data = (unsigned long)dev;
-        pDpa->timer.function = &rc_timer;    /* timer handler */
-        add_timer(&pDpa->timer);
-    }
+	PDPA pDpa = dev->priv;
+
+	dprintk ("RCreset_callback Status 0x%x\n", (uint) Status);
+	/*
+	 * Check to see why we were called.
+	 */
+	if (pDpa->shutdown) {
+		printk (KERN_INFO
+			"(rcpci45 driver:) Shutting down interface\n");
+		pDpa->shutdown = 0;
+		pDpa->reboot = 0;
+		MOD_DEC_USE_COUNT;
+	} else if (pDpa->reboot) {
+		printk (KERN_INFO
+			"(rcpci45 driver:) reboot, shutdown adapter\n");
+		/*
+		 * We don't set any of the flags in RCShutdownLANCard()
+		 * and we don't pass a callback routine to it.
+		 * The adapter will have already initiated the reboot by
+		 * the time the function returns.
+		 */
+		RCDisableI2OInterrupts (dev);
+		RCShutdownLANCard (dev, 0, 0, 0);
+		printk (KERN_INFO "(rcpci45 driver:) scheduling timer...\n");
+		init_timer (&pDpa->timer);
+		pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);	/* 4 sec. */
+		pDpa->timer.data = (unsigned long) dev;
+		pDpa->timer.function = &rc_timer;	/* timer handler */
+		add_timer (&pDpa->timer);
+	}
 }
 
 static void
-RCreboot_callback(U32 Status, U32 p1, U32 p2, struct net_device *dev)
+RCreboot_callback (U32 Status, U32 p1, U32 p2, struct net_device *dev)
 {
-    PDPA pDpa = dev->priv;
-    
-    dprintk("RCreboot: rcv buffers outstanding = %d\n", 
-           (uint)pDpa->numOutRcvBuffers);
-
-    if (pDpa->shutdown) {
-        printk(KERN_INFO "(rcpci45 driver:) skipping reboot sequence -- shutdown already initiated\n");
-        return;
-    }
-    pDpa->reboot = 1;
-    /*
-     * OK, we reset the adapter and ask it to return all
-     * outstanding transmit buffers as well as the posted
-     * receive buffers.  When the adapter is done returning
-     * those buffers, it will call our RCreset_callback() 
-     * routine.  In that routine, we'll call RCShutdownLANCard()
-     * to tell the adapter that it's OK to start the reboot and
-     * schedule a timer callback routine to execute 3 seconds 
-     * later; this routine will reinitialize the adapter at that time.
-     */
-    RCResetLANCard(dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
-                   RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
-                   (PFNCALLBACK)RCreset_callback);
-}
+	PDPA pDpa = dev->priv;
 
+	dprintk ("RCreboot: rcv buffers outstanding = %d\n",
+		 (uint) pDpa->numOutRcvBuffers);
 
-int broadcast_packet(unsigned char * address)
+	if (pDpa->shutdown) {
+		printk (KERN_INFO
+			"(rcpci45 driver:) skipping reboot sequence -- shutdown already initiated\n");
+		return;
+	}
+	pDpa->reboot = 1;
+	/*
+	 * OK, we reset the adapter and ask it to return all
+	 * outstanding transmit buffers as well as the posted
+	 * receive buffers.  When the adapter is done returning
+	 * those buffers, it will call our RCreset_callback() 
+	 * routine.  In that routine, we'll call RCShutdownLANCard()
+	 * to tell the adapter that it's OK to start the reboot and
+	 * schedule a timer callback routine to execute 3 seconds 
+	 * later; this routine will reinitialize the adapter at that time.
+	 */
+	RCResetLANCard (dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
+			RC_RESOURCE_RETURN_PEND_TX_BUFFERS, 0,
+			(PFNCALLBACK) RCreset_callback);
+}
+
+int
+broadcast_packet (unsigned char *address)
 {
-    int i;
-    for (i=0; i<6; i++)
-        if (address[i] != 0xff) return 0;
+	int i;
+	for (i = 0; i < 6; i++)
+		if (address[i] != 0xff)
+			return 0;
 
-    return 1;
+	return 1;
 }
 
 /*
@@ -534,124 +545,119 @@
  * filled (one ethernet packet per buffer).
  */
 static void
-RCrecv_callback(U32  Status, 
-                U8   PktCount, 
-                U32  BucketsRemain, 
-                PU32 PacketDescBlock, 
-                struct net_device *dev)
+RCrecv_callback (U32 Status,
+		 U8 PktCount,
+		 U32 BucketsRemain,
+		 PU32 PacketDescBlock, struct net_device *dev)
 {
 
-    U32 len, count;
-    PDPA pDpa = dev->priv;
-    struct sk_buff *skb;
-    singleTCB tcb;
-    psingleTCB ptcb = &tcb;
-
-
-    ptcb->bcount = 1;
-    
-    dprintk("RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
-	   (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);
-
-    if ((pDpa->shutdown || pDpa->reboot) && !Status)
-            dprintk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
-    
-    if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
-    {
-            /*
-             * Free whatever buffers the adapter returned, but don't
-             * pass them to the kernel.
-             */
-	    
-	    if (!pDpa->shutdown && !pDpa->reboot)
-                    printk(KERN_INFO "(rcpci45 driver:) RCrecv error: status = 0x%x\n", (uint)Status);
-                else
-			dprintk("Returning %d buffers, status = 0x%x\n", 
-                           PktCount, (uint)Status);
-            /*
-             * TO DO: check the nature of the failure and put the adapter in
-             * failed mode if it's a hard failure.  Send a reset to the adapter
-             * and free all outstanding memory.
-             */
-            if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
-                dprintk("RCrecv status ABORT NO DATA TRANSFER\n");
-
-            /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */ 
-            if (PacketDescBlock)
-            {
-                while(PktCount--)
-                {
-                    skb = (struct sk_buff *)PacketDescBlock[0];
-                    dprintk("free skb 0x%p\n", skb);
-                    dev_kfree_skb (skb);
-                    pDpa->numOutRcvBuffers--;
-                    PacketDescBlock += BD_SIZE; /* point to next context field */
-                }
-            }
-            return;
-        }
-        else
-        {
-            while(PktCount--)
-            {
-                skb = (struct sk_buff *)PacketDescBlock[0];
-                if (pDpa->shutdown)
-			dprintk("shutdown: skb=0x%x\n", (uint)skb);
-
-                dprintk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
-                       (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2],
-                       (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);
-
-#ifdef PROMISCUOUS_BY_DEFAULT   /* early 2.x firmware */
-                if ( (memcmp(dev->dev_addr, skb->data, 6)) &&
-                     (!broadcast_packet(skb->data)))
-                {
-                    /*
-                     * Re-post the buffer to the adapter.  Since the adapter usually
-                     * return 1 to 2 receive buffers at a time, it's not too inefficient
-                     * post one buffer at a time but ... may be that should be 
-                     * optimized at some point.
-                     */
-                    ptcb->b.context = (U32)skb;    
-                    ptcb->b.scount = 1;
-                    ptcb->b.size = MAX_ETHER_SIZE;
-                    ptcb->b.addr = virt_to_bus((void *)skb->data);
-
-                    if ( RCPostRecvBuffers(dev, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
-                    {
-                        printk(KERN_WARNING "(rcpci45 driver:) RCrecv_callback: post buffer failed!\n");
-                        dev_kfree_skb (skb);
-                    }
-                    else
-                        pDpa->numOutRcvBuffers++;
-                }
-                else
-#endif /* PROMISCUOUS_BY_DEFAULT */
-                {
-                    len = PacketDescBlock[2];
-                    skb->dev = dev;
-                    skb_put( skb, len ); /* adjust length and tail */
-                    skb->protocol = eth_type_trans(skb, dev);
-                    netif_rx(skb);    /* send the packet to the kernel */
-                    dev->last_rx = jiffies;
-                }
-                pDpa->numOutRcvBuffers--;
-                PacketDescBlock += BD_SIZE; /* point to next context field */
-            }
-        } 
-    
-        /*
-         * Replenish the posted receive buffers. 
-         * DO NOT replenish buffers if the driver has already
-         * initiated a reboot or shutdown!
-         */
-
-        if (!pDpa->shutdown && !pDpa->reboot)
-        {
-            count = RC_allocate_and_post_buffers(dev, 
-                                                 MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers);
-            pDpa->numOutRcvBuffers += count;
-        }
+	U32 len, count;
+	PDPA pDpa = dev->priv;
+	struct sk_buff *skb;
+	singleTCB tcb;
+	psingleTCB ptcb = &tcb;
+
+	ptcb->bcount = 1;
+
+	dprintk ("RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
+		 (uint) PktCount, (uint) BucketsRemain, (uint) PacketDescBlock);
+
+	if ((pDpa->shutdown || pDpa->reboot) && !Status)
+		dprintk ("shutdown||reboot && !Status: PktCount = %d\n",
+			 PktCount);
+
+	if ((Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown) {
+		/*
+		 * Free whatever buffers the adapter returned, but don't
+		 * pass them to the kernel.
+		 */
+
+		if (!pDpa->shutdown && !pDpa->reboot)
+			printk (KERN_INFO
+				"(rcpci45 driver:) RCrecv error: status = 0x%x\n",
+				(uint) Status);
+		else
+			dprintk ("Returning %d buffers, status = 0x%x\n",
+				 PktCount, (uint) Status);
+		/*
+		 * TO DO: check the nature of the failure and put the adapter in
+		 * failed mode if it's a hard failure.  Send a reset to the adapter
+		 * and free all outstanding memory.
+		 */
+		if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
+			dprintk ("RCrecv status ABORT NO DATA TRANSFER\n");
+
+		/* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */
+		if (PacketDescBlock) {
+			while (PktCount--) {
+				skb = (struct sk_buff *) PacketDescBlock[0];
+				dprintk ("free skb 0x%p\n", skb);
+				dev_kfree_skb (skb);
+				pDpa->numOutRcvBuffers--;
+				PacketDescBlock += BD_SIZE;	/* point to next context field */
+			}
+		}
+		return;
+	} else {
+		while (PktCount--) {
+			skb = (struct sk_buff *) PacketDescBlock[0];
+			if (pDpa->shutdown)
+				dprintk ("shutdown: skb=0x%x\n", (uint) skb);
+
+			dprintk ("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+				 (uint) skb, (uint) skb->data[0],
+				 (uint) skb->data[1], (uint) skb->data[2],
+				 (uint) skb->data[3], (uint) skb->data[4],
+				 (uint) skb->data[5]);
+
+#ifdef PROMISCUOUS_BY_DEFAULT	/* early 2.x firmware */
+			if ((memcmp (dev->dev_addr, skb->data, 6)) &&
+			    (!broadcast_packet (skb->data))) {
+				/*
+				 * Re-post the buffer to the adapter.  Since the adapter usually
+				 * return 1 to 2 receive buffers at a time, it's not too inefficient
+				 * post one buffer at a time but ... may be that should be 
+				 * optimized at some point.
+				 */
+				ptcb->b.context = (U32) skb;
+				ptcb->b.scount = 1;
+				ptcb->b.size = MAX_ETHER_SIZE;
+				ptcb->b.addr = virt_to_bus ((void *) skb->data);
+
+				if (RCPostRecvBuffers (dev, (PRCTCB) ptcb) !=
+				    RC_RTN_NO_ERROR) {
+					printk (KERN_WARNING
+						"(rcpci45 driver:) RCrecv_callback: post buffer failed!\n");
+					dev_kfree_skb (skb);
+				} else
+					pDpa->numOutRcvBuffers++;
+			} else
+#endif				/* PROMISCUOUS_BY_DEFAULT */
+			{
+				len = PacketDescBlock[2];
+				skb->dev = dev;
+				skb_put (skb, len);	/* adjust length and tail */
+				skb->protocol = eth_type_trans (skb, dev);
+				netif_rx (skb);	/* send the packet to the kernel */
+				dev->last_rx = jiffies;
+			}
+			pDpa->numOutRcvBuffers--;
+			PacketDescBlock += BD_SIZE;	/* point to next context field */
+		}
+	}
+
+	/*
+	 * Replenish the posted receive buffers. 
+	 * DO NOT replenish buffers if the driver has already
+	 * initiated a reboot or shutdown!
+	 */
+
+	if (!pDpa->shutdown && !pDpa->reboot) {
+		count = RC_allocate_and_post_buffers (dev,
+						      MAX_NMBR_RCV_BUFFERS -
+						      pDpa->numOutRcvBuffers);
+		pDpa->numOutRcvBuffers += count;
+	}
 
 }
 
@@ -663,474 +669,533 @@
  * RCProcI2OMsgQ(), which in turn process the message and
  * calls one of our callback functions.
  */
-static void 
-RCinterrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void
+RCinterrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
 
-    PDPA pDpa;
-    struct net_device *dev = dev_id;
+	PDPA pDpa;
+	struct net_device *dev = dev_id;
 
-    pDpa = dev->priv;
-     
-    if (pDpa->shutdown)
-        dprintk("shutdown: service irq\n");
-
-    dprintk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", 
-           (uint)pDpa, (uint)dev, (uint)pDpa->id);
-    dprintk("dev = 0x%x\n", (uint)dev);
+	pDpa = dev->priv;
 
-    RCProcI2OMsgQ(dev);
-}
+	if (pDpa->shutdown)
+		dprintk ("shutdown: service irq\n");
+
+	dprintk ("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n",
+		 (uint) pDpa, (uint) dev, (uint) pDpa->id);
+	dprintk ("dev = 0x%x\n", (uint) dev);
 
+	RCProcI2OMsgQ (dev);
+}
 
 #define REBOOT_REINIT_RETRY_LIMIT 4
-static void rc_timer(unsigned long data)
+static void
+rc_timer (unsigned long data)
 {
-    struct net_device *dev = (struct net_device *)data;
-    PDPA pDpa = dev->priv;
-    int init_status;
-    static int retry;
-    int post_buffers = MAX_NMBR_RCV_BUFFERS;
-    int count = 0;
-    int requested = 0;
-
-    if (pDpa->reboot)
-    {
-        init_status = RCInitI2OMsgLayer(dev, (PFNTXCALLBACK)RCxmit_callback,
-					(PFNRXCALLBACK)RCrecv_callback,
-					(PFNCALLBACK)RCreboot_callback);
-
-        switch(init_status)
-        {
-        case RC_RTN_NO_ERROR:
- 
-            pDpa->reboot = 0;
-            pDpa->shutdown = 0;        /* just in case */
-            RCReportDriverCapability(dev, DriverControlWord);
-            RCEnableI2OInterrupts(dev);
-
-            if (dev->flags & IFF_UP)
-            {
-                while(post_buffers)
-                {
-                    if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
-                        requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
-                    else
-                        requested = post_buffers;
-                    count = RC_allocate_and_post_buffers(dev, requested);
-                    post_buffers -= count;
-                    if ( count < requested )
-                        break;
-                }
-                pDpa->numOutRcvBuffers = 
-                    MAX_NMBR_RCV_BUFFERS - post_buffers;
-                dprintk("rc: posted %d buffers \r\n", 
-                       (uint)pDpa->numOutRcvBuffers);
-            }
-            dprintk("Initialization done.\n");
-            netif_wake_queue(dev);
-            retry=0;
-            return;
-        case RC_RTN_FREE_Q_EMPTY:
-            retry++;
-            printk(KERN_WARNING "(rcpci45 driver:) inbound free q empty\n");
-            break;
-        default:
-            retry++;
-            printk(KERN_WARNING "(rcpci45 driver:) bad status after reboot: %d\n", init_status);    
-            break;
-        }
-
-        if (retry > REBOOT_REINIT_RETRY_LIMIT)
-        {
-            printk(KERN_WARNING "(rcpci45 driver:) unable to reinitialize adapter after reboot\n");
-            printk(KERN_WARNING "(rcpci45 driver:) decrementing driver and closing interface\n");
-            RCDisableI2OInterrupts(dev);
-            dev->flags &= ~IFF_UP;
-            MOD_DEC_USE_COUNT; 
-        }
-        else
-        {
-            printk(KERN_INFO "(rcpci45 driver:) rescheduling timer...\n");
-            init_timer(&pDpa->timer);
-            pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 3 sec. */
-            pDpa->timer.data = (unsigned long)dev;
-            pDpa->timer.function = &rc_timer;    /* timer handler */
-            add_timer(&pDpa->timer);
-        }
-    }
-    else
-        printk(KERN_WARNING "(rcpci45 driver:) timer??\n");
+	struct net_device *dev = (struct net_device *) data;
+	PDPA pDpa = dev->priv;
+	int init_status;
+	static int retry;
+	int post_buffers = MAX_NMBR_RCV_BUFFERS;
+	int count = 0;
+	int requested = 0;
+
+	if (pDpa->reboot) {
+		init_status =
+		    RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback,
+				       (PFNRXCALLBACK) RCrecv_callback,
+				       (PFNCALLBACK) RCreboot_callback);
+
+		switch (init_status) {
+		case RC_RTN_NO_ERROR:
+
+			pDpa->reboot = 0;
+			pDpa->shutdown = 0;	/* just in case */
+			RCReportDriverCapability (dev, DriverControlWord);
+			RCEnableI2OInterrupts (dev);
+
+			if (dev->flags & IFF_UP) {
+				while (post_buffers) {
+					if (post_buffers >
+					    MAX_NMBR_POST_BUFFERS_PER_MSG)
+						requested =
+						    MAX_NMBR_POST_BUFFERS_PER_MSG;
+					else
+						requested = post_buffers;
+					count =
+					    RC_allocate_and_post_buffers (dev,
+									  requested);
+					post_buffers -= count;
+					if (count < requested)
+						break;
+				}
+				pDpa->numOutRcvBuffers =
+				    MAX_NMBR_RCV_BUFFERS - post_buffers;
+				dprintk ("rc: posted %d buffers \r\n",
+					 (uint) pDpa->numOutRcvBuffers);
+			}
+			dprintk ("Initialization done.\n");
+			netif_wake_queue (dev);
+			retry = 0;
+			return;
+		case RC_RTN_FREE_Q_EMPTY:
+			retry++;
+			printk (KERN_WARNING
+				"(rcpci45 driver:) inbound free q empty\n");
+			break;
+		default:
+			retry++;
+			printk (KERN_WARNING
+				"(rcpci45 driver:) bad status after reboot: %d\n",
+				init_status);
+			break;
+		}
+
+		if (retry > REBOOT_REINIT_RETRY_LIMIT) {
+			printk (KERN_WARNING
+				"(rcpci45 driver:) unable to reinitialize adapter after reboot\n");
+			printk (KERN_WARNING
+				"(rcpci45 driver:) decrementing driver and closing interface\n");
+			RCDisableI2OInterrupts (dev);
+			dev->flags &= ~IFF_UP;
+			MOD_DEC_USE_COUNT;
+		} else {
+			printk (KERN_INFO
+				"(rcpci45 driver:) rescheduling timer...\n");
+			init_timer (&pDpa->timer);
+			pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);	/* 3 sec. */
+			pDpa->timer.data = (unsigned long) dev;
+			pDpa->timer.function = &rc_timer;	/* timer handler */
+			add_timer (&pDpa->timer);
+		}
+	} else
+		printk (KERN_WARNING "(rcpci45 driver:) timer??\n");
 }
 
 static int
-RCclose(struct net_device *dev)
+RCclose (struct net_device *dev)
 {
-    PDPA pDpa = dev->priv;
+	PDPA pDpa = dev->priv;
+
+	netif_stop_queue (dev);
+
+	dprintk ("RCclose\r\n");
 
-    netif_stop_queue(dev);
-    
-    dprintk("RCclose\r\n");
-
-    if (pDpa->reboot)
-    {
-        printk(KERN_INFO "(rcpci45 driver:) skipping reset -- adapter already in reboot mode\n");
-        dev->flags &= ~IFF_UP;
-        pDpa->shutdown = 1;
-        return 0;
-    }
-    dprintk("receive buffers outstanding: %d\n", (uint)pDpa->numOutRcvBuffers);
-
-    pDpa->shutdown = 1;
-
-    /*
-     * We can't allow the driver to be unloaded until the adapter returns
-     * all posted receive buffers.  It doesn't hurt to tell the adapter
-     * to return all posted receive buffers and outstanding xmit buffers,
-     * even if there are none.
-     */
-
-    RCShutdownLANCard(dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
-                      RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
-                      (PFNCALLBACK)RCreset_callback);
+	if (pDpa->reboot) {
+		printk (KERN_INFO
+			"(rcpci45 driver:) skipping reset -- adapter already in reboot mode\n");
+		dev->flags &= ~IFF_UP;
+		pDpa->shutdown = 1;
+		return 0;
+	}
+	dprintk ("receive buffers outstanding: %d\n",
+		 (uint) pDpa->numOutRcvBuffers);
+
+	pDpa->shutdown = 1;
+
+	/*
+	 * We can't allow the driver to be unloaded until the adapter returns
+	 * all posted receive buffers.  It doesn't hurt to tell the adapter
+	 * to return all posted receive buffers and outstanding xmit buffers,
+	 * even if there are none.
+	 */
+
+	RCShutdownLANCard (dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
+			   RC_RESOURCE_RETURN_PEND_TX_BUFFERS, 0,
+			   (PFNCALLBACK) RCreset_callback);
 
-    dev->flags &= ~IFF_UP;
-    return 0;
+	dev->flags &= ~IFF_UP;
+	return 0;
 }
 
 static struct net_device_stats *
-RCget_stats(struct net_device *dev)
+RCget_stats (struct net_device *dev)
 {
-    RCLINKSTATS    RCstats;
-   
-    PDPA pDpa = dev->priv;
-
-    if (!pDpa)
-    {
-	dprintk("RCget_stats: !pDpa\n");
-        return 0;
-    }
-    else if (!(dev->flags & IFF_UP))    
-    {
-	dprintk("RCget_stats: device down\n");
-        return 0;
-    }
-
-    memset(&RCstats, 0, sizeof(RCLINKSTATS));
-    if ( (RCGetLinkStatistics(dev, &RCstats, (void *)0)) == RC_RTN_NO_ERROR )
-    {
-	dprintk("TX_good 0x%x\n", (uint)RCstats.TX_good);
-        dprintk("TX_maxcol 0x%x\n", (uint)RCstats.TX_maxcol);
-        dprintk("TX_latecol 0x%x\n", (uint)RCstats.TX_latecol);
-        dprintk("TX_urun 0x%x\n", (uint)RCstats.TX_urun);
-        dprintk("TX_crs 0x%x\n", (uint)RCstats.TX_crs);
-        dprintk("TX_def 0x%x\n", (uint)RCstats.TX_def);
-        dprintk("TX_singlecol 0x%x\n", (uint)RCstats.TX_singlecol);
-        dprintk("TX_multcol 0x%x\n", (uint)RCstats.TX_multcol);
-        dprintk("TX_totcol 0x%x\n", (uint)RCstats.TX_totcol);
-		 
-        dprintk("Rcv_good 0x%x\n", (uint)RCstats.Rcv_good);
-        dprintk("Rcv_CRCerr 0x%x\n", (uint)RCstats.Rcv_CRCerr);
-        dprintk("Rcv_alignerr 0x%x\n", (uint)RCstats.Rcv_alignerr);
-        dprintk("Rcv_reserr 0x%x\n", (uint)RCstats.Rcv_reserr);
-        dprintk("Rcv_orun 0x%x\n", (uint)RCstats.Rcv_orun);
-        dprintk("Rcv_cdt 0x%x\n", (uint)RCstats.Rcv_cdt);
-        dprintk("Rcv_runt 0x%x\n", (uint)RCstats.Rcv_runt);
-
-        pDpa->stats.rx_packets = RCstats.Rcv_good; /* total packets received    */
-        pDpa->stats.tx_packets = RCstats.TX_good; /* total packets transmitted    */
-
-        pDpa->stats.rx_errors = 
-            RCstats.Rcv_CRCerr +
-            RCstats.Rcv_alignerr + 
-            RCstats.Rcv_reserr + 
-            RCstats.Rcv_orun + 
-            RCstats.Rcv_cdt + 
-            RCstats.Rcv_runt; /* bad packets received        */
-
-        pDpa->stats.tx_errors = 
-            RCstats.TX_urun + 
-            RCstats.TX_crs + 
-            RCstats.TX_def + 
-            RCstats.TX_totcol; /* packet transmit problems    */
-
-        /*
-         * This needs improvement.
-         */
-        pDpa->stats.rx_dropped = 0;        /* no space in linux buffers    */
-        pDpa->stats.tx_dropped = 0;        /* no space available in linux    */
-        pDpa->stats.multicast = 0;        /* multicast packets received    */
-        pDpa->stats.collisions = RCstats.TX_totcol;
-
-        /* detailed rx_errors: */
-        pDpa->stats.rx_length_errors = 0;
-        pDpa->stats.rx_over_errors = RCstats.Rcv_orun; /* receiver ring buff overflow    */
-        pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr;    /* recved pkt with crc error    */
-        pDpa->stats.rx_frame_errors = 0; /* recv'd frame alignment error */
-        pDpa->stats.rx_fifo_errors = 0; /* recv'r fifo overrun        */
-        pDpa->stats.rx_missed_errors = 0; /* receiver missed packet    */
-
-        /* detailed tx_errors */
-        pDpa->stats.tx_aborted_errors = 0;
-        pDpa->stats.tx_carrier_errors = 0;
-        pDpa->stats.tx_fifo_errors = 0;
-        pDpa->stats.tx_heartbeat_errors = 0;
-        pDpa->stats.tx_window_errors = 0;
-
-        return ((struct net_device_stats *)&(pDpa->stats));
-    }
-    return 0;
+	RCLINKSTATS RCstats;
+
+	PDPA pDpa = dev->priv;
+
+	if (!pDpa) {
+		dprintk ("RCget_stats: !pDpa\n");
+		return 0;
+	} else if (!(dev->flags & IFF_UP)) {
+		dprintk ("RCget_stats: device down\n");
+		return 0;
+	}
+
+	memset (&RCstats, 0, sizeof (RCLINKSTATS));
+	if ((RCGetLinkStatistics (dev, &RCstats, (void *) 0)) ==
+	    RC_RTN_NO_ERROR) {
+		dprintk ("TX_good 0x%x\n", (uint) RCstats.TX_good);
+		dprintk ("TX_maxcol 0x%x\n", (uint) RCstats.TX_maxcol);
+		dprintk ("TX_latecol 0x%x\n", (uint) RCstats.TX_latecol);
+		dprintk ("TX_urun 0x%x\n", (uint) RCstats.TX_urun);
+		dprintk ("TX_crs 0x%x\n", (uint) RCstats.TX_crs);
+		dprintk ("TX_def 0x%x\n", (uint) RCstats.TX_def);
+		dprintk ("TX_singlecol 0x%x\n", (uint) RCstats.TX_singlecol);
+		dprintk ("TX_multcol 0x%x\n", (uint) RCstats.TX_multcol);
+		dprintk ("TX_totcol 0x%x\n", (uint) RCstats.TX_totcol);
+
+		dprintk ("Rcv_good 0x%x\n", (uint) RCstats.Rcv_good);
+		dprintk ("Rcv_CRCerr 0x%x\n", (uint) RCstats.Rcv_CRCerr);
+		dprintk ("Rcv_alignerr 0x%x\n", (uint) RCstats.Rcv_alignerr);
+		dprintk ("Rcv_reserr 0x%x\n", (uint) RCstats.Rcv_reserr);
+		dprintk ("Rcv_orun 0x%x\n", (uint) RCstats.Rcv_orun);
+		dprintk ("Rcv_cdt 0x%x\n", (uint) RCstats.Rcv_cdt);
+		dprintk ("Rcv_runt 0x%x\n", (uint) RCstats.Rcv_runt);
+
+		pDpa->stats.rx_packets = RCstats.Rcv_good;	/* total packets received    */
+		pDpa->stats.tx_packets = RCstats.TX_good;	/* total packets transmitted    */
+
+		pDpa->stats.rx_errors = RCstats.Rcv_CRCerr + RCstats.Rcv_alignerr + RCstats.Rcv_reserr + RCstats.Rcv_orun + RCstats.Rcv_cdt + RCstats.Rcv_runt;	/* bad packets received        */
+
+		pDpa->stats.tx_errors = RCstats.TX_urun + RCstats.TX_crs + RCstats.TX_def + RCstats.TX_totcol;	/* packet transmit problems    */
+
+		/*
+		 * This needs improvement.
+		 */
+		pDpa->stats.rx_dropped = 0;	/* no space in linux buffers    */
+		pDpa->stats.tx_dropped = 0;	/* no space available in linux    */
+		pDpa->stats.multicast = 0;	/* multicast packets received    */
+		pDpa->stats.collisions = RCstats.TX_totcol;
+
+		/* detailed rx_errors: */
+		pDpa->stats.rx_length_errors = 0;
+		pDpa->stats.rx_over_errors = RCstats.Rcv_orun;	/* receiver ring buff overflow    */
+		pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr;	/* recved pkt with crc error    */
+		pDpa->stats.rx_frame_errors = 0;	/* recv'd frame alignment error */
+		pDpa->stats.rx_fifo_errors = 0;	/* recv'r fifo overrun        */
+		pDpa->stats.rx_missed_errors = 0;	/* receiver missed packet    */
+
+		/* detailed tx_errors */
+		pDpa->stats.tx_aborted_errors = 0;
+		pDpa->stats.tx_carrier_errors = 0;
+		pDpa->stats.tx_fifo_errors = 0;
+		pDpa->stats.tx_heartbeat_errors = 0;
+		pDpa->stats.tx_window_errors = 0;
+
+		return ((struct net_device_stats *) &(pDpa->stats));
+	}
+	return 0;
 }
 
-static int RCioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int
+RCioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    RCuser_struct RCuser;
-    PDPA pDpa = dev->priv;
+	RCuser_struct RCuser;
+	PDPA pDpa = dev->priv;
+
+	dprintk ("RCioctl: cmd = 0x%x\n", cmd);
+
+	if (!capable (CAP_NET_ADMIN))
+		return -EPERM;
 
-    dprintk("RCioctl: cmd = 0x%x\n", cmd);
- 
-    if(!capable(CAP_NET_ADMIN))
-    	return -EPERM;
-    	
-    switch (cmd)  {
- 
-    case RCU_PROTOCOL_REV:
-        /*
-         * Assign user protocol revision, to tell user-level
-         * controller program whether or not it's in sync.
-         */
-        rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;
-        break;
-  
-
-    case RCU_COMMAND:
-    {
-        if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
-             return -EFAULT;
-        
-        dprintk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
-  
-        switch(RCuser.cmd)
-        {
-        case RCUC_GETFWVER:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETFWVER\n");
-            RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
-            RCGetFirmwareVer(dev, (PU8) &RCUD_GETFWVER->FirmString, NULL);
-            break;
-        case RCUC_GETINFO:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETINFO\n");
-            RCUD_GETINFO = &RCuser.RCUS_GETINFO;
-            RCUD_GETINFO -> mem_start = dev->base_addr;
-	    RCUD_GETINFO -> mem_end = dev->base_addr + pDpa->pci_addr_len;
-	    RCUD_GETINFO -> base_addr = pDpa->pci_addr;  
-            RCUD_GETINFO -> irq = dev->irq;
-            break;
-        case RCUC_GETIPANDMASK:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETIPANDMASK\n");
-            RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
-            RCGetRavlinIPandMask(dev, (PU32) &RCUD_GETIPANDMASK->IpAddr,
-                                 (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
-            break;
-        case RCUC_GETLINKSTATISTICS:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETLINKSTATISTICS\n");
-            RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS;
-            RCGetLinkStatistics(dev, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
-            break;
-        case RCUC_GETLINKSTATUS:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETLINKSTATUS\n");
-            RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
-            RCGetLinkStatus(dev, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
-            break;
-        case RCUC_GETMAC:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETMAC\n");
-            RCUD_GETMAC = &RCuser.RCUS_GETMAC;
-            RCGetMAC(dev, NULL);
-            break;
-        case RCUC_GETPROM:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETPROM\n");
-            RCUD_GETPROM = &RCuser.RCUS_GETPROM;
-            RCGetPromiscuousMode(dev, (PU32) &RCUD_GETPROM->PromMode, NULL);
-            break;
-        case RCUC_GETBROADCAST:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETBROADCAST\n");
-            RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
-            RCGetBroadcastMode(dev, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL);
-            break;
-        case RCUC_GETSPEED:
-            printk(KERN_INFO "(rcpci45 driver:) RC GETSPEED\n");
-            if (!(dev->flags & IFF_UP))    
-            {
-                printk(KERN_ERR "(rcpci45 driver:) RCioctl, GETSPEED error: interface down\n");
-                return -ENODATA;
-            }
-            RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
-            RCGetLinkSpeed(dev, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
-            printk(KERN_INFO "(rcpci45 driver:) RC speed = 0x%u\n", RCUD_GETSPEED->LinkSpeedCode);
-            break;
-        case RCUC_SETIPANDMASK:
-            printk(KERN_INFO "(rcpci45 driver:) RC SETIPANDMASK\n");
-            RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
-            printk (KERN_INFO "(rcpci45 driver:) RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->IpAddr >>  8) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff));
-            printk (KERN_INFO "(rcpci45 driver:) RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->NetMask >>  8) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff));
-            RCSetRavlinIPandMask(dev, (U32) RCUD_SETIPANDMASK->IpAddr,
-                                 (U32) RCUD_SETIPANDMASK->NetMask);
-            break;
-        case RCUC_SETMAC:
-            printk(KERN_INFO "(rcpci45 driver:) RC SETMAC\n");
-            RCUD_SETMAC = &RCuser.RCUS_SETMAC;
-            printk (KERN_INFO "(rcpci45 driver:) RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-                    (U8) (RCUD_SETMAC->mac[0]), (U8) (RCUD_SETMAC->mac[1]), (U8) (RCUD_SETMAC->mac[2]),
-                    (U8) (RCUD_SETMAC->mac[3]), (U8) (RCUD_SETMAC->mac[4]), (U8) (RCUD_SETMAC->mac[5]));
-            RCSetMAC(dev, (PU8) &RCUD_SETMAC->mac);
-            break;
-        case RCUC_SETSPEED:
-            printk(KERN_INFO "(rcpci45 driver:) RC SETSPEED\n");
-            RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
-            RCSetLinkSpeed(dev, (U16) RCUD_SETSPEED->LinkSpeedCode);
-            printk(KERN_INFO "(rcpci45 driver:) RC New speed = 0x%x\n", RCUD_SETSPEED->LinkSpeedCode);
-            break;
-        case RCUC_SETPROM:
-            printk(KERN_INFO "(rcpci45 driver:) RC SETPROM\n");
-            RCUD_SETPROM = &RCuser.RCUS_SETPROM;
-            RCSetPromiscuousMode(dev,(U16)RCUD_SETPROM->PromMode);
-            printk(KERN_INFO "(rcpci45 driver:) RC New prom mode = 0x%x\n", RCUD_SETPROM->PromMode);
-            break;
-        case RCUC_SETBROADCAST:
-            printk(KERN_INFO "(rcpci45 driver:) RC SETBROADCAST\n");
-            RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
-            RCSetBroadcastMode(dev,(U16)RCUD_SETBROADCAST->BroadcastMode);
-            printk(KERN_INFO "(rcpci45 driver:) RC New broadcast mode = 0x%x\n", RCUD_SETBROADCAST->BroadcastMode);
-            break;
-        default:
-            printk(KERN_INFO "(rcpci45 driver:) RC command default\n");
-            RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
-            RCUD_DEFAULT -> rc = 0x11223344;
-            break;
-        }
-        if(copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser)))
-        	return -EFAULT;
-        break;
-	}   /* RCU_COMMAND */ 
+	switch (cmd) {
+
+	case RCU_PROTOCOL_REV:
+		/*
+		 * Assign user protocol revision, to tell user-level
+		 * controller program whether or not it's in sync.
+		 */
+		rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;
+		break;
+
+	case RCU_COMMAND:
+		{
+			if (copy_from_user
+			    (&RCuser, rq->ifr_data, sizeof (RCuser)))
+				return -EFAULT;
+
+			dprintk ("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
+
+			switch (RCuser.cmd) {
+			case RCUC_GETFWVER:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETFWVER\n");
+				RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
+				RCGetFirmwareVer (dev,
+						  (PU8) & RCUD_GETFWVER->
+						  FirmString, NULL);
+				break;
+			case RCUC_GETINFO:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETINFO\n");
+				RCUD_GETINFO = &RCuser.RCUS_GETINFO;
+				RCUD_GETINFO->mem_start = dev->base_addr;
+				RCUD_GETINFO->mem_end =
+				    dev->base_addr + pDpa->pci_addr_len;
+				RCUD_GETINFO->base_addr = pDpa->pci_addr;
+				RCUD_GETINFO->irq = dev->irq;
+				break;
+			case RCUC_GETIPANDMASK:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETIPANDMASK\n");
+				RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
+				RCGetRavlinIPandMask (dev,
+						      (PU32) &
+						      RCUD_GETIPANDMASK->IpAddr,
+						      (PU32) &
+						      RCUD_GETIPANDMASK->
+						      NetMask, NULL);
+				break;
+			case RCUC_GETLINKSTATISTICS:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETLINKSTATISTICS\n");
+				RCUD_GETLINKSTATISTICS =
+				    &RCuser.RCUS_GETLINKSTATISTICS;
+				RCGetLinkStatistics (dev,
+						     (P_RCLINKSTATS) &
+						     RCUD_GETLINKSTATISTICS->
+						     StatsReturn, NULL);
+				break;
+			case RCUC_GETLINKSTATUS:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETLINKSTATUS\n");
+				RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
+				RCGetLinkStatus (dev,
+						 (PU32) & RCUD_GETLINKSTATUS->
+						 ReturnStatus, NULL);
+				break;
+			case RCUC_GETMAC:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETMAC\n");
+				RCUD_GETMAC = &RCuser.RCUS_GETMAC;
+				RCGetMAC (dev, NULL);
+				break;
+			case RCUC_GETPROM:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETPROM\n");
+				RCUD_GETPROM = &RCuser.RCUS_GETPROM;
+				RCGetPromiscuousMode (dev,
+						      (PU32) & RCUD_GETPROM->
+						      PromMode, NULL);
+				break;
+			case RCUC_GETBROADCAST:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETBROADCAST\n");
+				RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
+				RCGetBroadcastMode (dev,
+						    (PU32) & RCUD_GETBROADCAST->
+						    BroadcastMode, NULL);
+				break;
+			case RCUC_GETSPEED:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC GETSPEED\n");
+				if (!(dev->flags & IFF_UP)) {
+					printk (KERN_ERR
+						"(rcpci45 driver:) RCioctl, GETSPEED error: interface down\n");
+					return -ENODATA;
+				}
+				RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
+				RCGetLinkSpeed (dev,
+						(PU32) & RCUD_GETSPEED->
+						LinkSpeedCode, NULL);
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC speed = 0x%u\n",
+					RCUD_GETSPEED->LinkSpeedCode);
+				break;
+			case RCUC_SETIPANDMASK:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC SETIPANDMASK\n");
+				RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC New IP Addr = %d.%d.%d.%d, ",
+					(U8) ((RCUD_SETIPANDMASK->
+					       IpAddr) & 0xff),
+					(U8) ((RCUD_SETIPANDMASK->
+					       IpAddr >> 8) & 0xff),
+					(U8) ((RCUD_SETIPANDMASK->
+					       IpAddr >> 16) & 0xff),
+					(U8) ((RCUD_SETIPANDMASK->
+					       IpAddr >> 24) & 0xff));
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC New Mask = %d.%d.%d.%d\n",
+					(U8) ((RCUD_SETIPANDMASK->
+					       NetMask) & 0xff),
+					(U8) ((RCUD_SETIPANDMASK->
+					       NetMask >> 8) & 0xff),
+					(U8) ((RCUD_SETIPANDMASK->
+					       NetMask >> 16) & 0xff),
+					(U8) ((RCUD_SETIPANDMASK->
+					       NetMask >> 24) & 0xff));
+				RCSetRavlinIPandMask (dev,
+						      (U32) RCUD_SETIPANDMASK->
+						      IpAddr,
+						      (U32) RCUD_SETIPANDMASK->
+						      NetMask);
+				break;
+			case RCUC_SETMAC:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC SETMAC\n");
+				RCUD_SETMAC = &RCuser.RCUS_SETMAC;
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+					(U8) (RCUD_SETMAC->mac[0]),
+					(U8) (RCUD_SETMAC->mac[1]),
+					(U8) (RCUD_SETMAC->mac[2]),
+					(U8) (RCUD_SETMAC->mac[3]),
+					(U8) (RCUD_SETMAC->mac[4]),
+					(U8) (RCUD_SETMAC->mac[5]));
+				RCSetMAC (dev, (PU8) & RCUD_SETMAC->mac);
+				break;
+			case RCUC_SETSPEED:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC SETSPEED\n");
+				RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
+				RCSetLinkSpeed (dev,
+						(U16) RCUD_SETSPEED->
+						LinkSpeedCode);
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC New speed = 0x%x\n",
+					RCUD_SETSPEED->LinkSpeedCode);
+				break;
+			case RCUC_SETPROM:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC SETPROM\n");
+				RCUD_SETPROM = &RCuser.RCUS_SETPROM;
+				RCSetPromiscuousMode (dev,
+						      (U16) RCUD_SETPROM->
+						      PromMode);
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC New prom mode = 0x%x\n",
+					RCUD_SETPROM->PromMode);
+				break;
+			case RCUC_SETBROADCAST:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC SETBROADCAST\n");
+				RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
+				RCSetBroadcastMode (dev,
+						    (U16) RCUD_SETBROADCAST->
+						    BroadcastMode);
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC New broadcast mode = 0x%x\n",
+					RCUD_SETBROADCAST->BroadcastMode);
+				break;
+			default:
+				printk (KERN_INFO
+					"(rcpci45 driver:) RC command default\n");
+				RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
+				RCUD_DEFAULT->rc = 0x11223344;
+				break;
+			}
+			if (copy_to_user
+			    (rq->ifr_data, &RCuser, sizeof (RCuser)))
+				return -EFAULT;
+			break;
+		}		/* RCU_COMMAND */
 
 	default:
-        	rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;
-        	return -EINVAL;
-    }
-    return 0;
+		rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;
+		return -EINVAL;
+	}
+	return 0;
 }
 
-static int RCconfig(struct net_device *dev, struct ifmap *map)
+static int
+RCconfig (struct net_device *dev, struct ifmap *map)
 {
-    /*
-     * To be completed ...
-      */
-    dprintk("RCconfig\n");
-    return 0;
-    if (dev->flags & IFF_UP)    /* can't act on a running interface */
-        return -EBUSY;
-
-     /* Don't allow changing the I/O address */
-    if (map->base_addr != dev->base_addr) {
-        printk(KERN_WARNING "(rcpci45 driver:)  Change I/O address not implemented\n");
-        return -EOPNOTSUPP;
-    }
-    return 0;
+	/*
+	 * To be completed ...
+	 */
+	dprintk ("RCconfig\n");
+	return 0;
+	if (dev->flags & IFF_UP)	/* can't act on a running interface */
+		return -EBUSY;
+
+	/* Don't allow changing the I/O address */
+	if (map->base_addr != dev->base_addr) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:)  Change I/O address not implemented\n");
+		return -EOPNOTSUPP;
+	}
+	return 0;
 }
 
-
-static void __exit rcpci_cleanup_module (void)
+static void __exit
+rcpci_cleanup_module (void)
 {
-	pci_unregister_driver(&rcpci45_driver);
+	pci_unregister_driver (&rcpci45_driver);
 }
 
-module_init(rcpci_init_module);
-module_exit(rcpci_cleanup_module);
-
+module_init (rcpci_init_module);
+module_exit (rcpci_cleanup_module);
 
 static int
-RC_allocate_and_post_buffers(struct net_device *dev, int numBuffers)
+RC_allocate_and_post_buffers (struct net_device *dev, int numBuffers)
 {
 
-    int i;
-    PU32 p;
-    psingleB pB;
-    struct sk_buff *skb;
-    RC_RETURN status;
-    U32 res;
-
-    if (!numBuffers)
-        return 0;
-    else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
-    {
-        dprintk("Too many buffers requested!\n");
-        dprintk("attempting to allocate only 32 buffers\n");
-        numBuffers = 32;
-    }
-    
-    p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_KERNEL);
-
-    dprintk("TCB = 0x%x\n", (uint)p);
-
-    if (!p)
-    {
-        printk(KERN_WARNING "(rcpci45 driver:) RCopen: unable to allocate TCB\n");
-        return 0;
-    }
-
-    p[0] = 0;                              /* Buffer Count */
-    pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
-
-    dprintk("p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
-    dprintk("pB = 0x%x\n", (uint)pB);
-
-    for (i=0; i<numBuffers; i++)
-    {
-        skb = dev_alloc_skb(MAX_ETHER_SIZE+2);
-        if (!skb)
-        {
-            dprintk("Doh! RCopen: unable to allocate enough skbs!\n");
-            if (*p != 0)        /* did we allocate any buffers at all? */
-            {
-                dprintk("will post only %d buffers \n", (uint)(*p));
-                break;
-            }
-            else 
-            {
-                kfree(p);    /* Free the TCB */
-                return 0;
-            }
-        }
-        dprintk("post 0x%x\n", (uint)skb);
-        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
-        pB->context = (U32)skb;
-        pB->scount = 1;        /* segment count */
-        pB->size = MAX_ETHER_SIZE;
-        pB->addr = virt_to_bus((void *)skb->data);
-        p[0]++;
-        pB++;
-    }
-
-    if ( (status = RCPostRecvBuffers(dev, (PRCTCB)p )) != RC_RTN_NO_ERROR)
-    {
-        printk(KERN_WARNING "(rcpci45 driver:) Post buffer failed with error code 0x%x!\n", status);
-        pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
-        while(p[0])
-        {
-            skb = (struct sk_buff *)pB->context;
-            dprintk("freeing 0x%x\n", (uint)skb);
-            dev_kfree_skb (skb);
-            p[0]--;
-            pB++;
-        }
-        dprintk("freed all buffers, p[0] = %d\n", (uint)p[0]);
-    }
-    res = p[0];
-    kfree(p);
-    return(res);                /* return the number of posted buffers */
+	int i;
+	PU32 p;
+	psingleB pB;
+	struct sk_buff *skb;
+	RC_RETURN status;
+	U32 res;
+
+	if (!numBuffers)
+		return 0;
+	else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG) {
+		dprintk ("Too many buffers requested!\n");
+		dprintk ("attempting to allocate only 32 buffers\n");
+		numBuffers = 32;
+	}
+
+	p = (PU32) kmalloc (sizeof (U32) + numBuffers * sizeof (singleB),
+			    GFP_KERNEL);
+
+	dprintk ("TCB = 0x%x\n", (uint) p);
+
+	if (!p) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:) RCopen: unable to allocate TCB\n");
+		return 0;
+	}
+
+	p[0] = 0;		/* Buffer Count */
+	pB = (psingleB) ((U32) p + sizeof (U32));	/* point to the first buffer */
+
+	dprintk ("p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint) p[0], (uint) p,
+		 (uint) pB);
+	dprintk ("pB = 0x%x\n", (uint) pB);
+
+	for (i = 0; i < numBuffers; i++) {
+		skb = dev_alloc_skb (MAX_ETHER_SIZE + 2);
+		if (!skb) {
+			dprintk
+			    ("Doh! RCopen: unable to allocate enough skbs!\n");
+			if (*p != 0) {	/* did we allocate any buffers at all? */
+				dprintk ("will post only %d buffers \n",
+					 (uint) (*p));
+				break;
+			} else {
+				kfree (p);	/* Free the TCB */
+				return 0;
+			}
+		}
+		dprintk ("post 0x%x\n", (uint) skb);
+		skb_reserve (skb, 2);	/* Align IP on 16 byte boundaries */
+		pB->context = (U32) skb;
+		pB->scount = 1;	/* segment count */
+		pB->size = MAX_ETHER_SIZE;
+		pB->addr = virt_to_bus ((void *) skb->data);
+		p[0]++;
+		pB++;
+	}
+
+	if ((status = RCPostRecvBuffers (dev, (PRCTCB) p)) != RC_RTN_NO_ERROR) {
+		printk (KERN_WARNING
+			"(rcpci45 driver:) Post buffer failed with error code 0x%x!\n",
+			status);
+		pB = (psingleB) ((U32) p + sizeof (U32));	/* point to the first buffer */
+		while (p[0]) {
+			skb = (struct sk_buff *) pB->context;
+			dprintk ("freeing 0x%x\n", (uint) skb);
+			dev_kfree_skb (skb);
+			p[0]--;
+			pB++;
+		}
+		dprintk ("freed all buffers, p[0] = %d\n", (uint) p[0]);
+	}
+	res = p[0];
+	kfree (p);
+	return (res);		/* return the number of posted buffers */
 }
diff -urN linux-2.4.6-pre8/drivers/net/saa9730.c linux/drivers/net/saa9730.c
--- linux-2.4.6-pre8/drivers/net/saa9730.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/saa9730.c	Mon Dec  3 22:50:38 2001
@@ -44,7 +44,7 @@
 
 
 /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
-static unsigned int pci_irq_line = 0;
+static unsigned int pci_irq_line;
 
 #define INL(a)     inl((unsigned long)a)
 #define OUTL(x,a)  outl(x,(unsigned long)a)
diff -urN linux-2.4.6-pre8/drivers/net/sis900.c linux/drivers/net/sis900.c
--- linux-2.4.6-pre8/drivers/net/sis900.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/sis900.c	Mon Dec  3 22:50:38 2001
@@ -53,6 +53,7 @@
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/mii.h>
 
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -1702,19 +1703,24 @@
 static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
 {
 	struct sis900_private *sis_priv = net_dev->priv;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 
 	switch(cmd) {
-	case SIOCDEVPRIVATE:            	/* Get the address of the PHY in use. */
-		data[0] = sis_priv->mii->phy_addr;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = sis_priv->mii->phy_addr;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:          	/* Read the specified MII register. */
-		data[3] = mdio_read(net_dev, data[0] & 0x1f, data[1] & 0x1f);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:          	/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		mdio_write(net_dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/sis900.h linux/drivers/net/sis900.h
--- linux-2.4.6-pre8/drivers/net/sis900.h	Wed Apr 11 21:17:59 2001
+++ linux/drivers/net/sis900.h	Mon Dec  3 22:50:38 2001
@@ -266,13 +266,5 @@
 #define NUM_TX_DESC     16      	/* Number of Tx descriptor registers. */
 #define NUM_RX_DESC     16       	/* Number of Rx descriptor registers. */
 
-/* PCI stuff, should be move to pic.h */
-#define PCI_DEVICE_ID_SI_900	0x900   
-#define PCI_DEVICE_ID_SI_7016	0x7016
 #define SIS630_VENDOR_ID        0x1039
 #define SIS630_DEVICE_ID        0x0630
-
-/* ioctl for accessing MII transceiver */
-#define SIOCGMIIPHY (SIOCDEVPRIVATE)		/* Get the PHY in use. */
-#define SIOCGMIIREG (SIOCDEVPRIVATE+1)		/* Read a PHY register. */
-#define SIOCSMIIREG (SIOCDEVPRIVATE+2)		/* Write a PHY register */
diff -urN linux-2.4.6-pre8/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- linux-2.4.6-pre8/drivers/net/sk_g16.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/sk_g16.c	Mon Dec  3 22:50:38 2001
@@ -536,8 +536,6 @@
  * Check for a network adaptor of this type, and return '0' if one exists.
  * If dev->base_addr == 0, probe all likely locations.
  * If dev->base_addr == 1, always return failure.
- * If dev->base_addr == 2, allocate space for the device and return success
- *                         (detachable devices only).
  */
 
 int __init SK_init(struct net_device *dev)
diff -urN linux-2.4.6-pre8/drivers/net/starfire.c linux/drivers/net/starfire.c
--- linux-2.4.6-pre8/drivers/net/starfire.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/starfire.c	Mon Dec  3 22:50:38 2001
@@ -149,7 +149,7 @@
 #if defined(__ia64__) || defined(__alpha__) || defined(__sparc__)
 static int rx_copybreak = PKT_BUF_SZ;
 #else
-static int rx_copybreak = 0;
+static int rx_copybreak /* = 0 */;
 #endif
 
 /* Used to pass the media type, etc.
@@ -585,7 +585,7 @@
 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);
 static void	netdev_media_change(struct net_device *dev);
 
@@ -726,7 +726,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;
 
 	if (mtu)
 		dev->mtu = mtu;
@@ -1664,38 +1664,149 @@
 
 			*fptr |= cpu_to_le32(1 << (bit_nr & 31));
 		}
-		/* Clear the perfect filter list. */
-		filter_addr = ioaddr + 0x56000 + 1*16;
+		/* Clear the perfect filter list, skip first entry. */
+		filter_addr = ioaddr + PerfFilterTable + 1 * 16;
 		for (i = 1; i < 16; i++) {
 			writew(0xffff, filter_addr); filter_addr += 4;
 			writew(0xffff, filter_addr); filter_addr += 4;
 			writew(0xffff, filter_addr); filter_addr += 8;
 		}
-		for (filter_addr=ioaddr + 0x56100, i=0; i < 32; filter_addr+= 16, i++)
+		for (filter_addr = ioaddr + HashTable, i=0; i < 32; filter_addr+= 16, i++)
 			writew(mc_filter[i], filter_addr);
 		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 	}
 	writel(rx_mode, ioaddr + RxFilterMode);
 }
 
-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 ethtool_cmd ecmd;
+	struct netdev_private *np = dev->priv;
+
+	if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+		return -EFAULT;
+
+	switch (ecmd.cmd) {
+	case ETHTOOL_GSET:
+		ecmd.supported =
+			SUPPORTED_10baseT_Half |
+			SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half |
+			SUPPORTED_100baseT_Full |
+			SUPPORTED_Autoneg |
+			SUPPORTED_MII;
+
+		ecmd.advertising = ADVERTISED_MII;
+		if (np->advertising & ADVERTISE_10HALF)
+			ecmd.advertising |= ADVERTISED_10baseT_Half;
+		if (np->advertising & ADVERTISE_10FULL)
+			ecmd.advertising |= ADVERTISED_10baseT_Full;
+		if (np->advertising & ADVERTISE_100HALF)
+			ecmd.advertising |= ADVERTISED_100baseT_Half;
+		if (np->advertising & ADVERTISE_100FULL)
+			ecmd.advertising |= ADVERTISED_100baseT_Full;
+		if (np->autoneg) {
+			ecmd.advertising |= ADVERTISED_Autoneg;
+			ecmd.autoneg = AUTONEG_ENABLE;
+		} else
+			ecmd.autoneg = AUTONEG_DISABLE;
+
+		ecmd.port = PORT_MII;
+		ecmd.transceiver = XCVR_INTERNAL;
+		ecmd.phy_address = np->phys[0];
+		ecmd.speed = np->speed100 ? SPEED_100 : SPEED_10;
+		ecmd.duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+		ecmd.maxtxpkt = TX_RING_SIZE;
+		ecmd.maxrxpkt = np->intr_mitigation; /* not 100% accurate */
+
+
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+
+	case ETHTOOL_SSET: {
+		u16 autoneg, speed100, full_duplex;
+
+		autoneg = (ecmd.autoneg == AUTONEG_ENABLE);
+		speed100 = (ecmd.speed == SPEED_100);
+		full_duplex = (ecmd.duplex == DUPLEX_FULL);
+
+		np->autoneg = autoneg;
+		if (speed100 != np->speed100 ||
+		    full_duplex != np->full_duplex) {
+			np->speed100 = speed100;
+			np->full_duplex = full_duplex;
+			/* change advertising bits */
+			np->advertising &= ~(ADVERTISE_10HALF |
+					     ADVERTISE_10FULL |
+					     ADVERTISE_100HALF |
+					     ADVERTISE_100FULL |
+					     ADVERTISE_100BASE4);
+			if (speed100) {
+				if (full_duplex)
+					np->advertising |= ADVERTISE_100FULL;
+				else
+					np->advertising |= ADVERTISE_100HALF;
+			} else {
+				if (full_duplex)
+					np->advertising |= ADVERTISE_10FULL;
+				else
+					np->advertising |= ADVERTISE_10HALF;
+			}
+		}
+		check_duplex(dev);
+		return 0;
+	}
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info;
+		memset(&info, 0, sizeof(info));
+		info.cmd = ecmd.cmd;
+		strcpy(info.driver, DRV_NAME);
+		strcpy(info.version, DRV_VERSION);
+		*info.fw_version = 0;
+		strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev));
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+		       return -EFAULT;
+		return 0;
+	}
+
+	default:
+		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;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 
 	switch(cmd) {
-	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
-		data[0] = np->phys[0] & 0x1f;
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	/* Legacy mii-diag interface */
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		if (data[0] == np->phys[0]) {
-			u16 value = data[2];
-			switch (data[1]) {
+		if (data->phy_id == np->phys[0]) {
+			u16 value = data->val_in;
+			switch (data->reg_num) {
 			case 0:
 				if (value & 0x9000)	/* Autonegotiation. */
 					np->autoneg = 1;
@@ -1710,7 +1821,7 @@
 			}
 			check_duplex(dev);
 		}
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/sundance.c linux/drivers/net/sundance.c
--- linux-2.4.6-pre8/drivers/net/sundance.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/sundance.c	Mon Dec  3 22:50:38 2001
@@ -91,6 +91,7 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -1195,21 +1196,26 @@
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&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 netdev_private *)dev->priv)->phys[0] & 0x1f;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = ((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);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/tlan.c linux/drivers/net/tlan.c
--- linux-2.4.6-pre8/drivers/net/tlan.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/tlan.c	Mon Dec  3 22:50:38 2001
@@ -171,6 +171,7 @@
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/mii.h>
 
 
 typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
@@ -245,21 +246,21 @@
 };
 
 static struct pci_device_id tlan_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_BNC,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_DESKPRO_4000_5233MMX,
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
@@ -911,24 +912,29 @@
 static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	TLanPrivateInfo *priv = dev->priv;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	u32 phy   = priv->phy[priv->phyNum];
 	
 	if (!priv->phyOnline)
 		return -EAGAIN;
 
 	switch(cmd) {
-		case SIOCDEVPRIVATE:
-			data[0] = phy;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+			data->phy_id = phy;
 
-		case SIOCDEVPRIVATE+1: /* Read MII register */
-			TLan_MiiReadReg(dev, data[0] & 0x1f, data[1] & 0x1f, &data[3]);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+			TLan_MiiReadReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, &data->val_out);
 			return 0;
 		
-		case SIOCDEVPRIVATE+2: /* Write MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
-			TLan_MiiWriteReg(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+			TLan_MiiWriteReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 			return 0;
 		default:
 			return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/tlan.h linux/drivers/net/tlan.h
--- linux-2.4.6-pre8/drivers/net/tlan.h	Tue Mar 20 12:05:00 2001
+++ linux/drivers/net/tlan.h	Mon Dec  3 22:50:38 2001
@@ -61,14 +61,6 @@
 	 *
 	 ****************************************************************/
 		
-#define PCI_DEVICE_ID_NETELLIGENT_10			0xAE34
-#define PCI_DEVICE_ID_NETELLIGENT_10_100		0xAE32
-#define PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED		0xAE35
-#define PCI_DEVICE_ID_NETFLEX_3P			0xF130
-#define PCI_DEVICE_ID_NETFLEX_3P_BNC			0xF150
-#define PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT	0xAE43
-#define PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL		0xAE40
-#define PCI_DEVICE_ID_DESKPRO_4000_5233MMX		0xB011
 #define PCI_DEVICE_ID_NETELLIGENT_10_T2			0xB012
 #define PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100	0xB030
 #ifndef PCI_DEVICE_ID_OLICOM_OC2183
diff -urN linux-2.4.6-pre8/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- linux-2.4.6-pre8/drivers/net/tulip/tulip_core.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/tulip/tulip_core.c	Mon Dec  3 22:50:38 2001
@@ -15,8 +15,8 @@
 */
 
 #define DRV_NAME	"tulip"
-#define DRV_VERSION	"0.9.15-pre5"
-#define DRV_RELDATE	"June 16, 2001"
+#define DRV_VERSION	"0.9.15-pre6"
+#define DRV_RELDATE	"July 2, 2001"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -924,66 +924,72 @@
 {
 	struct tulip_private *tp = dev->priv;
 	long ioaddr = dev->base_addr;
-	u16 *data = (u16 *) & rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
 	const unsigned int phy_idx = 0;
 	int phy = tp->phys[phy_idx] & 0x1f;
-	unsigned int regnum = data[1];
+	unsigned int regnum = data->reg_num;
 
 	switch (cmd) {
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
+
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		if (tp->mii_cnt)
-			data[0] = phy;
+			data->phy_id = phy;
 		else if (tp->flags & HAS_NWAY)
-			data[0] = 32;
+			data->phy_id = 32;
 		else if (tp->chip_id == COMET)
-			data[0] = 1;
+			data->phy_id = 1;
 		else
 			return -ENODEV;
-	case SIOCDEVPRIVATE + 1:	/* Read the specified MII register. */
-		if (data[0] == 32 && (tp->flags & HAS_NWAY)) {
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) {
 			int csr12 = inl (ioaddr + CSR12);
 			int csr14 = inl (ioaddr + CSR14);
 			switch (regnum) {
 			case 0:
                                 if (((csr14<<5) & 0x1000) ||
                                         (dev->if_port == 5 && tp->nwayset))
-                                        data[3] = 0x1000;
+                                        data->val_out = 0x1000;
                                 else
-                                        data[3] = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0)
+                                        data->val_out = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0)
                                                 | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0);
 				break;
 			case 1:
-                                data[3] =
+                                data->val_out =
 					0x1848 +
 					((csr12&0x7000) == 0x5000 ? 0x20 : 0) +
 					((csr12&0x06) == 6 ? 0 : 4);
                                 if (tp->chip_id != DC21041)
-                                        data[3] |= 0x6048;
+                                        data->val_out |= 0x6048;
 				break;
 			case 4:
                                 /* Advertised value, bogus 10baseTx-FD value from CSR6. */
-                                data[3] =
+                                data->val_out =
 					((inl(ioaddr + CSR6) >> 3) & 0x0040) + 
 					((csr14 >> 1) & 0x20) + 1;
                                 if (tp->chip_id != DC21041)
-                                         data[3] |= ((csr14 >> 9) & 0x03C0);
+                                         data->val_out |= ((csr14 >> 9) & 0x03C0);
 				break;
-			case 5: data[3] = tp->lpar; break;
-			default: data[3] = 0; break;
+			case 5: data->val_out = tp->lpar; break;
+			default: data->val_out = 0; break;
 			}
 		} else {
-			data[3] = tulip_mdio_read (dev, data[0] & 0x1f, regnum);
+			data->val_out = tulip_mdio_read (dev, data->phy_id & 0x1f, regnum);
 		}
 		return 0;
-	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable (CAP_NET_ADMIN))
 			return -EPERM;
 		if (regnum & ~0x1f)
 			return -EINVAL;
-		if (data[0] == phy) {
-			u16 value = data[2];
+		if (data->phy_id == phy) {
+			u16 value = data->val_in;
 			switch (regnum) {
 			case 0:	/* Check for autonegotiation on or reset. */
 				tp->full_duplex_lock = (value & 0x9000) ? 0 : 1;
@@ -992,19 +998,19 @@
 				break;
 			case 4:
 				tp->advertising[phy_idx] =
-				tp->mii_advertise = data[2];
+				tp->mii_advertise = data->val_in;
 				break;
 			}
 		}
-		if (data[0] == 32 && (tp->flags & HAS_NWAY)) {
-			u16 value = data[2];
+		if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) {
+			u16 value = data->val_in;
 			if (regnum == 0) {
 				if ((value & 0x1200) == 0x1200)
 					t21142_start_nway (dev);
 			} else if (regnum == 4)
 				tp->sym_advertise = value;
 		} else {
-			tulip_mdio_write (dev, data[0] & 0x1f, regnum, data[2]);
+			tulip_mdio_write (dev, data->phy_id & 0x1f, regnum, data->val_in);
 		}
 		return 0;
 	default:
diff -urN linux-2.4.6-pre8/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- linux-2.4.6-pre8/drivers/net/via-rhine.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/via-rhine.c	Mon Dec  3 22:50:38 2001
@@ -139,6 +139,7 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/mii.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -1485,7 +1486,7 @@
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	unsigned long flags;
 	int retval;
 
@@ -1493,18 +1494,23 @@
 	retval = 0;
 
 	switch(cmd) {
-	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
-		data[0] = np->phys[0] & 0x1f;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		break;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN)) {
 			retval = -EPERM;
 			break;
 		}
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		break;
 	default:
 		retval = -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- linux-2.4.6-pre8/drivers/net/wavelan.p.h	Tue Mar  6 19:28:34 2001
+++ linux/drivers/net/wavelan.p.h	Mon Dec  3 22:50:38 2001
@@ -699,12 +699,15 @@
 
 #ifdef	MODULE
 /* Parameters set by insmod */
-static int	io[4]	= { 0, 0, 0, 0 };
-static int	irq[4]	= { 0, 0, 0, 0 };
-static char	name[4][IFNAMSIZ] = { "", "", "", "" };
+static int	io[4];
+static int	irq[4];
+static char	name[4][IFNAMSIZ];
 MODULE_PARM(io, "1-4i");
 MODULE_PARM(irq, "1-4i");
 MODULE_PARM(name, "1-4c" __MODULE_STRING(IFNAMSIZ));
+MODULE_PARM_DESC(io, "WaveLAN I/O base address(es),required");
+MODULE_PARM_DESC(irq, "WaveLAN IRQ number(s)");
+MODULE_PARM_DESC(name, "WaveLAN interface neme(s)");
 #endif	/* MODULE */
 
 #endif	/* WAVELAN_P_H */
diff -urN linux-2.4.6-pre8/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c
--- linux-2.4.6-pre8/drivers/net/winbond-840.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/winbond-840.c	Mon Dec  3 22:50:38 2001
@@ -128,6 +128,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -1349,21 +1350,26 @@
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&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 netdev_private *)dev->priv)->phys[0] & 0x1f;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = ((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);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c
--- linux-2.4.6-pre8/drivers/net/wireless/airo.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/wireless/airo.c	Mon Dec  3 22:50:38 2001
@@ -2984,14 +2984,9 @@
 	printk( KERN_INFO "airo:  Finished probing for PCI adapters\n" );
 #endif
 
-	/* arguably, we should clean up and error exit if pci_module_init
-	 * fails with an error other than -ENODEV, instead of proceeding,
-	 * if ISA devs are present.
+	/* Always exit with success, as we are a library module
+	 * as well as a driver module
 	 */
-	if (have_isa_dev)
-		return 0;
-	if (rc && (rc != -ENODEV))
-		return rc;
 	return 0;
 }
 
diff -urN linux-2.4.6-pre8/drivers/net/wireless/orinoco_cs.c linux/drivers/net/wireless/orinoco_cs.c
--- linux-2.4.6-pre8/drivers/net/wireless/orinoco_cs.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/wireless/orinoco_cs.c	Mon Dec  3 22:50:38 2001
@@ -108,8 +108,8 @@
    device numbers are used to derive the corresponding array index.
 */
 
-static dev_link_t *dev_list = NULL;
-static int num_instances = 0;
+static dev_link_t *dev_list;
+static int num_instances;
 
 /*====================================================================*/
 
diff -urN linux-2.4.6-pre8/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- linux-2.4.6-pre8/drivers/net/yellowfin.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/net/yellowfin.c	Mon Dec  3 22:50:38 2001
@@ -1373,23 +1373,28 @@
 {
 	struct yellowfin_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&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] = np->phys[0] & 0x1f;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = np->phys[0] & 0x1f;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		if (data[0] == np->phys[0]) {
-			u16 value = data[2];
-			switch (data[1]) {
+		if (data->phy_id == np->phys[0]) {
+			u16 value = data->val_in;
+			switch (data->reg_num) {
 			case 0:
 				/* Check for autonegotiation on or reset. */
 				np->medialock = (value & 0x9000) ? 0 : 1;
@@ -1400,7 +1405,7 @@
 			}
 			/* Perhaps check_duplex(dev), depending on chip semantics. */
 		}
-		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
diff -urN linux-2.4.6-pre8/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux-2.4.6-pre8/drivers/pci/pci.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/pci/pci.c	Mon Dec  3 22:50:38 2001
@@ -420,11 +420,13 @@
 	if (!value || !(value & (1 << state))) 
 		return enable ? -EINVAL : 0;
 
-	/* Enable PME# Generation */
 	pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);
 
-	if (enable) value |= PCI_PM_CTRL_PME_STATUS;
-	else value &= ~PCI_PM_CTRL_PME_STATUS;
+	/* Clear PME_Status by writing 1 to it and enable PME# */
+	value |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE;
+
+	if (!enable)
+		value &= ~PCI_PM_CTRL_PME_ENABLE;
 
 	pci_write_config_word(dev, pm + PCI_PM_CTRL, value);
 	
diff -urN linux-2.4.6-pre8/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- linux-2.4.6-pre8/drivers/pci/pci.ids	Mon Dec  3 22:50:28 2001
+++ linux/drivers/pci/pci.ids	Mon Dec  3 22:50:38 2001
@@ -244,6 +244,7 @@
 	000f  OHCI Compliant FireWire Controller
 	0011  National PCI System I/O
 	0012  USB Controller
+	0020  DP83815 (MacPhyter) Ethernet Controller
 	d001  87410 IDE
 100c  Tseng Labs Inc
 	3202  ET4000/W32p rev A
@@ -383,10 +384,12 @@
 		1014 00cf  16/4 Token-Ring Adapter Special
 		1014 00e4  High-Speed 100/16/4 Token-Ring Adapter
 		1014 00e5  16/4 Token-Ring Adapter 2 + Wake-On-LAN
+		1014 016d  iSeries 2744 Card
 	0045  SSA Adapter
 	0046  MPIC interrupt controller
 	0047  PCI to PCI Bridge
 	0048  PCI to PCI Bridge
+	0049  Warhead SCSI Controller
 	004e  ATM Controller (14104e00)
 	004f  ATM Controller (14104f00)
 	0050  ATM Controller (14105000)
@@ -398,6 +401,10 @@
 	0090  GXT 3000P
 		1014 008E  GXT-3000P
 	0095  20H2999 PCI Docking Bridge
+	0096  Chukar chipset SCSI controller
+		1014 0099  iSeries 2748 DASD IOA
+		1014 0098  iSeries 2763 DASD IOA
+		1014 0097  iSeries 2778 DASD IOA
 	00a5  ATM Controller (1410a500)
 	00a6  ATM 155MBPS MM Controller (1410a600)
 	00b7  256-bit Graphics Rasterizer [Fire GL1]
@@ -458,6 +465,8 @@
 	2040  79c974
 	7006  AMD-751 [Irongate] System Controller
 	7007  AMD-751 [Irongate] AGP Bridge
+	700E  AMD-760 [Irongate] System Controller
+	700F  AMD-760 [Irongate] AGP Bridge
 	7400  AMD-755 [Cobra] ISA
 	7401  AMD-755 [Cobra] IDE
 	7403  AMD-755 [Cobra] ACPI
@@ -466,6 +475,10 @@
 	7409  AMD-756 [Viper] IDE
 	740b  AMD-756 [Viper] ACPI
 	740c  AMD-756 [Viper] USB
+	7410  AMD-765 [Viper] ISA
+	7411  AMD-765 [Viper] IDE
+	7413  AMD-765 [Viper] ACPI
+	7414  AMD-765 [Viper] USB
 1023  Trident Microsystems
 	0194  82C194
 	2000  4DWave DX
@@ -993,6 +1006,7 @@
 	4d30  20267
 	4d33  20246
 	4d38  20262
+	4d68  20268
 	5300  DC5300
 105b  Foxconn International, Inc.
 105c  Wipro Infotech Limited
@@ -1925,9 +1939,9 @@
 		1102 8051  CT4850 SBLive! Value
 	7002  SB Live!
 		1102 0020  Gameport Joystick
-1103  Triones Technologies, Inc.
-	0003  HPT343
-	0004  HPT366
+1103  HighPoint Technologies, Inc.
+	0003  HPT343 UltraDMA 33 IDE Controller
+	0004  HPT366/370 UltraDMA 66/100 IDE Controller
 1104  RasterOps Corp.
 1105  Sigma Designs, Inc.
 	8300  REALmagic Hollywood Plus DVD Decoder
@@ -2217,7 +2231,7 @@
 1145  Workbit Corporation
 1146  Force Computers
 1147  Interface Corp
-1148  Syskonnect (Schneider & Koch)
+1148  SysKonnect GmbH
 	4000  FDDI Adapter
 		0e11 b03b  Netelligent 100 FDDI DAS Fibre SC
 		0e11 b03c  Netelligent 100 FDDI SAS Fibre SC
@@ -2234,7 +2248,7 @@
 		1148 5841  FDDI SK-5841 (SK-NET FDDI-FP64)
 		1148 5843  FDDI SK-5843 (SK-NET FDDI-LP64)
 		1148 5844  FDDI SK-5844 (SK-NET FDDI-LP64 DAS)
-	4200  Token ring adaptor
+	4200  Token Ring adapter
 	4300  Gigabit Ethernet
 		1148 9821  SK-9821 (1000Base-T single link)
 		1148 9822  SK-9822 (1000Base-T dual link)
@@ -2242,6 +2256,8 @@
 		1148 9842  SK-9842 (1000Base-LX dual link)
 		1148 9843  SK-9843 (1000Base-SX single link)
 		1148 9844  SK-9844 (1000Base-SX dual link)
+		1148 9861  SK-9861 (1000Base-SX VF45 single link)
+		1148 9862  SK-9862 (1000Base-SX VF45 dual link)
 1149  Win System Corporation
 114a  VMIC
 	7587  VMIVME-7587
@@ -2335,13 +2351,16 @@
 1165  Imagraph Corporation
 	0001  Motion TPEG Recorder/Player with audio
 1166  ServerWorks
-	0007  CNB20-LE CPU to PCI Bridge
-	0008  CNB20HE
-	0009  CNB20LE
+	0007  CNB20-LE Host Bridge
+	0008  CNB20HE Host Bridge
+	0009  CNB20LE Host Bridge
 	0010  CIOB30
 	0011  CMIC-HE
-	0200  OSB4
-	0201  CSB5
+	0200  OSB4 South Bridge
+	0201  CSB5 South Bridge
+	0211  OSB4 IDE Controller
+	0212  CSB5 IDE Controller
+	0220  OSB4/CSB5 OHCI USB Controller
 1167  Mutoh Industries Inc
 1168  Thine Electronics Inc
 1169  Centre for Development of Advanced Computing
@@ -2455,7 +2474,9 @@
 	1221  82C092G
 119c  Information Technology Inst.
 119d  Bug, Inc. Sapporo Japan
-119e  Fujitsu Microelectronics Ltd.
+119e  Fujitsu Microelectronics Europe GMBH
+	0001 FireStream 155
+	0003 FireStream 50
 119f  Bull HN Information Systems
 11a0  Convex Computer Corporation
 11a1  Hamamatsu Photonics K.K.
@@ -3002,13 +3023,14 @@
 		8086 5643  ES1371, ES1373 AudioPCI On Motherboard Vancouver
 		8086 5753  ES1371, ES1373 AudioPCI On Motherboard WS440BX
 	5000  ES1370 [AudioPCI]
-	5880  5880 AudioPCI
+		4942 4c4c  Creative Sound Blaster AudioPCI128
+	5880  CT5880 [AudioPCI]
 		1274 2000  Creative Sound Blaster AudioPCI128
 		1274 5880  Creative Sound Blaster AudioPCI128
-		1462 6880  5880 AudioPCI On Motherboard MS-6188 1.00
-		270f 2001  5880 AudioPCI On Motherboard 6CTR
-		270f 2200  5880 AudioPCI On Motherboard 6WTX
-		270f 7040  5880 AudioPCI On Motherboard 6ATA4
+		1462 6880  CT5880 AudioPCI On Motherboard MS-6188 1.00
+		270f 2001  CT5880 AudioPCI On Motherboard 6CTR
+		270f 2200  CT5880 AudioPCI On Motherboard 6WTX
+		270f 7040  CT5880 AudioPCI On Motherboard 6ATA4
 1275  Network Appliance Corporation
 1276  Switched Network Technologies, Inc.
 1277  Comstream
diff -urN linux-2.4.6-pre8/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- linux-2.4.6-pre8/drivers/scsi/scsi_syms.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/scsi/scsi_syms.c	Mon Dec  3 22:50:38 2001
@@ -91,3 +91,10 @@
 EXPORT_SYMBOL(scsi_devicelist);
 EXPORT_SYMBOL(scsi_device_types);
 
+/*
+ * Externalize timers so that HBAs can safely start/restart commands.
+ */
+extern void scsi_add_timer(Scsi_Cmnd *, int, void ((*) (Scsi_Cmnd *)));
+extern int scsi_delete_timer(Scsi_Cmnd *);
+EXPORT_SYMBOL(scsi_add_timer);
+EXPORT_SYMBOL(scsi_delete_timer);
diff -urN linux-2.4.6-pre8/drivers/sound/Config.in linux/drivers/sound/Config.in
--- linux-2.4.6-pre8/drivers/sound/Config.in	Wed Apr 18 11:49:11 2001
+++ linux/drivers/sound/Config.in	Mon Dec  3 22:50:38 2001
@@ -81,6 +81,7 @@
 fi
 
 dep_tristate '  VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI
+dep_mbool    '  VIA 82C686 MIDI' CONFIG_MIDI_VIA82CXXX $CONFIG_SOUND_VIA82CXXX
 
 dep_tristate '  OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
 
diff -urN linux-2.4.6-pre8/drivers/sound/Makefile linux/drivers/sound/Makefile
--- linux-2.4.6-pre8/drivers/sound/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/drivers/sound/Makefile	Mon Dec  3 22:50:38 2001
@@ -47,6 +47,9 @@
 obj-$(CONFIG_SOUND_AWE32_SYNTH)	+= awe_wave.o
 
 obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
+ifeq ($(CONFIG_MIDI_VIA82CXXX),y)
+  obj-$(CONFIG_SOUND_VIA82CXXX) += sound.o uart401.o
+endif
 obj-$(CONFIG_SOUND_YMFPCI)	+= ymfpci.o ac97_codec.o
 ifeq ($(CONFIG_SOUND_YMFPCI_LEGACY),y)
   obj-$(CONFIG_SOUND_YMFPCI)    += opl3.o uart401.o
diff -urN linux-2.4.6-pre8/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c
--- linux-2.4.6-pre8/drivers/sound/cs4232.c	Sat Nov 11 18:33:13 2000
+++ linux/drivers/sound/cs4232.c	Mon Dec  3 22:50:38 2001
@@ -42,9 +42,11 @@
  * 	Arnaldo C. de Melo	got rid of attach_uart401
  *	Bartlomiej Zolnierkiewicz
  *				Added some __init/__initdata/__exit
+ *	Marcus Meissner		Added ISA PnP support.
  */
 
 #include <linux/config.h>
+#include <linux/isapnp.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
@@ -95,7 +97,7 @@
 	schedule_timeout(howlong);
 }
 
-int __init probe_cs4232(struct address_info *hw_config)
+int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
 {
 	int i, n;
 	int base = hw_config->io_base, irq = hw_config->irq;
@@ -110,8 +112,13 @@
 		printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
 		return 0;
 	}
-	if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
+	if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) {
 		return 1;	/* The card is already active */
+	}
+	if (isapnp_configured) {
+		printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n");
+		return 0;
+	}
 
 	/*
 	 * This version of the driver doesn't use the PnP method when configuring
@@ -318,27 +325,97 @@
 static int __initdata mpuirq	= -1;
 static int __initdata synthio	= -1;
 static int __initdata synthirq	= -1;
+static int __initdata isapnp	= 1;
 
-
+MODULE_DESCRIPTION("CS4232 based soundcard driver"); 
+MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis"); 
 MODULE_PARM(io,"i");
+MODULE_PARM_DESC(io,"base I/O port for AD1848");
 MODULE_PARM(irq,"i");
+MODULE_PARM_DESC(irq,"IRQ for AD1848 chip");
 MODULE_PARM(dma,"i");
+MODULE_PARM_DESC(dma,"8 bit DMA for AD1848 chip");
 MODULE_PARM(dma2,"i");
+MODULE_PARM_DESC(dma2,"16 bit DMA for AD1848 chip");
 MODULE_PARM(mpuio,"i");
+MODULE_PARM_DESC(mpuio,"MPU 401 base address");
 MODULE_PARM(mpuirq,"i");
+MODULE_PARM_DESC(mpuirq,"MPU 401 IRQ");
 MODULE_PARM(synthio,"i");
+MODULE_PARM_DESC(synthio,"Maui WaveTable base I/O port");
 MODULE_PARM(synthirq,"i");
+MODULE_PARM_DESC(synthirq,"Maui WaveTable IRQ");
+MODULE_PARM(isapnp,"i");
+MODULE_PARM_DESC(isapnp,"Enable ISAPnP probing (default 1)");
 
 /*
  *	Install a CS4232 based card. Need to have ad1848 and mpu401
  *	loaded ready.
  */
 
+/* All cs4232 based cards have the main ad1848 card either as CSC0000 or
+ * CSC0100. */
+struct isapnp_device_id isapnp_cs4232_list[] __initdata = {
+	{       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100),
+		0 },
+	{       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000),
+		0 },
+	/* Guillemot Turtlebeach something appears to be cs4232 compatible
+	 * (untested) */
+	{       ISAPNP_VENDOR('C','S','C'), ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('G','I','M'), ISAPNP_FUNCTION(0x0100),
+		0 },
+	{0}
+};
+
+MODULE_DEVICE_TABLE(isapnp, isapnp_cs4232_list);
+
+int cs4232_isapnp_probe(struct pci_dev *dev, const struct isapnp_device_id *id)
+{
+	int ret;
+	struct address_info *isapnpcfg;
+
+	isapnpcfg=(struct address_info*)kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
+	if (!isapnpcfg) 
+		return -ENOMEM;
+	/*
+	 * If device is active, assume configured with /proc/isapnp
+	 * and use anyway. Any other way to check this?
+	 */
+	ret = dev->prepare(dev);
+	if(ret && ret != -EBUSY) {
+		printk(KERN_ERR "cs4232: ISA PnP found device that could not be autoconfigured.\n");
+		kfree(isapnpcfg);
+		return -ENODEV;
+	}
+	if(ret != -EBUSY) {
+		if(dev->activate(dev) < 0) {
+			printk(KERN_WARNING "cs4232: ISA PnP activate failed\n");
+			kfree(isapnpcfg);
+			return -ENODEV;
+		}
+	} /* else subfunction is already activated */
+
+	isapnpcfg->irq		= dev->irq_resource[0].start;
+	isapnpcfg->dma		= dev->dma_resource[0].start;
+	isapnpcfg->dma2		= dev->dma_resource[1].start;
+	isapnpcfg->io_base	= dev->resource[0].start;
+	if (probe_cs4232(isapnpcfg,TRUE) == 0) {
+		printk(KERN_ERR "cs4232: ISA PnP card found, but not detected?\n");
+		return -ENODEV;
+	}
+	attach_cs4232(isapnpcfg);
+	pci_set_drvdata(dev,isapnpcfg);
+	return 0;
+}
+
 static int __init init_cs4232(void)
 {
 #ifdef CONFIG_SOUND_WAVEFRONT_MODULE
 	if(synthio == -1)
-		printk(KERN_WARNING "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
+		printk(KERN_INFO "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
 	else {
 		synth_base = synthio;
 		synth_irq =  synthirq;	
@@ -347,6 +424,13 @@
 	if(synthio != -1)
 		printk(KERN_WARNING "cs4232: wavefront support not enabled in this driver.\n");
 #endif
+	cfg.irq = -1;
+
+	if (isapnp &&
+	    (isapnp_probe_devs(isapnp_cs4232_list, cs4232_isapnp_probe) > 0)
+	)
+		return 0;
+
 	if(io==-1||irq==-1||dma==-1)
 	{
 		printk(KERN_ERR "cs4232: Must set io, irq and dma.\n");
@@ -367,16 +451,27 @@
 		probe_cs4232_mpu(&cfg_mpu); /* Bug always returns 0 not OK -- AC */
 	}
 
-	if (probe_cs4232(&cfg) == 0)
+	if (probe_cs4232(&cfg,FALSE) == 0)
 		return -ENODEV;
 	attach_cs4232(&cfg);
 	
 	return 0;
 }
 
+int cs4232_isapnp_remove(struct pci_dev *dev, const struct isapnp_device_id *id)
+{
+	struct address_info *cfg = (struct address_info*)pci_get_drvdata(dev);
+	if (cfg) unload_cs4232(cfg);
+	pci_set_drvdata(dev,NULL);
+	dev->deactivate(dev);
+	return 0;
+}
+
 static void __exit cleanup_cs4232(void)
 {
-        unload_cs4232(&cfg); /* unloads MPU as well, if needed */
+	isapnp_probe_devs(isapnp_cs4232_list, cs4232_isapnp_remove);
+        if (cfg.irq != -1)
+		unload_cs4232(&cfg); /* Unloads global MPU as well, if needed */
 }
 
 module_init(init_cs4232);
@@ -387,6 +482,10 @@
 {
 	/* io, irq, dma, dma2 mpuio, mpuirq*/
 	int ints[7];
+
+	/* If we have isapnp cards, no need for options */
+	if (isapnp_probe_devs(isapnp_cs4232_list, cs4232_isapnp_probe) > 0)
+		return 1;
 	
 	str = get_options(str, ARRAY_SIZE(ints), ints);
 	
diff -urN linux-2.4.6-pre8/drivers/sound/cs4232.h linux/drivers/sound/cs4232.h
--- linux-2.4.6-pre8/drivers/sound/cs4232.h	Tue Mar  7 13:40:24 2000
+++ linux/drivers/sound/cs4232.h	Mon Dec  3 22:50:38 2001
@@ -5,7 +5,7 @@
  *
  */
 
-int probe_cs4232 (struct address_info *hw_config);
+int probe_cs4232 (struct address_info *hw_config,int useisapnp);
 void attach_cs4232 (struct address_info *hw_config);
 int probe_cs4232_mpu (struct address_info *hw_config);
 void attach_cs4232_mpu (struct address_info *hw_config);
diff -urN linux-2.4.6-pre8/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c
--- linux-2.4.6-pre8/drivers/sound/cs46xx.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/sound/cs46xx.c	Mon Dec  3 22:50:38 2001
@@ -383,8 +383,8 @@
 static int cs46xx_powerup(struct cs_card *card, unsigned int type);
 static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
 static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
-static void cs46xx_suspend_tbl(struct pci_dev *pcidev);
-static void cs46xx_resume_tbl(struct pci_dev *pcidev);
+static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state);
+static int cs46xx_resume_tbl(struct pci_dev *pcidev);
 
 static inline unsigned ld2(unsigned int x)
 {
@@ -3655,7 +3655,7 @@
 
 static void cs461x_reset(struct cs_card *card);
 static void cs461x_proc_stop(struct cs_card *card);
-static int cs46xx_suspend(struct cs_card *card)
+static int cs46xx_suspend(struct cs_card *card, u32 state)
 {
 	unsigned int tmp;
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
@@ -4174,7 +4174,7 @@
 				list_for_each(entry, &cs46xx_devs)
 				{
 					card = list_entry(entry, struct cs_card, list);
-					cs46xx_suspend(card);
+					cs46xx_suspend(card, 0);
 				}
 
 			}
@@ -5665,7 +5665,7 @@
 			case PM_SUSPEND:
 				CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
 					"cs46xx: PM suspend request\n"));
-				if(cs46xx_suspend(card))
+				if(cs46xx_suspend(card, 0))
 				{
 				    CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
 					"cs46xx: PM suspend request refused\n"));
@@ -5694,7 +5694,7 @@
 	struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 2, 
 		printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n"));
-	cs46xx_suspend(s);
+	cs46xx_suspend(s, 0);
 	return 0;
 }
 
diff -urN linux-2.4.6-pre8/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c
--- linux-2.4.6-pre8/drivers/sound/emu10k1/audio.c	Wed Apr 18 11:49:11 2001
+++ linux/drivers/sound/emu10k1/audio.c	Mon Dec  3 22:50:38 2001
@@ -903,33 +903,46 @@
 
 	case SNDCTL_COPR_LOAD:
 		{
-			copr_buffer buf;
+			copr_buffer *buf;
 			u32 i;
+			int ret = -EFAULT;
 
 			DPF(2, "SNDCTL_COPR_LOAD:\n");
+			
+			buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL);
+			if(buf == NULL)
+				return -ENOMEM;
+
+			if (copy_from_user(buf, (copr_buffer *) arg, sizeof(buf)))
+				goto fail;
+
+			if ((buf->command != 1) && (buf->command != 2))
+			{
+				ret = -EINVAL;
+				goto fail;
+			}
 
-			if (copy_from_user(&buf, (copr_buffer *) arg, sizeof(buf)))
-				return -EFAULT;
-
-			if ((buf.command != 1) && (buf.command != 2))
-				return -EINVAL;
-
-			if ((buf.offs < 0x100)
-			    || (buf.offs < 0x000)
-			    || (buf.offs + buf.len > 0x800) || (buf.len > 1000))
-				return -EINVAL;
-
-			if (buf.command == 1) {
-				for (i = 0; i < buf.len; i++)
-					((u32 *) buf.data)[i] = sblive_readptr(wave_dev->card, buf.offs + i, 0);
+			if ((buf->offs < 0x100)
+			    || (buf->offs < 0x000)
+			    || (buf->offs + buf->len > 0x800) || (buf->len > 1000))
+			{
+				ret = -EINVAL;
+				goto fail;
+			}
+			if (buf->command == 1) {
+				for (i = 0; i < buf->len; i++)
+					((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, 0);
 
-				if (copy_to_user((copr_buffer *) arg, &buf, sizeof(buf)))
-					return -EFAULT;
+				if (copy_to_user((copr_buffer *) arg, buf, sizeof(buf)))
+					goto fail;
 			} else {
-				for (i = 0; i < buf.len; i++)
-					sblive_writeptr(wave_dev->card, buf.offs + i, 0, ((u32 *) buf.data)[i]);
+				for (i = 0; i < buf->len; i++)
+					sblive_writeptr(wave_dev->card, buf->offs + i, 0, ((u32 *) buf->data)[i]);
 			}
-			break;
+			ret = 0;
+		fail:			
+			kfree(buf);
+			return ret;
 		}
 
 	default:		/* Default is unrecognized command */
diff -urN linux-2.4.6-pre8/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- linux-2.4.6-pre8/drivers/sound/via82cxxx_audio.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/sound/via82cxxx_audio.c	Mon Dec  3 22:50:38 2001
@@ -39,6 +39,9 @@
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/semaphore.h>
+#include "sound_config.h"
+#include "dev_table.h"
+#include "mpu401.h"
 
 
 #undef VIA_DEBUG	/* define to enable debugging output and checks */
@@ -178,6 +181,8 @@
 #define VIA_CR42_MIDI_ENABLE	0x02
 #define VIA_CR42_FM_ENABLE	0x04
 #define VIA_CR42_GAME_ENABLE	0x08
+#define VIA_CR42_MIDI_IRQMASK   0x40
+#define VIA_CR42_MIDI_PNP	0x80
 
 #define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
 #define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
@@ -290,6 +295,11 @@
 	struct via_channel ch_in;
 	struct via_channel ch_out;
 	struct via_channel ch_fm;
+
+#ifdef CONFIG_MIDI_VIA82CXXX
+        void *midi_devc;
+        struct address_info midi_info;
+#endif
 };
 
 
@@ -720,12 +730,10 @@
 
 	/* set location of DMA-able scatter-gather info table */
 	DPRINTK ("outl (0x%X, 0x%04lX)\n",
-		cpu_to_le32 (chan->sgt_handle),
-		chan->iobase + VIA_PCM_TABLE_ADDR);
+		chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
 
 	via_ac97_wait_idle (card);
-	outl (cpu_to_le32 (chan->sgt_handle),
-	      chan->iobase + VIA_PCM_TABLE_ADDR);
+	outl (chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
 	udelay (20);
 	via_ac97_wait_idle (card);
 
@@ -1216,25 +1224,28 @@
 
 	card = codec->private_data;
 
-	data = (reg << 16) | VIA_CR80_READ;
+	/* Every time we write to register 80 we cause a transaction.
+	   The only safe way to clear the valid bit is to write it at
+	   the same time as the command */
+	data = (reg << 16) | VIA_CR80_READ | VIA_CR80_VALID;
 
 	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
-	udelay (20);
-
 	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
-		if (inl (card->baseaddr + 0x80) & VIA_CR80_VALID)
+	        udelay (1);
+		if ((((data = inl(card->baseaddr + 0x80)) &
+			(VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID))
 			goto out;
-
-		udelay (15);
 	}
 
 	printk (KERN_WARNING PFX "timeout while reading AC97 codec (0x%lX)\n", data);
 	goto err_out;
 
 out:
+	/* Once the valid bit has become set, we must wait a complete AC97
+	   frame before the data has settled. */
+        udelay(25);
 	data = (unsigned long) inl (card->baseaddr + 0x80);
-	outb (0x02, card->baseaddr + 0x83);
-
+        
 	if (((data & 0x007F0000) >> 16) == reg) {
 		DPRINTK ("EXIT, success, data=0x%lx, retval=0x%lx\n",
 			 data, data & 0x0000FFFF);
@@ -1371,7 +1382,6 @@
 static int __init via_ac97_reset (struct via_info *card)
 {
 	struct pci_dev *pdev = card->pdev;
-	u8 tmp8;
 	u16 tmp16;
 
 	DPRINTK ("ENTER\n");
@@ -1569,10 +1579,10 @@
 	 * and advance the h/w ptr, wrapping around to zero if needed
 	 */
 	if (n == (chan->frag_number - 1)) {
-		chan->sgtable[n].count = (chan->frag_size | VIA_EOL);
+		chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_EOL);
 		atomic_set (&chan->hw_ptr, 0);
 	} else {
-		chan->sgtable[n].count = (chan->frag_size | VIA_FLAG);
+		chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_FLAG);
 		atomic_inc (&chan->hw_ptr);
 	}
 
@@ -1628,8 +1638,12 @@
 	 */
 	status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW);
 	if (!(status32 & VIA_INTR_MASK))
+        {
+#ifdef CONFIG_MIDI_VIA82CXXX
+                uart401intr(irq, card->midi_devc, regs);
+#endif
 		return;
-
+    	}	    
 	DPRINTK ("intr, status32 == 0x%08X\n", status32);
 
 	/* synchronize interrupt handling under SMP.  this spinlock
@@ -1781,10 +1795,8 @@
 
 	/* turn off legacy features, if not already */
 	pci_read_config_byte (card->pdev, VIA_FUNC_ENABLE, &tmp8);
-	if (tmp8 & (VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-		    VIA_CR42_FM_ENABLE)) {
-		tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-			  VIA_CR42_FM_ENABLE);
+	if (tmp8 & (VIA_CR42_SB_ENABLE |  VIA_CR42_FM_ENABLE)) {
+		tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE);
 		pci_write_config_byte (card->pdev, VIA_FUNC_ENABLE, tmp8);
 	}
 
@@ -2682,6 +2694,7 @@
 	/* wait until all buffers have been played, and then stop device */
 	case SNDCTL_DSP_SYNC:
 		DPRINTK ("DSP_SYNC\n");
+		rc = 0;
 		if (wr) {
 			DPRINTK ("SYNC EXIT (after calling via_dsp_drain_playback)\n");
 			rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
@@ -3010,6 +3023,9 @@
 
 static int __init via_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
 {
+#ifdef CONFIG_MIDI_VIA82CXXX
+	u8 r42;
+#endif
 	int rc;
 	struct via_info *card;
 	static int printed_version = 0;
@@ -3019,25 +3035,19 @@
 	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)) {
-		printk (KERN_ERR PFX "unable to obtain I/O resources, aborting\n");
-		rc = -EBUSY;
+	rc = pci_enable_device (pdev);
+	if (rc)
 		goto err_out;
-	}
 
+	rc = pci_request_regions (pdev, "via82cxxx_audio");
+	if (rc)
+		goto err_out_disable;
 
 	card = kmalloc (sizeof (*card), GFP_KERNEL);
 	if (!card) {
 		printk (KERN_ERR PFX "out of memory, aborting\n");
 		rc = -ENOMEM;
-		goto err_out_none;
+		goto err_out_res;
 	}
 
 	pci_set_drvdata (pdev, card);
@@ -3111,6 +3121,34 @@
 	printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n",
 		card->card_num + 1, card->baseaddr, pdev->irq);
 
+#ifdef CONFIG_MIDI_VIA82CXXX
+	/* Disable by default */
+	card->midi_info.io_base = 0;
+
+	pci_read_config_byte (pdev, 0x42, &r42);
+	/* Disable MIDI interrupt */
+	pci_write_config_byte (pdev, 0x42, r42 | VIA_CR42_MIDI_IRQMASK);
+	if (r42 & VIA_CR42_MIDI_ENABLE)
+	{
+		if (r42 & VIA_CR42_MIDI_PNP) /* Address selected by iobase 2 - not tested */
+			card->midi_info.io_base = pci_resource_start (pdev, 2);
+		else /* Address selected by byte 0x43 */
+		{
+			u8 r43;
+			pci_read_config_byte (pdev, 0x43, &r43);
+			card->midi_info.io_base = 0x300 + ((r43 & 0x0c) << 2);
+		}
+		
+		card->midi_info.irq = -pdev->irq;
+		if (probe_uart401(& card->midi_info, THIS_MODULE))
+		{
+			card->midi_devc=midi_devs[card->midi_info.slots[4]]->devc;
+			pci_write_config_byte(pdev, 0x42, r42 & ~VIA_CR42_MIDI_IRQMASK);
+			printk("Enabled Via MIDI\n");
+		}
+	}
+#endif
+
 	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 
@@ -3129,8 +3167,12 @@
 #endif
 	kfree (card);
 
-err_out_none:
-	release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
+err_out_res:
+	pci_release_regions (pdev);
+
+err_out_disable:
+	pci_disable_device (pdev);
+
 err_out:
 	pci_set_drvdata (pdev, NULL);
 	DPRINTK ("EXIT - returning %d\n", rc);
@@ -3148,13 +3190,16 @@
 	card = pci_get_drvdata (pdev);
 	assert (card != NULL);
 
+#ifdef CONFIG_MIDI_VIA82CXXX
+	if (card->midi_info.io_base)
+	    unload_uart401(&card->midi_info);
+#endif
+
 	via_interrupt_cleanup (card);
 	via_card_cleanup_proc (card);
 	via_dsp_cleanup (card);
 	via_ac97_cleanup (card);
 
-	release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
-
 #ifndef VIA_NDEBUG
 	memset (card, 0xAB, sizeof (*card)); /* poison memory */
 #endif
@@ -3162,7 +3207,9 @@
 
 	pci_set_drvdata (pdev, NULL);
 
+	pci_release_regions (pdev);
 	pci_set_power_state (pdev, 3); /* ...zzzzzz */
+	pci_disable_device (pdev);
 
 	DPRINTK ("EXIT\n");
 	return;
diff -urN linux-2.4.6-pre8/drivers/usb/se401.c linux/drivers/usb/se401.c
--- linux-2.4.6-pre8/drivers/usb/se401.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/usb/se401.c	Mon Dec  3 22:50:38 2001
@@ -49,6 +49,7 @@
 #include "se401.h"
 
 static int flickerless=0;
+static int video_nr = -1;
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
 static __devinitdata struct usb_device_id device_table [] = {
@@ -63,12 +64,11 @@
 MODULE_DEVICE_TABLE(usb, device_table);
 #endif
 
-static int video_nr = -1;
-
 MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
 MODULE_DESCRIPTION("SE401 USB Camera Driver");
 MODULE_PARM(flickerless, "i");
 MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
+MODULE_PARM(video_nr, "i");
 EXPORT_NO_SYMBOLS;
 
 
@@ -1286,6 +1286,9 @@
 		if (copy_from_user((void *)&frame, arg, sizeof(int)))
 			return -EFAULT;
 
+		if(frame <0 || frame >= SE401_NUMFRAMES)
+			return -EINVAL;
+			
 		ret=se401_newframe(se401, frame);
 		se401->frame[frame].grabstate=FRAME_UNUSED;
 		return ret;
diff -urN linux-2.4.6-pre8/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c
--- linux-2.4.6-pre8/drivers/video/aty128fb.c	Mon Dec  3 22:50:28 2001
+++ linux/drivers/video/aty128fb.c	Mon Dec  3 22:50:38 2001
@@ -111,7 +111,6 @@
 };
 #endif /* CONFIG_PPC */
 
-#ifndef MODULE
 /* default modedb mode */
 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
 static struct fb_videomode defaultmode __initdata = {
@@ -128,7 +127,6 @@
 	sync:		0,
 	vmode:		FB_VMODE_NONINTERLACED
 };
-#endif /* MODULE */
 
 /* struct to hold chip description information */
 struct aty128_chip_info {
@@ -213,11 +211,13 @@
 
 static const char *aty128fb_name = "ATY Rage128";
 static char fontname[40] __initdata = { 0 };
+
 static int  noaccel __initdata = 0;
+static char *font __initdata = NULL;
+static char *mode __initdata = NULL;
+static int  nomtrr __initdata = 0;
 
-#ifndef MODULE
 static const char *mode_option __initdata = NULL;
-#endif
 
 #ifdef CONFIG_PPC
 static int default_vmode __initdata = VMODE_1024_768_60;
@@ -528,7 +528,7 @@
 	}
 
     if (reset)	/* reset engine?? */
-	printk(KERN_DEBUG "aty128fb: PLL write timeout!");
+	printk(KERN_DEBUG "aty128fb: PLL write timeout!\n");
 }
 
 
@@ -1605,7 +1605,6 @@
 }
 
 
-#ifndef MODULE
 int __init
 aty128fb_setup(char *options)
 {
@@ -1663,7 +1662,6 @@
     }
     return 0;
 }
-#endif /* !MODULE */
 
 
     /*
@@ -1710,10 +1708,7 @@
     info->fb_info.blank = &aty128fbcon_blank;
     info->fb_info.flags = FBINFO_FLAG_DEFAULT;
 
-#ifdef MODULE
     var = default_var;
-#else
-    memset(&var, 0, sizeof(var));
 #ifdef CONFIG_PPC
     if (_machine == _MACH_Pmac) {
         if (mode_option) {
@@ -1736,7 +1731,6 @@
                           &defaultmode, 8) == 0)
             var = default_var;
     }
-#endif /* MODULE */
 
     if (noaccel)
         var.accel_flags &= ~FB_ACCELF_TEXT;
@@ -2598,10 +2592,39 @@
 #ifdef MODULE
 MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>");
 MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)");
+MODULE_PARM(font, "s");
+MODULE_PARM_DESC(font, "Specify one of the compiled-in fonts (default=none)");
+MODULE_PARM(mode, "s");
+MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#ifdef CONFIG_MTRR
+MODULE_PARM(nomtrr, "i");
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
+#endif
 
 int __init
 init_module(void)
 {
+    if (noaccel) {
+        noaccel = 1;
+        printk(KERN_INFO "aty128fb: Parameter NOACCEL set\n");
+    }
+    if (font) {
+        strncpy(fontname, font, sizeof(fontname)-1);
+        printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n", font);
+    }
+    if (mode) {
+        mode_option = mode;
+        printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n", mode);
+    }
+#ifdef CONFIG_MTRR
+    if (nomtrr) {
+        mtrr = 0;
+        printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n");
+    }
+#endif
+    
     aty128fb_init();
     return 0;
 }
diff -urN linux-2.4.6-pre8/fs/Config.in linux/fs/Config.in
--- linux-2.4.6-pre8/fs/Config.in	Mon Dec  3 22:50:28 2001
+++ linux/fs/Config.in	Mon Dec  3 22:50:38 2001
@@ -27,8 +27,8 @@
 dep_tristate '  VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
 dep_tristate 'EFS file system support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS $CONFIG_EXPERIMENTAL
 dep_tristate 'Journalling Flash File System (JFFS) support (EXPERIMENTAL)' CONFIG_JFFS_FS $CONFIG_EXPERIMENTAL $CONFIG_MTD
-if [ "$CONFIG_JFFS_FS" != "n" ] ; then
-	int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0
+if [ "$CONFIG_JFFS_FS" = "y" -o "$CONFIG_JFFS_FS" = "m" ] ; then
+   int 'JFFS debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_JFFS_FS_VERBOSE 0
 fi
 tristate 'Compressed ROM file system support' CONFIG_CRAMFS
 bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
@@ -64,8 +64,7 @@
 
 tristate 'Second extended fs support' CONFIG_EXT2_FS
 
-tristate 'System V and Coherent file system support (read only)' CONFIG_SYSV_FS
-dep_mbool '  SYSV file system write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE $CONFIG_SYSV_FS $CONFIG_EXPERIMENTAL
+tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
 
 tristate 'UDF file system support (read only)' CONFIG_UDF_FS
 dep_mbool '  UDF write support (DANGEROUS)' CONFIG_UDF_RW $CONFIG_UDF_FS $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.6-pre8/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.6-pre8/fs/binfmt_elf.c	Sat May 19 18:09:15 2001
+++ linux/fs/binfmt_elf.c	Mon Dec  3 22:50:38 2001
@@ -396,7 +396,7 @@
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
 	struct file *interpreter = NULL; /* to shut gcc up */
- 	unsigned long load_addr = 0, load_bias;
+ 	unsigned long load_addr = 0, load_bias = 0;
 	int load_addr_set = 0;
 	char * elf_interpreter = NULL;
 	unsigned int interpreter_type = INTERPRETER_NONE;
@@ -595,12 +595,6 @@
 	setup_arg_pages(bprm); /* XXX: check error */
 	current->mm->start_stack = bprm->p;
 
-	/* Try and get dynamic programs out of the way of the default mmap
-	   base, as well as whatever program they might try to exec.  This
-	   is because the brk will follow the loader, and is not movable.  */
-
-	load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0);
-
 	/* Now we do a little grungy work by mmaping the ELF image into
 	   the correct location in memory.  At this point, we assume that
 	   the image should be loaded at fixed address, not at a variable
@@ -624,6 +618,11 @@
 		vaddr = elf_ppnt->p_vaddr;
 		if (elf_ex.e_type == ET_EXEC || load_addr_set) {
 			elf_flags |= MAP_FIXED;
+		} else if (elf_ex.e_type == ET_DYN) {
+			/* Try and get dynamic programs out of the way of the default mmap
+			   base, as well as whatever program they might try to exec.  This
+		           is because the brk will follow the loader, and is not movable.  */
+			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 		}
 
 		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
diff -urN linux-2.4.6-pre8/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.6-pre8/fs/buffer.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/buffer.c	Mon Dec  3 22:50:38 2001
@@ -168,14 +168,25 @@
 	unlock_buffer(bh);
 }
 
-/* The buffers have been marked clean and locked. Just submit the dang things.. */
+/*
+ * The buffers have been marked clean and locked.  Just submit the dang
+ * things.. 
+ *
+ * We'll wait for the first one of them - "sync" is not exactly
+ * performance-critical, and this makes us not hog the IO subsystem
+ * completely, while still allowing for a fair amount of concurrent IO. 
+ */
 static void write_locked_buffers(struct buffer_head **array, unsigned int count)
 {
+	struct buffer_head *wait = *array;
+	atomic_inc(&wait->b_count);
 	do {
 		struct buffer_head * bh = *array++;
 		bh->b_end_io = end_buffer_write;
 		submit_bh(WRITE, bh);
 	} while (--count);
+	wait_on_buffer(wait);
+	atomic_dec(&wait->b_count);
 }
 
 #define NRSYNC (32)
diff -urN linux-2.4.6-pre8/fs/nfsd/export.c linux/fs/nfsd/export.c
--- linux-2.4.6-pre8/fs/nfsd/export.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/nfsd/export.c	Mon Dec  3 22:50:39 2001
@@ -428,7 +428,7 @@
 	 * fh must be initialized before calling fh_compose
 	 */
 	fh_init(&fh, maxsize);
-	if (fh_compose(&fh, exp, dget(nd.dentry)))
+	if (fh_compose(&fh, exp, dget(nd.dentry), NULL))
 		err = -EINVAL;
 	else
 		err = 0;
diff -urN linux-2.4.6-pre8/fs/nfsd/nfs3proc.c linux/fs/nfsd/nfs3proc.c
--- linux-2.4.6-pre8/fs/nfsd/nfs3proc.c	Wed Apr 25 14:58:17 2001
+++ linux/fs/nfsd/nfs3proc.c	Mon Dec  3 22:50:39 2001
@@ -91,7 +91,8 @@
 				SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
-	nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
+	nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
+			      argp->check_guard, argp->guardtime);
 	RETURN_STATUS(nfserr);
 }
 
diff -urN linux-2.4.6-pre8/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
--- linux-2.4.6-pre8/fs/nfsd/nfs3xdr.c	Sat May 19 18:02:45 2001
+++ linux/fs/nfsd/nfs3xdr.c	Mon Dec  3 22:50:39 2001
@@ -716,7 +716,7 @@
 			dchild = lookup_one_len(name, dparent,namlen);
 		if (IS_ERR(dchild))
 			goto noexec;
-		if (fh_compose(&fh, exp, dchild) != 0 || !dchild->d_inode)
+		if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode)
 			goto noexec;
 		p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry);
 		*p++ = xdr_one; /* yes, a file handle follows */
diff -urN linux-2.4.6-pre8/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- linux-2.4.6-pre8/fs/nfsd/nfsfh.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/nfsd/nfsfh.c	Mon Dec  3 22:50:39 2001
@@ -743,9 +743,31 @@
 	return 2;
 }
 
+/*
+ * for composing old style file handles
+ */
+inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp,
+			   struct knfsd_fh *fh)
+{
+	fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
+	fh->ofh_generation = dentry->d_inode->i_generation;
+	if (S_ISDIR(dentry->d_inode->i_mode) ||
+	    (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
+		fh->ofh_dirino = 0;
+}
+
 int
-fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
+fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
 {
+	/* ref_fh is a reference file handle.
+	 * if it is non-null, then we should compose a filehandle which is
+	 * of the same version, where possible.
+	 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
+	 * Then create a 32byte filehandle using nfs_fhbase_old
+	 * But only do this if dentry_to_fh is not available
+	 *
+	 */
+	
 	struct inode * inode = dentry->d_inode;
 	struct dentry *parent = dentry->d_parent;
 	__u32 *datap;
@@ -766,20 +788,32 @@
 	fhp->fh_dentry = dentry; /* our internal copy */
 	fhp->fh_export = exp;
 
-	fhp->fh_handle.fh_version = 1;
-	fhp->fh_handle.fh_auth_type = 0;
-	fhp->fh_handle.fh_fsid_type = 0;
-	datap = fhp->fh_handle.fh_auth+0;
-	/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
-	*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
-	*datap++ = ino_t_to_u32(exp->ex_ino);
-
-	if (inode)
-		fhp->fh_handle.fh_fileid_type =
-			_fh_update(dentry, exp, &datap, fhp->fh_maxsize-3);
-
-	fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
-
+	if (ref_fh &&
+	    ref_fh->fh_handle.fh_version == 0xca &&
+	    parent->d_inode->i_sb->s_op->dentry_to_fh == NULL) {
+		/* old style filehandle please */
+		memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
+		fhp->fh_handle.fh_size = NFS_FHSIZE;
+		fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
+		fhp->fh_handle.ofh_dev =  htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+		fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
+		fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_ino);
+		fhp->fh_handle.ofh_dirino = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
+		if (inode)
+			_fh_update_old(dentry, exp, &fhp->fh_handle);
+	} else {
+		fhp->fh_handle.fh_version = 1;
+		fhp->fh_handle.fh_auth_type = 0;
+		fhp->fh_handle.fh_fsid_type = 0;
+		datap = fhp->fh_handle.fh_auth+0;
+		/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
+		*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+		*datap++ = ino_t_to_u32(exp->ex_ino);
+		if (inode)
+			fhp->fh_handle.fh_fileid_type =
+				_fh_update(dentry, exp, &datap, fhp->fh_maxsize-3);
+		fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
+	}
 
 	nfsd_nr_verified++;
 	if (fhp->fh_handle.fh_fileid_type == 255)
@@ -805,11 +839,15 @@
 		goto out_negative;
 	if (fhp->fh_handle.fh_fileid_type != 0)
 		goto out_uptodate;
-	datap = fhp->fh_handle.fh_auth+
-		          fhp->fh_handle.fh_size/4 -1;
-	fhp->fh_handle.fh_fileid_type =
-		_fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size);
-	fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
+	if (fhp->fh_handle.fh_version != 1) {
+		_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
+	} else {
+		datap = fhp->fh_handle.fh_auth+
+			fhp->fh_handle.fh_size/4 -1;
+		fhp->fh_handle.fh_fileid_type =
+			_fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size);
+		fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
+	}
 out:
 	return 0;
 
diff -urN linux-2.4.6-pre8/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- linux-2.4.6-pre8/fs/nfsd/nfsproc.c	Sat May 19 18:02:45 2001
+++ linux/fs/nfsd/nfsproc.c	Mon Dec  3 22:50:39 2001
@@ -71,7 +71,7 @@
 		argp->attrs.ia_valid, (long) argp->attrs.ia_size);
 
 	fh_copy(&resp->fh, &argp->fh);
-	return nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
+	return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
 }
 
 /*
@@ -222,7 +222,7 @@
 		goto out_unlock;
 	}
 	fh_init(newfhp, NFS_FHSIZE);
-	nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild);
+	nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
 	if (!nfserr && !dchild->d_inode)
 		nfserr = nfserr_noent;
 	if (nfserr) {
@@ -331,7 +331,7 @@
 		 */
 		attr->ia_valid &= ATTR_SIZE;
 		if (attr->ia_valid)
-			nfserr = nfsd_setattr(rqstp, newfhp, attr);
+			nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0);
 	}
 
 out_unlock:
diff -urN linux-2.4.6-pre8/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- linux-2.4.6-pre8/fs/nfsd/vfs.c	Sat May 19 18:02:45 2001
+++ linux/fs/nfsd/vfs.c	Mon Dec  3 22:50:39 2001
@@ -176,7 +176,7 @@
 	 * Note: we compose the file handle now, but as the
 	 * dentry may be negative, it may need to be updated.
 	 */
-	err = fh_compose(resfh, exp, dentry);
+	err = fh_compose(resfh, exp, dentry, fhp);
 	if (!err && !dentry->d_inode)
 		err = nfserr_noent;
 out:
@@ -192,7 +192,8 @@
  * N.B. After this call fhp needs an fh_put
  */
 int
-nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
+nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+	     int check_guard, time_t guardtime)
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
@@ -310,21 +311,23 @@
 		fh_lock(fhp);
 		size_change = 1;
 	}
+	err = nfserr_notsync;
+	if (!check_guard || guardtime == inode->i_ctime) {
 #ifdef CONFIG_QUOTA
-	if (iap->ia_valid & (ATTR_UID|ATTR_GID)) 
-		err = DQUOT_TRANSFER(dentry, iap);
-	else
+		if (iap->ia_valid & (ATTR_UID|ATTR_GID)) 
+			err = DQUOT_TRANSFER(dentry, iap);
+		else
 #endif
-		err = notify_change(dentry, iap);
+			err = notify_change(dentry, iap);
+		err = nfserrno(err);
+	}
 	if (size_change) {
 		fh_unlock(fhp);
 		put_write_access(inode);
 	}
-	if (err)
-		goto out_nfserr;
-	if (EX_ISSYNC(fhp->fh_export))
-		write_inode_now(inode, 1);
-	err = 0;
+	if (!err)
+		if (EX_ISSYNC(fhp->fh_export))
+			write_inode_now(inode, 1);
 out:
 	return err;
 
@@ -849,7 +852,7 @@
 		err = PTR_ERR(dchild);
 		if (IS_ERR(dchild))
 			goto out_nfserr;
-		err = fh_compose(resfhp, fhp->fh_export, dchild);
+		err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
 		if (err)
 			goto out;
 	} else {
@@ -916,7 +919,7 @@
 	 */
 	err = 0;
 	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
-		err = nfsd_setattr(rqstp, resfhp, iap);
+		err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
 	/*
 	 * Update the file handle to get the new inode info.
 	 */
@@ -975,7 +978,7 @@
 	if (IS_ERR(dchild))
 		goto out_nfserr;
 
-	err = fh_compose(resfhp, fhp->fh_export, dchild);
+	err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
 	if (err)
 		goto out;
 
@@ -1051,7 +1054,7 @@
 	 */
  set_attr:
 	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
- 		err = nfsd_setattr(rqstp, resfhp, iap);
+ 		err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
 
  out:
 	fh_unlock(fhp);
@@ -1159,7 +1162,7 @@
 	fh_unlock(fhp);
 
 	/* Compose the fh so the dentry will be freed ... */
-	cerr = fh_compose(resfhp, fhp->fh_export, dnew);
+	cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
 	if (err==0) err = cerr;
 out:
 	return err;
diff -urN linux-2.4.6-pre8/fs/proc/generic.c linux/fs/proc/generic.c
--- linux-2.4.6-pre8/fs/proc/generic.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/proc/generic.c	Mon Dec  3 22:50:39 2001
@@ -190,7 +190,7 @@
 	return 0;
 }
 
-static unsigned long proc_alloc_map[PROC_NDYNAMIC / 8];
+static unsigned long proc_alloc_map[(PROC_NDYNAMIC + BITS_PER_LONG - 1) / BITS_PER_LONG];
 
 spinlock_t proc_alloc_map_lock = SPIN_LOCK_UNLOCKED;
 
diff -urN linux-2.4.6-pre8/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
--- linux-2.4.6-pre8/fs/reiserfs/inode.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/reiserfs/inode.c	Mon Dec  3 22:50:39 2001
@@ -1284,7 +1284,12 @@
 	                  inode->i_ino) ;
         return ;
     }
-    if (do_sync) {
+    /* memory pressure can sometimes initiate write_inode calls with sync == 1,
+    ** these cases are just when the system needs ram, not when the 
+    ** inode needs to reach disk for safety, and they can safely be
+    ** ignored because the altered inode has already been logged.
+    */
+    if (do_sync && !(current->flags & PF_MEMALLOC)) {
 	lock_kernel() ;
 	journal_begin(&th, inode->i_sb, jbegin_count) ;
 	reiserfs_update_sd (&th, inode);
diff -urN linux-2.4.6-pre8/fs/sysv/Makefile linux/fs/sysv/Makefile
--- linux-2.4.6-pre8/fs/sysv/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/fs/sysv/Makefile	Mon Dec  3 22:50:39 2001
@@ -9,7 +9,7 @@
 
 O_TARGET := sysv.o
 
-obj-y   := ialloc.o balloc.o inode.o file.o dir.o namei.o fsync.o truncate.o
+obj-y   := ialloc.o balloc.o inode.o itree.o file.o dir.o namei.o super.o
 obj-m   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.6-pre8/fs/sysv/balloc.c linux/fs/sysv/balloc.c
--- linux-2.4.6-pre8/fs/sysv/balloc.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/sysv/balloc.c	Mon Dec  3 22:50:39 2001
@@ -19,311 +19,201 @@
  *  This file contains code for allocating/freeing blocks.
  */
 
-#include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
-#include <linux/string.h>
 #include <linux/locks.h>
 
 /* We don't trust the value of
-   sb->sv_sbd2->s_tfree = *sb->sv_sb_total_free_blocks
+   sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
    but we nevertheless keep it up to date. */
 
-void sysv_free_block(struct super_block * sb, unsigned int block)
+static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
+{
+	char *bh_data = bh->b_data;
+
+	if (sb->sv_type == FSTYPE_SYSV4)
+		return (u32*)(bh_data+4);
+	else
+		return (u32*)(bh_data+2);
+}
+
+/* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
+
+void sysv_free_block(struct super_block * sb, u32 nr)
 {
 	struct buffer_head * bh;
-	char * bh_data;
+	u32 *blocks = sb->sv_bcache;
+	unsigned count;
+	unsigned block = fs32_to_cpu(sb, nr);
 
-	if (!sb) {
-		printk("sysv_free_block: trying to free block on nonexistent device\n");
-		return;
-	}
 	if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
 		printk("sysv_free_block: trying to free block not in datazone\n");
 		return;
 	}
+
 	lock_super(sb);
-	if (*sb->sv_sb_flc_count > sb->sv_flc_size) {
+	count = fs16_to_cpu(sb, *sb->sv_bcache_count);
+
+	if (count > sb->sv_flc_size) {
 		printk("sysv_free_block: flc_count > flc_size\n");
 		unlock_super(sb);
 		return;
 	}
 	/* If the free list head in super-block is full, it is copied
-	 * into this block being freed:
+	 * into this block being freed, ditto if it's completely empty
+	 * (applies only on Coherent).
 	 */
-	if (*sb->sv_sb_flc_count == sb->sv_flc_size) {
-		u16 * flc_count;
-		u32 * flc_blocks;
-
-		bh = sv_getblk(sb, sb->s_dev, block);
+	if (count == sb->sv_flc_size || count == 0) {
+		block += sb->sv_block_base;
+		bh = getblk(sb->s_dev, block, sb->s_blocksize);
 		if (!bh) {
 			printk("sysv_free_block: getblk() failed\n");
 			unlock_super(sb);
 			return;
 		}
-		bh_data = bh->b_data;
-		switch (sb->sv_type) {
-			case FSTYPE_XENIX:
-				flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			case FSTYPE_SYSV4:
-				flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			case FSTYPE_SYSV2:
-				flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			case FSTYPE_COH:
-				flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			default: panic("sysv_free_block: invalid fs type\n");
-		}
-		*flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */
-		memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));
+		memset(bh->b_data, 0, sb->s_blocksize);
+		*(u16*)bh->b_data = cpu_to_fs16(sb, count);
+		memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
 		mark_buffer_dirty(bh);
 		mark_buffer_uptodate(bh, 1);
 		brelse(bh);
-		*sb->sv_sb_flc_count = 0;
-	} else
-	/* If the free list head in super-block is empty, create a new head
-	 * in this block being freed:
-	 */
-	if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */
-		bh = sv_getblk(sb, sb->s_dev, block);
-		if (!bh) {
-			printk("sysv_free_block: getblk() failed\n");
-			unlock_super(sb);
-			return;
-		}
-		memset(bh->b_data, 0, sb->sv_block_size);
-		/* this implies ((struct ..._freelist_chunk *) bh->b_data)->flc_count = 0; */
-		mark_buffer_dirty(bh);
-		mark_buffer_uptodate(bh, 1);
-		brelse(bh);
-		/* still *sb->sv_sb_flc_count = 0 */
-	} else {
-		/* Throw away block's contents */
-		bh = sv_get_hash_table(sb, sb->s_dev, block);
-		if (bh)
-			mark_buffer_clean(bh);
-		brelse(bh);
+		count = 0;
 	}
-	if (sb->sv_convert)
-		block = to_coh_ulong(block);
-	sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block;
-	if (sb->sv_convert)
-		*sb->sv_sb_total_free_blocks =
-		  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
-	else
-		*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
-	mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */
-	if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2);
-	sb->s_dirt = 1; /* and needs time stamp */
+	sb->sv_bcache[count++] = nr;
+
+	*sb->sv_bcache_count = cpu_to_fs16(sb, count);
+	fs32_add(sb, sb->sv_free_blocks, 1);
+	dirty_sb(sb);
 	unlock_super(sb);
 }
 
-int sysv_new_block(struct super_block * sb)
+u32 sysv_new_block(struct super_block * sb)
 {
 	unsigned int block;
+	u32 nr;
 	struct buffer_head * bh;
-	char * bh_data;
+	unsigned count;
 
-	if (!sb) {
-		printk("sysv_new_block: trying to get new block from nonexistent device\n");
-		return 0;
-	}
 	lock_super(sb);
-	if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */
-		unlock_super(sb);
-		return 0;		/* no blocks available */
-	}
-	block = sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)-1];
-	if (sb->sv_convert)
-		block = from_coh_ulong(block);
-	if (block == 0) { /* Applies only to Xenix FS, SystemV FS */
-		unlock_super(sb);
-		return 0;		/* no blocks available */
-	}
-	(*sb->sv_sb_flc_count)--;
+	count = fs16_to_cpu(sb, *sb->sv_bcache_count);
+
+	if (count == 0) /* Applies only to Coherent FS */
+		goto Enospc;
+	nr = sb->sv_bcache[--count];
+	if (nr == 0)  /* Applies only to Xenix FS, SystemV FS */
+		goto Enospc;
+
+	block = fs32_to_cpu(sb, nr);
+
+	*sb->sv_bcache_count = cpu_to_fs16(sb, count);
+
 	if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
-		printk("sysv_new_block: new block %d is not in data zone\n",block);
-		unlock_super(sb);
-		return 0;
+		printk("sysv_new_block: new block %d is not in data zone\n",
+			block);
+		goto Enospc;
 	}
-	if (*sb->sv_sb_flc_count == 0) { /* the last block continues the free list */
-		u16 * flc_count;
-		u32 * flc_blocks;
 
-		if (!(bh = sv_bread(sb, sb->s_dev, block))) {
+	if (count == 0) { /* the last block continues the free list */
+		unsigned count;
+
+		block += sb->sv_block_base;
+		if (!(bh = bread(sb->s_dev, block, sb->s_blocksize))) {
 			printk("sysv_new_block: cannot read free-list block\n");
 			/* retry this same block next time */
-			(*sb->sv_sb_flc_count)++;
-			unlock_super(sb);
-			return 0;
-		}
-		bh_data = bh->b_data;
-		switch (sb->sv_type) {
-			case FSTYPE_XENIX:
-				flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			case FSTYPE_SYSV4:
-				flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			case FSTYPE_SYSV2:
-				flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			case FSTYPE_COH:
-				flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
-				flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
-				break;
-			default: panic("sysv_new_block: invalid fs type\n");
+			*sb->sv_bcache_count = cpu_to_fs16(sb, 1);
+			goto Enospc;
 		}
-		if (*flc_count > sb->sv_flc_size) {
+		count = fs16_to_cpu(sb, *(u16*)bh->b_data);
+		if (count > sb->sv_flc_size) {
 			printk("sysv_new_block: free-list block with >flc_size entries\n");
 			brelse(bh);
-			unlock_super(sb);
-			return 0;
+			goto Enospc;
 		}
-		*sb->sv_sb_flc_count = *flc_count;
-		memcpy(sb->sv_sb_flc_blocks, flc_blocks, *flc_count * sizeof(sysv_zone_t));
+		*sb->sv_bcache_count = cpu_to_fs16(sb, count);
+		memcpy(sb->sv_bcache, get_chunk(sb, bh),
+				count * sizeof(sysv_zone_t));
 		brelse(bh);
 	}
 	/* Now the free list head in the superblock is valid again. */
-	bh = sv_getblk(sb, sb->s_dev, block);
-	if (!bh) {
-		printk("sysv_new_block: getblk() failed\n");
-		unlock_super(sb);
-		return 0;
-	}
-	if (atomic_read(&bh->b_count) != 1) {
-		printk("sysv_new_block: block already in use\n");
-		unlock_super(sb);
-		return 0;
-	}
-	memset(bh->b_data, 0, sb->sv_block_size);
-	mark_buffer_dirty(bh);
-	mark_buffer_uptodate(bh, 1);
-	brelse(bh);
-	if (sb->sv_convert)
-		*sb->sv_sb_total_free_blocks =
-		  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
-	else
-		*sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
-	mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */
-	if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2);
-	sb->s_dirt = 1; /* and needs time stamp */
+	fs32_add(sb, sb->sv_free_blocks, -1);
+	dirty_sb(sb);
+	unlock_super(sb);
+	return nr;
+
+Enospc:
 	unlock_super(sb);
-	return block;
+	return 0;
 }
 
 unsigned long sysv_count_free_blocks(struct super_block * sb)
 {
-#if 1 /* test */
-	int count, old_count;
-	unsigned int block;
-	struct buffer_head * bh;
-	char * bh_data;
-	int i;
+	int sb_count;
+	int count;
+	struct buffer_head * bh = NULL;
+	u32 *blocks;
+	unsigned block;
+	int n;
+
+	lock_super(sb);
+	sb_count = fs32_to_cpu(sb, *sb->sv_free_blocks);
+
+	if (0)
+		goto trust_sb;
 
 	/* this causes a lot of disk traffic ... */
 	count = 0;
-	lock_super(sb);
-	if (*sb->sv_sb_flc_count > 0) {
-		for (i = *sb->sv_sb_flc_count ; /* i > 0 */ ; ) {
-			block = sb->sv_sb_flc_blocks[--i];
-			if (sb->sv_convert)
-				block = from_coh_ulong(block);
-			if (block == 0) /* block 0 terminates list */
-				goto done;
+	n = fs16_to_cpu(sb, *sb->sv_bcache_count);
+	blocks = sb->sv_bcache;
+	while (1) {
+		if (n > sb->sv_flc_size)
+			goto E2big;
+		block = 0;
+		while (n && (block = blocks[--n]) != 0)
 			count++;
-			if (i == 0)
-				break;
-		}
-		/* block = sb->sv_sb_flc_blocks[0], the last block continues the free list */
-		while (1) {
-			u16 * flc_count;
-			u32 * flc_blocks;
-
-			if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
-				printk("sysv_count_free_blocks: new block %d is not in data zone\n",block);
-				break;
-			}
-			if (!(bh = sv_bread(sb, sb->s_dev, block))) {
-				printk("sysv_count_free_blocks: cannot read free-list block\n");
-				break;
-			}
-			bh_data = bh->b_data;
-			switch (sb->sv_type) {
-				case FSTYPE_XENIX:
-					flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
-					flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
-					break;
-				case FSTYPE_SYSV4:
-					flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
-					flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
-					break;
-				case FSTYPE_SYSV2:
-					flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
-					flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
-					break;
-				case FSTYPE_COH:
-					flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
-					flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
-					break;
-				default: panic("sysv_count_free_blocks: invalid fs type\n");
-			}
-			if (*flc_count > sb->sv_flc_size) {
-				printk("sysv_count_free_blocks: free-list block with >flc_size entries\n");
-				brelse(bh);
-				break;
-			}
-			if (*flc_count == 0) { /* Applies only to Coherent FS */
-				brelse(bh);
-				break;
-			}
-			for (i = *flc_count ; /* i > 0 */ ; ) {
-				block = flc_blocks[--i];
-				if (sb->sv_convert)
-					block = from_coh_ulong(block);
-				if (block == 0) /* block 0 terminates list */
-					break;
-				count++;
-				if (i == 0)
-					break;
-			}
-			/* block = flc_blocks[0], the last block continues the free list */
+		if (block == 0)
+			break;
+
+		block = fs32_to_cpu(sb, block);
+		if (bh)
 			brelse(bh);
-			if (block == 0) /* Applies only to Xenix FS and SystemV FS */
-				break;
-		}
-		done: ;
-	}
-	old_count = *sb->sv_sb_total_free_blocks;
-	if (sb->sv_convert)
-		old_count = from_coh_ulong(old_count);
-	if (count != old_count) {
-		printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
-		if (!(sb->s_flags & MS_RDONLY)) {
-			*sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
-			mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */
-			sb->s_dirt = 1; /* and needs time stamp */
-		}
+
+		if (block < sb->sv_firstdatazone || block >= sb->sv_nzones)
+			goto Einval;
+		block += sb->sv_block_base;
+		bh = bread(sb->s_dev, block, sb->s_blocksize);
+		if (!bh)
+			goto Eio;
+		n = fs16_to_cpu(sb, *(u16*)bh->b_data);
+		blocks = get_chunk(sb, bh);
 	}
+	if (bh)
+		brelse(bh);
+	if (count != sb_count)
+		goto Ecount;
+done:
 	unlock_super(sb);
 	return count;
-#else
-	int count;
 
-	count = *sb->sv_sb_total_free_blocks;
-	if (sb->sv_convert)
-		count = from_coh_ulong(count);
-	return count;
-#endif
+Einval:
+	printk("sysv_count_free_blocks: new block %d is not in data zone\n",
+		block);
+	goto trust_sb;
+Eio:
+	printk("sysv_count_free_blocks: cannot read free-list block\n");
+	goto trust_sb;
+E2big:
+	printk("sysv_count_free_blocks: >flc_size entries in free-list block\n");
+	if (bh)
+		brelse(bh);
+trust_sb:
+	count = sb_count;
+	goto done;
+Ecount:
+	printk("sysv_count_free_blocks: free block count was %d, "
+		"correcting to %d\n", sb_count, count);
+	if (!(sb->s_flags & MS_RDONLY)) {
+		*sb->sv_free_blocks = cpu_to_fs32(sb, count);
+		dirty_sb(sb);
+	}
+	goto done;
 }
-
diff -urN linux-2.4.6-pre8/fs/sysv/dir.c linux/fs/sysv/dir.c
--- linux-2.4.6-pre8/fs/sysv/dir.c	Fri Aug 11 14:29:01 2000
+++ linux/fs/sysv/dir.c	Mon Dec  3 22:50:39 2001
@@ -13,63 +13,356 @@
  *  SystemV/Coherent directory handling functions
  */
 
-#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
-#include <linux/stat.h>
-#include <linux/string.h>
+#include <linux/pagemap.h>
 
 static int sysv_readdir(struct file *, void *, filldir_t);
 
 struct file_operations sysv_dir_operations = {
 	read:		generic_read_dir,
 	readdir:	sysv_readdir,
-	fsync:		file_fsync,
+	fsync:		sysv_sync_file,
 };
 
+static inline void dir_put_page(struct page *page)
+{
+	kunmap(page);
+	page_cache_release(page);
+}
+
+static inline unsigned long dir_pages(struct inode *inode)
+{
+	return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
+}
+
+static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
+{
+	struct inode *dir = (struct inode *)page->mapping->host;
+	int err = 0;
+	page->mapping->a_ops->commit_write(NULL, page, from, to);
+	if (IS_SYNC(dir))
+		err = waitfor_one_page(page);
+	return err;
+}
+
+static struct page * dir_get_page(struct inode *dir, unsigned long n)
+{
+	struct address_space *mapping = dir->i_mapping;
+	struct page *page = read_cache_page(mapping, n,
+				(filler_t*)mapping->a_ops->readpage, NULL);
+	if (!IS_ERR(page)) {
+		wait_on_page(page);
+		kmap(page);
+		if (!Page_Uptodate(page))
+			goto fail;
+	}
+	return page;
+
+fail:
+	dir_put_page(page);
+	return ERR_PTR(-EIO);
+}
+
 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
+	unsigned long pos = filp->f_pos;
 	struct inode *inode = filp->f_dentry->d_inode;
-	struct super_block * sb = inode->i_sb;
-	unsigned int offset,i;
-	struct buffer_head * bh;
-	char* bh_data;
-	struct sysv_dir_entry * de, sde;
-
-	if ((unsigned long)(filp->f_pos) % SYSV_DIRSIZE)
-		return -EBADF;
-	while (filp->f_pos < inode->i_size) {
-		offset = filp->f_pos & sb->sv_block_size_1;
-		bh = sysv_file_bread(inode, filp->f_pos >> sb->sv_block_size_bits, 0);
-		if (!bh) {
-			filp->f_pos += sb->sv_block_size - offset;
+	struct super_block *sb = inode->i_sb;
+	unsigned offset = pos & ~PAGE_CACHE_MASK;
+	unsigned long n = pos >> PAGE_CACHE_SHIFT;
+	unsigned long npages = dir_pages(inode);
+
+	pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
+	if (pos >= inode->i_size)
+		goto done;
+
+	for ( ; n < npages; n++, offset = 0) {
+		char *kaddr, *limit;
+		struct sysv_dir_entry *de;
+		struct page *page = dir_get_page(inode, n);
+
+		if (IS_ERR(page))
+			continue;
+		kaddr = (char *)page_address(page);
+		de = (struct sysv_dir_entry *)(kaddr+offset);
+		limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE;
+		for ( ;(char*)de <= limit; de++) {
+			char *name = de->name;
+			int over;
+
+			if (!de->inode)
+				continue;
+
+			offset = (char *)de - kaddr;
+
+			over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
+					(n<<PAGE_CACHE_SHIFT) | offset,
+					fs16_to_cpu(sb, de->inode), DT_UNKNOWN);
+			if (over) {
+				dir_put_page(page);
+				goto done;
+			}
+		}
+		dir_put_page(page);
+	}
+
+done:
+	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
+	UPDATE_ATIME(inode);
+	return 0;
+}
+
+/* compare strings: name[0..len-1] (not zero-terminated) and
+ * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
+ */
+static inline int namecompare(int len, int maxlen,
+	const char * name, const char * buffer)
+{
+	if (len < maxlen && buffer[len])
+		return 0;
+	return !memcmp(name, buffer, len);
+}
+
+/*
+ *	sysv_find_entry()
+ *
+ * finds an entry in the specified directory with the wanted name. It
+ * returns the cache buffer in which the entry was found, and the entry
+ * itself (as a parameter - res_dir). It does NOT read the inode of the
+ * entry - you'll have to do that yourself if you want to.
+ */
+struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page)
+{
+	const char * name = dentry->d_name.name;
+	int namelen = dentry->d_name.len;
+	struct inode * dir = dentry->d_parent->d_inode;
+	unsigned long n;
+	unsigned long npages = dir_pages(dir);
+	struct page *page = NULL;
+	struct sysv_dir_entry *de;
+
+	*res_page = NULL;
+
+	for (n = 0; n < npages; n++) {
+		char *kaddr;
+		page = dir_get_page(dir, n);
+		if (IS_ERR(page))
 			continue;
+
+		kaddr = (char*)page_address(page);
+		de = (struct sysv_dir_entry *) kaddr;
+		kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE;
+		for ( ; (char *) de <= kaddr ; de++) {
+			if (!de->inode)
+				continue;
+			if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) 
+				goto found;
+		}
+		dir_put_page(page);
+	}
+	return NULL;
+
+found:
+	*res_page = page;
+	return de;
+}
+
+int sysv_add_link(struct dentry *dentry, struct inode *inode)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+	const char * name = dentry->d_name.name;
+	int namelen = dentry->d_name.len;
+	struct page *page = NULL;
+	struct sysv_dir_entry * de;
+	unsigned long npages = dir_pages(dir);
+	unsigned long n;
+	char *kaddr;
+	unsigned from, to;
+	int err;
+
+	/* We take care of directory expansion in the same loop */
+	for (n = 0; n <= npages; n++) {
+		page = dir_get_page(dir, n);
+		err = PTR_ERR(page);
+		if (IS_ERR(page))
+			goto out;
+		kaddr = (char*)page_address(page);
+		de = (struct sysv_dir_entry *)kaddr;
+		kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE;
+		while ((char *)de <= kaddr) {
+			if (!de->inode)
+				goto got_it;
+			err = -EEXIST;
+			if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) 
+				goto out_page;
+			de++;
 		}
-		bh_data = bh->b_data;
-		while (offset < sb->sv_block_size && filp->f_pos < inode->i_size) {
-			de = (struct sysv_dir_entry *) (offset + bh_data);
-			if (de->inode) {
-				/* Copy the directory entry first, because the directory
-				 * might be modified while we sleep in filldir()...
-				 */
-				memcpy(&sde, de, sizeof(struct sysv_dir_entry));
-
-				if (sde.inode > inode->i_sb->sv_ninodes)
-					printk("sysv_readdir: Bad inode number on dev "
-					       "%s, ino %ld, offset 0x%04lx: %d is out of range\n",
-					       kdevname(inode->i_dev),
-					       inode->i_ino, (off_t) filp->f_pos, sde.inode);
-
-				i = strnlen(sde.name, SYSV_NAMELEN);
-				if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode, DT_UNKNOWN) < 0) {
-					brelse(bh);
-					return 0;
-				}
+		dir_put_page(page);
+	}
+	BUG();
+	return -EINVAL;
+
+got_it:
+	from = (char*)de - (char*)page_address(page);
+	to = from + SYSV_DIRSIZE;
+	lock_page(page);
+	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+	if (err)
+		goto out_unlock;
+	memcpy (de->name, name, namelen);
+	memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen);
+	de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino);
+	err = dir_commit_chunk(page, from, to);
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(dir);
+out_unlock:
+	UnlockPage(page);
+out_page:
+	dir_put_page(page);
+out:
+	return err;
+}
+
+int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = (struct inode*)mapping->host;
+	char *kaddr = (char*)page_address(page);
+	unsigned from = (char*)de - kaddr;
+	unsigned to = from + SYSV_DIRSIZE;
+	int err;
+
+	lock_page(page);
+	err = mapping->a_ops->prepare_write(NULL, page, from, to);
+	if (err)
+		BUG();
+	de->inode = 0;
+	err = dir_commit_chunk(page, from, to);
+	UnlockPage(page);
+	dir_put_page(page);
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	return err;
+}
+
+int sysv_make_empty(struct inode *inode, struct inode *dir)
+{
+	struct address_space *mapping = inode->i_mapping;
+	struct page *page = grab_cache_page(mapping, 0);
+	struct sysv_dir_entry * de;
+	char *base;
+	int err;
+
+	if (!page)
+		return -ENOMEM;
+	err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE);
+	if (err)
+		goto fail;
+
+	base = (char*)page_address(page);
+	memset(base, 0, PAGE_CACHE_SIZE);
+
+	de = (struct sysv_dir_entry *) base;
+	de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino);
+	strcpy(de->name,".");
+	de++;
+	de->inode = cpu_to_fs16(inode->i_sb, dir->i_ino);
+	strcpy(de->name,"..");
+
+	err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
+fail:
+	UnlockPage(page);
+	page_cache_release(page);
+	return err;
+}
+
+/*
+ * routine to check that the specified directory is empty (for rmdir)
+ */
+int sysv_empty_dir(struct inode * inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct page *page = NULL;
+	unsigned long i, npages = dir_pages(inode);
+
+	for (i = 0; i < npages; i++) {
+		char *kaddr;
+		struct sysv_dir_entry * de;
+		page = dir_get_page(inode, i);
+
+		if (IS_ERR(page))
+			continue;
+
+		kaddr = (char *)page_address(page);
+		de = (struct sysv_dir_entry *)kaddr;
+		kaddr += PAGE_CACHE_SIZE-SYSV_DIRSIZE;
+
+		for ( ;(char *)de <= kaddr; de++) {
+			if (!de->inode)
+				continue;
+			/* check for . and .. */
+			if (de->name[0] != '.')
+				goto not_empty;
+			if (!de->name[1]) {
+				if (de->inode == cpu_to_fs16(sb, inode->i_ino))
+					continue;
+				goto not_empty;
 			}
-			offset += SYSV_DIRSIZE;
-			filp->f_pos += SYSV_DIRSIZE;
+			if (de->name[1] != '.' || de->name[2])
+				goto not_empty;
 		}
-		brelse(bh);
+		dir_put_page(page);
 	}
+	return 1;
+
+not_empty:
+	dir_put_page(page);
 	return 0;
+}
+
+/* Releases the page */
+void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
+	struct inode *inode)
+{
+	struct inode *dir = (struct inode*)page->mapping->host;
+	unsigned from = (char *)de-(char*)page_address(page);
+	unsigned to = from + SYSV_DIRSIZE;
+	int err;
+
+	lock_page(page);
+	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+	if (err)
+		BUG();
+	de->inode = cpu_to_fs16(inode->i_sb, inode->i_ino);
+	err = dir_commit_chunk(page, from, to);
+	UnlockPage(page);
+	dir_put_page(page);
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(dir);
+}
+
+struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p)
+{
+	struct page *page = dir_get_page(dir, 0);
+	struct sysv_dir_entry *de = NULL;
+
+	if (!IS_ERR(page)) {
+		de = (struct sysv_dir_entry*) page_address(page) + 1;
+		*p = page;
+	}
+	return de;
+}
+
+ino_t sysv_inode_by_name(struct dentry *dentry)
+{
+	struct page *page;
+	struct sysv_dir_entry *de = sysv_find_entry (dentry, &page);
+	ino_t res = 0;
+	
+	if (de) {
+		res = fs16_to_cpu(dentry->d_sb, de->inode);
+		dir_put_page(page);
+	}
+	return res;
 }
diff -urN linux-2.4.6-pre8/fs/sysv/file.c linux/fs/sysv/file.c
--- linux-2.4.6-pre8/fs/sysv/file.c	Sat Feb 26 20:33:43 2000
+++ linux/fs/sysv/file.c	Mon Dec  3 22:50:39 2001
@@ -31,3 +31,17 @@
 	truncate:	sysv_truncate,
 	setattr:	sysv_notify_change,
 };
+
+int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync)
+{
+	struct inode *inode = dentry->d_inode;
+	int err  = fsync_inode_buffers(inode);
+
+	if (!(inode->i_state & I_DIRTY))
+		return err;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		return err;
+	
+	err |= sysv_sync_inode(inode);
+	return err ? -EIO : 0;
+}
diff -urN linux-2.4.6-pre8/fs/sysv/fsync.c linux/fs/sysv/fsync.c
--- linux-2.4.6-pre8/fs/sysv/fsync.c	Thu Jun 29 16:06:54 2000
+++ linux/fs/sysv/fsync.c	Wed Dec 31 16:00:00 1969
@@ -1,200 +0,0 @@
-/*
- *  linux/fs/sysv/fsync.c
- *
- *  minix/fsync.c
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 1993  Stephen Tweedie (sct@dcs.ed.ac.uk)
- *
- *  coh/fsync.c
- *  Copyright (C) 1993  Pascal Haible, Bruno Haible
- *
- *  sysv/fsync.c
- *  Copyright (C) 1993  Bruno Haible
- *
- *  SystemV/Coherent fsync primitive
- */
-
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/fs.h>
-#include <linux/sysv_fs.h>
-#include <linux/smp_lock.h>
-
-
-/* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */
-
-/* Sync one block. The block number is
- * from_coh_ulong(*blockp) if convert=1, *blockp if convert=0.
- */
-static int sync_block (struct inode * inode, u32 *blockp, int convert, int wait)
-{
-	struct buffer_head * bh;
-	u32 tmp, block;
-	struct super_block * sb;
-
-	block = tmp = *blockp;
-	if (convert)
-		block = from_coh_ulong(block);
-	if (!block)
-		return 0;
-	sb = inode->i_sb;
-	bh = sv_get_hash_table(sb, inode->i_dev, block);
-	if (!bh)
-		return 0;
-	if (*blockp != tmp) {
-		brelse (bh);
-		return 1;
-	}
-	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
-		brelse(bh);
-		return -1;
-	}
-	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
-		brelse(bh);
-		return 0;
-	}
-	ll_rw_block(WRITE, 1, &bh);
-	atomic_dec(&bh->b_count);
-	return 0;
-}
-
-/* Sync one block full of indirect pointers and read it because we'll need it. */
-static int sync_iblock (struct inode * inode, u32 * iblockp, int convert,
-			struct buffer_head * *bh, int wait)
-{
-	int rc;
-	u32 tmp, block;
-
-	*bh = NULL;
-	block = tmp = *iblockp;
-	if (convert)
-		block = from_coh_ulong(block);
-	if (!block)
-		return 0;
-	rc = sync_block (inode, iblockp, convert, wait);
-	if (rc)
-		return rc;
-	*bh = sv_bread(inode->i_sb, inode->i_dev, block);
-	if (tmp != *iblockp) {
-		brelse(*bh);
-		*bh = NULL;
-		return 1;
-	}
-	if (!*bh)
-		return -1;
-	return 0;
-}
-
-
-static int sync_direct(struct inode *inode, int wait)
-{
-	int i;
-	int rc, err = 0;
-
-	for (i = 0; i < 10; i++) {
-		rc = sync_block (inode, inode->u.sysv_i.i_data + i, 0, wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	return err;
-}
-
-static int sync_indirect(struct inode *inode, u32 *iblockp, int convert, int wait)
-{
-	int i;
-	struct buffer_head * ind_bh;
-	int rc, err = 0;
-	struct super_block * sb;
-
-	rc = sync_iblock (inode, iblockp, convert, &ind_bh, wait);
-	if (rc || !ind_bh)
-		return rc;
-
-	sb = inode->i_sb;
-	for (i = 0; i < sb->sv_ind_per_block; i++) {
-		rc = sync_block (inode,
-				 ((u32 *) ind_bh->b_data) + i, sb->sv_convert,
-				 wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(ind_bh);
-	return err;
-}
-
-static int sync_dindirect(struct inode *inode, u32 *diblockp, int convert,
-			  int wait)
-{
-	int i;
-	struct buffer_head * dind_bh;
-	int rc, err = 0;
-	struct super_block * sb;
-
-	rc = sync_iblock (inode, diblockp, convert, &dind_bh, wait);
-	if (rc || !dind_bh)
-		return rc;
-
-	sb = inode->i_sb;
-	for (i = 0; i < sb->sv_ind_per_block; i++) {
-		rc = sync_indirect (inode,
-				    ((u32 *) dind_bh->b_data) + i, sb->sv_convert,
-				    wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(dind_bh);
-	return err;
-}
-
-static int sync_tindirect(struct inode *inode, u32 *tiblockp, int convert,
-			  int wait)
-{
-	int i;
-	struct buffer_head * tind_bh;
-	int rc, err = 0;
-	struct super_block * sb;
-
-	rc = sync_iblock (inode, tiblockp, convert, &tind_bh, wait);
-	if (rc || !tind_bh)
-		return rc;
-
-	sb = inode->i_sb;
-	for (i = 0; i < sb->sv_ind_per_block; i++) {
-		rc = sync_dindirect (inode,
-				     ((u32 *) tind_bh->b_data) + i, sb->sv_convert,
-				     wait);
-		if (rc > 0)
-			break;
-		if (rc)
-			err = rc;
-	}
-	brelse(tind_bh);
-	return err;
-}
-
-int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync)
-{
-	int wait, err = 0;
-	struct inode *inode = dentry->d_inode;
-
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	     S_ISLNK(inode->i_mode)))
-		return -EINVAL;
-
-	lock_kernel();
-	for (wait=0; wait<=1; wait++) {
-		err |= sync_direct(inode, wait);
-		err |= sync_indirect(inode, inode->u.sysv_i.i_data+10, 0, wait);
-		err |= sync_dindirect(inode, inode->u.sysv_i.i_data+11, 0, wait);
-		err |= sync_tindirect(inode, inode->u.sysv_i.i_data+12, 0, wait);
-	}
-	err |= sysv_sync_inode (inode);
-	unlock_kernel();
-	return (err < 0) ? -EIO : 0;
-}
diff -urN linux-2.4.6-pre8/fs/sysv/ialloc.c linux/fs/sysv/ialloc.c
--- linux-2.4.6-pre8/fs/sysv/ialloc.c	Fri Nov 17 11:35:27 2000
+++ linux/fs/sysv/ialloc.c	Mon Dec  3 22:50:39 2001
@@ -19,7 +19,6 @@
  *  This file contains code for allocating/freeing inodes.
  */
 
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
@@ -35,7 +34,8 @@
 /* An inode on disk is considered free if both i_mode == 0 and i_nlink == 0. */
 
 /* return &sb->sv_sb_fic_inodes[i] = &sbd->s_inode[i]; */
-static inline sysv_ino_t * sv_sb_fic_inode (struct super_block * sb, unsigned int i)
+static inline sysv_ino_t *
+sv_sb_fic_inode(struct super_block * sb, unsigned int i)
 {
 	if (sb->sv_bh1 == sb->sv_bh2)
 		return &sb->sv_sb_fic_inodes[i];
@@ -49,12 +49,55 @@
 	}
 }
 
+struct sysv_inode *
+sysv_raw_inode(struct super_block *sb, unsigned ino, struct buffer_head **bh)
+{
+	struct sysv_inode *res;
+	int block = sb->sv_firstinodezone + sb->sv_block_base;
+	block += (ino-1) >> sb->sv_inodes_per_block_bits;
+	*bh = bread(sb->s_dev, block, sb->s_blocksize);
+	if (!*bh)
+		return NULL;
+	res = (struct sysv_inode *) (*bh)->b_data;
+	return res + ((ino-1) & sb->sv_inodes_per_block_1);
+}
+
+static int refill_free_cache(struct super_block *sb)
+{
+	struct buffer_head * bh;
+	struct sysv_inode * raw_inode;
+	int i = 0, ino;
+
+	ino = SYSV_ROOT_INO+1;
+	raw_inode = sysv_raw_inode(sb, ino, &bh);
+	if (!raw_inode)
+		goto out;
+	while (ino <= sb->sv_ninodes) {
+		if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0) {
+			*sv_sb_fic_inode(sb,i++) = cpu_to_fs16(sb, ino);
+			if (i == sb->sv_fic_size)
+				break;
+		}
+		if ((ino++ & sb->sv_inodes_per_block_1) == 0) {
+			brelse(bh);
+			raw_inode = sysv_raw_inode(sb, ino, &bh);
+			if (!raw_inode)
+				goto out;
+		} else
+			raw_inode++;
+	}
+	brelse(bh);
+out:
+	return i;
+}
+
 void sysv_free_inode(struct inode * inode)
 {
 	struct super_block * sb;
 	unsigned int ino;
 	struct buffer_head * bh;
 	struct sysv_inode * raw_inode;
+	unsigned count;
 
 	sb = inode->i_sb;
 	ino = inode->i_ino;
@@ -62,137 +105,119 @@
 		printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n");
 		return;
 	}
-	if (!(bh = sv_bread(sb, inode->i_dev, sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits)))) {
+	raw_inode = sysv_raw_inode(sb, ino, &bh);
+	clear_inode(inode);
+	if (!raw_inode) {
 		printk("sysv_free_inode: unable to read inode block on device "
-		       "%s\n", kdevname(inode->i_dev));
-		clear_inode(inode);
+		       "%s\n", bdevname(inode->i_dev));
 		return;
 	}
-	raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
-	clear_inode(inode);
 	lock_super(sb);
-	if (*sb->sv_sb_fic_count < sb->sv_fic_size)
-		*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)++) = ino;
-	(*sb->sv_sb_total_free_inodes)++;
-	mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */
-	if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2);
-	sb->s_dirt = 1; /* and needs time stamp */
+	count = fs16_to_cpu(sb, *sb->sv_sb_fic_count);
+	if (count < sb->sv_fic_size) {
+		*sv_sb_fic_inode(sb,count++) = cpu_to_fs16(sb, ino);
+		*sb->sv_sb_fic_count = cpu_to_fs16(sb, count);
+	}
+	fs16_add(sb, sb->sv_sb_total_free_inodes, 1);
+	dirty_sb(sb);
 	memset(raw_inode, 0, sizeof(struct sysv_inode));
 	mark_buffer_dirty(bh);
 	unlock_super(sb);
 	brelse(bh);
 }
 
-struct inode * sysv_new_inode(const struct inode * dir)
+struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
 {
 	struct inode * inode;
 	struct super_block * sb;
-	struct buffer_head * bh;
-	struct sysv_inode * raw_inode;
-	int i,j,ino,block;
+	u16 ino;
+	unsigned count;
 
-	if (!dir)
-		return NULL;
 	sb = dir->i_sb;
 	inode = new_inode(sb);
 	if (!inode)
 		return NULL;
-	lock_super(sb);		/* protect against task switches */
-	if ((*sb->sv_sb_fic_count == 0)
-	    || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */
-	   ) {
-		/* Rebuild cache of free inodes: */
-		/* i : index into cache slot being filled	     */
-		/* ino : inode we are trying			     */
-		/* block : firstinodezone + (ino-1)/inodes_per_block */
-		/* j : (ino-1)%inodes_per_block			     */
-		/* bh : buffer for block			     */
-		/* raw_inode : pointer to inode ino in the block     */
-		for (i = 0, ino = SYSV_ROOT_INO+1, block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; i < sb->sv_fic_size && block < sb->sv_firstdatazone ; block++, j = 0) {
-			if (!(bh = sv_bread(sb, sb->s_dev, block))) {
-				printk("sysv_new_inode: unable to read inode table\n");
-				break;	/* go with what we've got */
-				/* FIXME: Perhaps try the next block? */
-			}
-			raw_inode = (struct sysv_inode *) bh->b_data + j;
-			for (; j < sb->sv_inodes_per_block && i < sb->sv_fic_size; ino++, j++, raw_inode++) {
-				if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
-					*sv_sb_fic_inode(sb,i++) = ino;
-			}
-			brelse(bh);
-		}
-		if (i == 0) {
+	lock_super(sb);
+	count = fs16_to_cpu(sb, *sb->sv_sb_fic_count);
+	if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
+		count = refill_free_cache(sb);
+		if (count == 0) {
 			iput(inode);
 			unlock_super(sb);
-			return NULL;	/* no inodes available */
+			return NULL;
 		}
-		*sb->sv_sb_fic_count = i;
 	}
-	/* Now *sb->sv_sb_fic_count > 0. */
-	ino = *sv_sb_fic_inode(sb,--(*sb->sv_sb_fic_count));
-	mark_buffer_dirty(sb->sv_bh1); /* super-block has been modified */
-	if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2);
-	sb->s_dirt = 1; /* and needs time stamp */
+	/* Now count > 0. */
+	ino = *sv_sb_fic_inode(sb,--count);
+	*sb->sv_sb_fic_count = cpu_to_fs16(sb, count);
+	fs16_add(sb, sb->sv_sb_total_free_inodes, -1);
+	dirty_sb(sb);
 	inode->i_uid = current->fsuid;
 	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
-	inode->i_ino = ino;
+	inode->i_ino = fs16_to_cpu(sb, ino);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_blocks = inode->i_blksize = 0;
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
-	/* Change directory entry: */
-	inode->i_mode = 0;		/* for sysv_write_inode() */
+	inode->i_mode = mode;		/* for sysv_write_inode() */
 	sysv_write_inode(inode, 0);	/* ensure inode not allocated again */
 					/* FIXME: caller may call this too. */
 	mark_inode_dirty(inode);	/* cleared by sysv_write_inode() */
 	/* That's it. */
-	(*sb->sv_sb_total_free_inodes)--;
-	mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified again */
-	sb->s_dirt = 1; /* and needs time stamp again */
 	unlock_super(sb);
 	return inode;
 }
 
 unsigned long sysv_count_free_inodes(struct super_block * sb)
 {
-#if 1 /* test */
 	struct buffer_head * bh;
 	struct sysv_inode * raw_inode;
-	int j,block,count;
+	int ino, count, sb_count;
+
+	lock_super(sb);
+
+	sb_count = fs16_to_cpu(sb, *sb->sv_sb_total_free_inodes);
+
+	if (0)
+		goto trust_sb;
 
 	/* this causes a lot of disk traffic ... */
 	count = 0;
-	lock_super(sb);
-	/* i : index into cache slot being filled	     */
-	/* ino : inode we are trying			     */
-	/* block : firstinodezone + (ino-1)/inodes_per_block */
-	/* j : (ino-1)%inodes_per_block			     */
-	/* bh : buffer for block			     */
-	/* raw_inode : pointer to inode ino in the block     */
-	for (block = sb->sv_firstinodezone, j = SYSV_ROOT_INO ; block < sb->sv_firstdatazone ; block++, j = 0) {
-		if (!(bh = sv_bread(sb, sb->s_dev, block))) {
-			printk("sysv_count_free_inodes: unable to read inode table\n");
-			break;	/* go with what we've got */
-			/* FIXME: Perhaps try the next block? */
-		}
-		raw_inode = (struct sysv_inode *) bh->b_data + j;
-		for (; j < sb->sv_inodes_per_block ; j++, raw_inode++)
-			if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
-				count++;
-		brelse(bh);
-	}
-	if (count != *sb->sv_sb_total_free_inodes) {
-		printk("sysv_count_free_inodes: free inode count was %d, correcting to %d\n",(short)(*sb->sv_sb_total_free_inodes),count);
-		if (!(sb->s_flags & MS_RDONLY)) {
-			*sb->sv_sb_total_free_inodes = count;
-			mark_buffer_dirty(sb->sv_bh2); /* super-block has been modified */
-			sb->s_dirt = 1; /* and needs time stamp */
-		}
+	ino = SYSV_ROOT_INO+1;
+	raw_inode = sysv_raw_inode(sb, ino, &bh);
+	if (!raw_inode)
+		goto Eio;
+	while (ino <= sb->sv_ninodes) {
+		if (raw_inode->i_mode == 0 && raw_inode->i_nlink == 0)
+			count++;
+		if ((ino++ & sb->sv_inodes_per_block_1) == 0) {
+			brelse(bh);
+			raw_inode = sysv_raw_inode(sb, ino, &bh);
+			if (!raw_inode)
+				goto Eio;
+		} else
+			raw_inode++;
 	}
+	brelse(bh);
+	if (count != sb_count)
+		goto Einval;
+out:
 	unlock_super(sb);
 	return count;
-#else
-	return *sb->sv_sb_total_free_inodes;
-#endif
-}
 
+Einval:
+	printk("sysv_count_free_inodes: "
+		"free inode count was %d, correcting to %d\n",
+		sb_count, count);
+	if (!(sb->s_flags & MS_RDONLY)) {
+		*sb->sv_sb_total_free_inodes = cpu_to_fs16(sb, count);
+		dirty_sb(sb);
+	}
+	goto out;
+
+Eio:
+	printk("sysv_count_free_inodes: unable to read inode table\n");
+trust_sb:
+	count = sb_count;
+	goto out;
+}
diff -urN linux-2.4.6-pre8/fs/sysv/inode.c linux/fs/sysv/inode.c
--- linux-2.4.6-pre8/fs/sysv/inode.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/sysv/inode.c	Mon Dec  3 22:50:39 2001
@@ -21,499 +21,13 @@
  *  the superblock.
  */
 
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
-#include <linux/stat.h>
-#include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#if 0
-void sysv_print_inode(struct inode * inode)
-{
-        printk("ino %lu  mode 0%6.6o  lk %d  uid %d  gid %d"
-               "  sz %lu  blks %lu  cnt %u\n",
-               inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid,
-               inode->i_gid, inode->i_size, inode->i_blocks,
-               atomic_read(&inode->i_count));
-        printk("  db <0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx"
-               " 0x%lx 0x%lx>\n",
-                inode->u.sysv_i.i_data[0], inode->u.sysv_i.i_data[1],
-                inode->u.sysv_i.i_data[2], inode->u.sysv_i.i_data[3],
-                inode->u.sysv_i.i_data[4], inode->u.sysv_i.i_data[5],
-                inode->u.sysv_i.i_data[6], inode->u.sysv_i.i_data[7],
-                inode->u.sysv_i.i_data[8], inode->u.sysv_i.i_data[9]);
-        printk("  ib <0x%lx 0x%lx 0x%lx>\n",
-                inode->u.sysv_i.i_data[10],
-                inode->u.sysv_i.i_data[11],
-                inode->u.sysv_i.i_data[12]);
-}
-#endif
-
-static void sysv_delete_inode(struct inode *inode)
-{
-	lock_kernel();
-	inode->i_size = 0;
-	sysv_truncate(inode);
-	sysv_free_inode(inode);
-	unlock_kernel();
-}
-
-static void sysv_put_super(struct super_block *);
-static void sysv_write_super(struct super_block *);
-static void sysv_read_inode(struct inode *);
-static int sysv_statfs(struct super_block *, struct statfs *);
-
-static struct super_operations sysv_sops = {
-	read_inode:	sysv_read_inode,
-	write_inode:	sysv_write_inode,
-	delete_inode:	sysv_delete_inode,
-	put_super:	sysv_put_super,
-	write_super:	sysv_write_super,
-	statfs:		sysv_statfs,
-};
-
-/* The following functions try to recognize specific filesystems.
- * We recognize:
- * - Xenix FS by its magic number.
- * - SystemV FS by its magic number.
- * - Coherent FS by its funny fname/fpack field.
- * We discriminate among SystemV4 and SystemV2 FS by the assumption that
- * the time stamp is not < 01-01-1980.
- */
-
-static void detected_bs (u_char type, struct super_block *sb)
-{
-	u_char n_bits = type+8;
-	int bsize = 1 << n_bits;
-	int bsize_4 = bsize >> 2;
-	
-	sb->sv_block_size = bsize;
-	sb->sv_block_size_1 = bsize-1;
-	sb->sv_block_size_bits = n_bits;
-	sb->sv_block_size_dec_bits = (bsize==512) ? 1 : 0;
-	sb->sv_block_size_inc_bits = (bsize==2048) ? 1 : 0;
-	sb->sv_inodes_per_block = bsize >> 6;
-	sb->sv_inodes_per_block_1 = (bsize >> 6)-1;
-	sb->sv_inodes_per_block_bits = n_bits-6;
-	sb->sv_toobig_block = 10 +
-	  (sb->sv_ind_per_block = bsize_4) +
-	  (sb->sv_ind_per_block_2 = bsize_4*bsize_4) +
-	  (sb->sv_ind_per_block_3 = bsize_4*bsize_4*bsize_4);
-	sb->sv_ind_per_block_1 = bsize_4-1;
-	sb->sv_ind_per_block_2_1 = bsize_4*bsize_4-1;
-	sb->sv_ind_per_block_2_bits = 2 *
-	  (sb->sv_ind_per_block_bits = n_bits-2);
-	sb->sv_ind_per_block_block_size_1 = bsize_4*bsize-1;
-	sb->sv_ind_per_block_block_size_bits = 2*n_bits-2;
-	sb->sv_ind_per_block_2_block_size_1 = bsize_4*bsize_4*bsize-1;
-	sb->sv_ind_per_block_2_block_size_bits = 3*n_bits-4;
-	sb->sv_ind0_size = 10 * bsize;
-	sb->sv_ind1_size = (10 + bsize_4)* bsize;
-	sb->sv_ind2_size = (10 + bsize_4 + bsize_4*bsize_4) * bsize;
-}
-
-static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh)
-{
-	struct xenix_super_block * sbd;
-
-	sbd = (struct xenix_super_block *) bh->b_data;
-	if (sbd->s_magic != 0x2b5544)
-		return NULL;
-	if (sbd->s_type > 2 || sbd->s_type < 1)
-		return NULL;
-	detected_bs(sbd->s_type, sb);
-	sb->sv_type = FSTYPE_XENIX;
-	return "Xenix";
-}
-static struct super_block * detected_xenix (struct super_block *sb, struct buffer_head *bh1, struct buffer_head *bh2)
-{
-	struct xenix_super_block * sbd1;
-	struct xenix_super_block * sbd2;
-
-	if (sb->sv_block_size >= BLOCK_SIZE)
-		/* block size >= 1024, so bh1 = bh2 */
-		sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data;
-	else {
-		/* block size = 512, so bh1 != bh2 */
-		sbd1 = (struct xenix_super_block *) bh1->b_data;
-		sbd2 = (struct xenix_super_block *) (bh2->b_data - BLOCK_SIZE/2);
-		/* sanity check */
-		if (sbd2->s_magic != 0x2b5544)
-			return NULL;
-	}
-
-	sb->sv_convert = 0;
-	sb->sv_kludge_symlinks = 1;
-	sb->sv_truncate = 1;
-	sb->sv_link_max = XENIX_LINK_MAX;
-	sb->sv_fic_size = XENIX_NICINOD;
-	sb->sv_flc_size = XENIX_NICFREE;
-	sb->sv_bh1 = bh1;
-	sb->sv_bh2 = bh2;
-	sb->sv_sbd1 = (char *) sbd1;
-	sb->sv_sbd2 = (char *) sbd2;
-	sb->sv_sb_fic_count = &sbd1->s_ninode;
-	sb->sv_sb_fic_inodes = &sbd1->s_inode[0];
-	sb->sv_sb_total_free_inodes = &sbd2->s_tinode;
-	sb->sv_sb_flc_count = &sbd1->s_nfree;
-	sb->sv_sb_flc_blocks = &sbd1->s_free[0];
-	sb->sv_sb_total_free_blocks = &sbd2->s_tfree;
-	sb->sv_sb_time = &sbd2->s_time;
-	sb->sv_firstinodezone = 2;
-	sb->sv_firstdatazone = sbd1->s_isize;
-	sb->sv_nzones = sbd1->s_fsize;
-	sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone;
-	return sb;
-}
-
-static const char* detect_sysv4 (struct super_block *sb, struct buffer_head *bh)
-{
-	struct sysv4_super_block * sbd;
-
-	sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	if (sbd->s_magic != 0xfd187e20)
-		return NULL;
-	if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */
-		return NULL;
-	if ((sbd->s_type > 3 || sbd->s_type < 1) && (sbd->s_type > 0x30 || sbd->s_type < 0x10))
-		return NULL;
-
-	/* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10,
-	   0x20 or 0x30 indicates that symbolic links and the 14-character
-	   filename limit is gone. Due to lack of information about this
-           feature read-only mode seems to be a reasonable approach... -KGB */
-
-	if (sbd->s_type >= 0x10) {
-		printk("SysV FS: can't handle long file names on %s, "
-		       "forcing read-only mode.\n", kdevname(sb->s_dev));
-		sb->s_flags |= MS_RDONLY;
-	}
-
-	detected_bs(sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type, sb);
-	sb->sv_type = FSTYPE_SYSV4;
-	return "SystemV";
-}
-
-static struct super_block * detected_sysv4 (struct super_block *sb, struct buffer_head *bh)
-{
-	struct sysv4_super_block * sbd;
-
-	if (sb->sv_block_size >= BLOCK_SIZE)
-		sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	else {
-		sbd = (struct sysv4_super_block *) bh->b_data;
-		/* sanity check */
-		if (sbd->s_magic != 0xfd187e20)
-			return NULL;
-		if (sbd->s_time < 315532800)
-			return NULL;
-	}
-
-	sb->sv_convert = 0;
-	sb->sv_kludge_symlinks = 0; /* ?? */
-	sb->sv_truncate = 1;
-	sb->sv_link_max = SYSV_LINK_MAX;
-	sb->sv_fic_size = SYSV_NICINOD;
-	sb->sv_flc_size = SYSV_NICFREE;
-	sb->sv_bh1 = bh;
-	sb->sv_bh2 = bh;
-	sb->sv_sbd1 = (char *) sbd;
-	sb->sv_sbd2 = (char *) sbd;
-	sb->sv_sb_fic_count = &sbd->s_ninode;
-	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
-	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
-	sb->sv_sb_flc_count = &sbd->s_nfree;
-	sb->sv_sb_flc_blocks = &sbd->s_free[0];
-	sb->sv_sb_total_free_blocks = &sbd->s_tfree;
-	sb->sv_sb_time = &sbd->s_time;
-	sb->sv_sb_state = &sbd->s_state;
-	sb->sv_firstinodezone = 2;
-	sb->sv_firstdatazone = sbd->s_isize;
-	sb->sv_nzones = sbd->s_fsize;
-	sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone;
-	return sb;
-}
-
-static const char* detect_sysv2 (struct super_block *sb, struct buffer_head *bh)
-{
-	struct sysv2_super_block * sbd;
-
-	sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	if (sbd->s_magic != 0xfd187e20)
-		return NULL;
-	if (sbd->s_time < 315532800) /* this is likely to happen on SystemV4 FS */
-		return NULL;
-	if (sbd->s_type > 3 || sbd->s_type < 1)
-		return NULL;
-	detected_bs(sbd->s_type, sb);
-	sb->sv_type = FSTYPE_SYSV2;
-	return "SystemV Release 2";
-}
-static struct super_block * detected_sysv2 (struct super_block *sb, struct buffer_head *bh)
-{
-	struct sysv2_super_block * sbd;
-
-	if (sb->sv_block_size >= BLOCK_SIZE)
-		sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	else {
-		sbd = (struct sysv2_super_block *) bh->b_data;
-		/* sanity check */
-		if (sbd->s_magic != 0xfd187e20)
-			return NULL;
-		if (sbd->s_time < 315532800)
-			return NULL;
-	}
-
-	sb->sv_convert = 0;
-	sb->sv_kludge_symlinks = 0; /* ?? */
-	sb->sv_truncate = 1;
-	sb->sv_link_max = SYSV_LINK_MAX;
-	sb->sv_fic_size = SYSV_NICINOD;
-	sb->sv_flc_size = SYSV_NICFREE;
-	sb->sv_bh1 = bh;
-	sb->sv_bh2 = bh;
-	sb->sv_sbd1 = (char *) sbd;
-	sb->sv_sbd2 = (char *) sbd;
-	sb->sv_sb_fic_count = &sbd->s_ninode;
-	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
-	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
-	sb->sv_sb_flc_count = &sbd->s_nfree;
-	sb->sv_sb_flc_blocks = &sbd->s_free[0];
-	sb->sv_sb_total_free_blocks = &sbd->s_tfree;
-	sb->sv_sb_time = &sbd->s_time;
-	sb->sv_sb_state = &sbd->s_state;
-	sb->sv_firstinodezone = 2;
-	sb->sv_firstdatazone = sbd->s_isize;
-	sb->sv_nzones = sbd->s_fsize;
-	sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone;
-	return sb;
-}
-
-static const char* detect_coherent (struct super_block *sb, struct buffer_head *bh)
-{
-	struct coh_super_block * sbd;
-
-	sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6))
-	    || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6)))
-		return NULL;
-	detected_bs(1, sb);
-	sb->sv_type = FSTYPE_COH;
-	return "Coherent";
-}
-static struct super_block * detected_coherent (struct super_block *sb, struct buffer_head *bh)
-{
-	struct coh_super_block * sbd;
-
-	sbd = (struct coh_super_block *) bh->b_data;
-	/* sanity check */
-	if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6))
-	    || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6)))
-		return NULL;
-
-	sb->sv_convert = 1;
-	sb->sv_kludge_symlinks = 1;
-	sb->sv_truncate = 1;
-	sb->sv_link_max = COH_LINK_MAX;
-	sb->sv_fic_size = COH_NICINOD;
-	sb->sv_flc_size = COH_NICFREE;
-	sb->sv_bh1 = bh;
-	sb->sv_bh2 = bh;
-	sb->sv_sbd1 = (char *) sbd;
-	sb->sv_sbd2 = (char *) sbd;
-	sb->sv_sb_fic_count = &sbd->s_ninode;
-	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
-	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
-	sb->sv_sb_flc_count = &sbd->s_nfree;
-	sb->sv_sb_flc_blocks = &sbd->s_free[0];
-	sb->sv_sb_total_free_blocks = &sbd->s_tfree;
-	sb->sv_sb_time = &sbd->s_time;
-	sb->sv_firstinodezone = 2;
-	sb->sv_firstdatazone = sbd->s_isize;
-	sb->sv_nzones = from_coh_ulong(sbd->s_fsize);
-	sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone;
-	return sb;
-}
 
-static struct super_block *sysv_read_super(struct super_block *sb,
-					   void *data, int silent)
-{
-	struct buffer_head *bh;
-	const char *found;
-	kdev_t dev = sb->s_dev;
-	struct inode *root_inode;
-	unsigned long blocknr;
-	
-	if (1024 != sizeof (struct xenix_super_block))
-		panic("Xenix FS: bad super-block size");
-	if ((512 != sizeof (struct sysv4_super_block))
-            || (512 != sizeof (struct sysv2_super_block)))
-		panic("SystemV FS: bad super-block size");
-	if (500 != sizeof (struct coh_super_block))
-		panic("Coherent FS: bad super-block size");
-	if (64 != sizeof (struct sysv_inode))
-		panic("sysv fs: bad i-node size");
-	set_blocksize(dev,BLOCK_SIZE);
-	sb->sv_block_base = 0;
-
-	/* Try to read Xenix superblock */
-	if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) {
-		if ((found = detect_xenix(sb,bh)) != NULL)
-			goto ok;
-		brelse(bh);
-	}
-	if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) {
-		/* Try to recognize SystemV superblock */
-		if ((found = detect_sysv4(sb,bh)) != NULL)
-			goto ok;
-		if ((found = detect_sysv2(sb,bh)) != NULL)
-			goto ok;
-		/* Try to recognize Coherent superblock */
-		if ((found = detect_coherent(sb,bh)) != NULL)
-			goto ok;
-		brelse(bh);
-	}
-	/* Try to recognize SystemV superblock */
-	/* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */
-	/* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */
-	/* Maybe we should also check the device geometry ? */
-	{	static int offsets[] = { 9, 15, 18, };
-		int i;
-		for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
-			if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
-				/* Try to recognize SystemV superblock */
-				if ((found = detect_sysv4(sb,bh)) != NULL) {
-					if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
-						goto bad_shift;
-					sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
-					goto ok;
-				}
-				if ((found = detect_sysv2(sb,bh)) != NULL) {
-					if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
-						goto bad_shift;
-					sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
-					goto ok;
-				}
-				brelse(bh);
-			}
-	}
-	bad_shift:
-	if (!silent)
-		printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device "
-		       "%s\n", kdevname(dev));
-	failed:
-	return NULL;
-
-	ok:
-	if (sb->sv_block_size >= BLOCK_SIZE) {
-		if (sb->sv_block_size != BLOCK_SIZE) {
-			brelse(bh);
-			set_blocksize(dev, sb->sv_block_size);
-			blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
-			if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL)
-				goto bad_superblock;
-		}
-		switch (sb->sv_type) {
-			case FSTYPE_XENIX:
-				if (!detected_xenix(sb,bh,bh))
-					goto bad_superblock;
-				break;
-			case FSTYPE_SYSV4:
-				if (!detected_sysv4(sb,bh))
-					goto bad_superblock;
-				break;
-			case FSTYPE_SYSV2:
-				if (!detected_sysv2(sb,bh))
-					goto bad_superblock;
-				break;
-			default: goto bad_superblock;
-		goto superblock_ok;
-		bad_superblock:
-			brelse(bh);
-			printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
-			goto failed;
-		superblock_ok:;
-		}
-	} else {
-		/* Switch to 512 block size. Unfortunately, we have to
-		   release the block bh and read it again. */
-		struct buffer_head *bh1, *bh2;
-		unsigned long blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
-
-		brelse(bh);
-		set_blocksize(dev,sb->sv_block_size);
-		bh1 = NULL; bh2 = NULL;
-		switch (sb->sv_type) {
-			case FSTYPE_XENIX:
-				if ((bh1 = bread(dev, blocknr, sb->sv_block_size)) == NULL)
-					goto bad_superblock2;
-				if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL)
-					goto bad_superblock2;
-				if (!detected_xenix(sb,bh1,bh2))
-					goto bad_superblock2;
-				break;
-			case FSTYPE_SYSV4:
-				if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL)
-					goto bad_superblock2;
-				if (!detected_sysv4(sb,bh2))
-					goto bad_superblock2;
-				break;
-			case FSTYPE_SYSV2:
-				if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL)
-					goto bad_superblock2;
-				if (!detected_sysv2(sb,bh2))
-					goto bad_superblock2;
-				break;
-			case FSTYPE_COH:
-				if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL)
-					goto bad_superblock2;
-				if (!detected_coherent(sb,bh2))
-					goto bad_superblock2;
-				break;
-			default:
-			bad_superblock2:
-				brelse(bh1);
-				brelse(bh2);
-				set_blocksize(sb->s_dev,BLOCK_SIZE);
-				printk("SysV FS: cannot read superblock in 512 byte mode\n");
-				goto failed;
-		}
-	}
-	sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits;
-	if (!silent)
-		printk("VFS: Found a %s FS (block size = %d) on device %s\n",
-		       found, sb->sv_block_size, kdevname(dev));
-	sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type;
-	/* The buffer code now supports block size 512 as well as 1024. */
-	sb->s_blocksize = sb->sv_block_size;
-	sb->s_blocksize_bits = sb->sv_block_size_bits;
-	/* set up enough so that it can read an inode */
-	sb->s_op = &sysv_sops;
-	root_inode = iget(sb,SYSV_ROOT_INO);
-	sb->s_root = d_alloc_root(root_inode);
-	if (!sb->s_root) {
-		printk("SysV FS: get root inode failed\n");
-		sysv_put_super(sb);
-		return NULL;
-	}
-#ifndef CONFIG_SYSV_FS_WRITE
-	sb->s_flags |= MS_RDONLY;
-#endif
-	sb->s_dirt = 1;
-	/* brelse(bh);  resp.  brelse(bh1); brelse(bh2);
-	   occurs when the disk is unmounted. */
-	return sb;
-}
 
 /* This is only called on sync() and umount(), when s_dirt=1. */
 static void sysv_write_super(struct super_block *sb)
@@ -523,15 +37,11 @@
 		   then attach current time stamp.
 		   But if the filesystem was marked clean, keep it clean. */
 		unsigned long time = CURRENT_TIME;
-		unsigned long old_time = *sb->sv_sb_time;
-		if (sb->sv_convert)
-			old_time = from_coh_ulong(old_time);
+		unsigned long old_time = fs32_to_cpu(sb, *sb->sv_sb_time);
 		if (sb->sv_type == FSTYPE_SYSV4)
-			if (*sb->sv_sb_state == 0x7c269d38 - old_time)
-				*sb->sv_sb_state = 0x7c269d38 - time;
-		if (sb->sv_convert)
-			time = to_coh_ulong(time);
-		*sb->sv_sb_time = time;
+			if (*sb->sv_sb_state == cpu_to_fs32(sb, 0x7c269d38 - old_time))
+				*sb->sv_sb_state = cpu_to_fs32(sb, 0x7c269d38 - time);
+		*sb->sv_sb_time = cpu_to_fs32(sb, time);
 		mark_buffer_dirty(sb->sv_bh2);
 	}
 	sb->s_dirt = 0;
@@ -550,445 +60,81 @@
 
 static int sysv_statfs(struct super_block *sb, struct statfs *buf)
 {
-	buf->f_type = sb->s_magic;			/* type of filesystem */
-	buf->f_bsize = sb->sv_block_size;		/* block size */
-	buf->f_blocks = sb->sv_ndatazones;		/* total data blocks in file system */
-	buf->f_bfree = sysv_count_free_blocks(sb);	/* free blocks in fs */
-	buf->f_bavail = buf->f_bfree;			/* free blocks available to non-superuser */
-	buf->f_files = sb->sv_ninodes;			/* total file nodes in file system */
-	buf->f_ffree = sysv_count_free_inodes(sb);	/* free file nodes in fs */
+	buf->f_type = sb->s_magic;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = sb->sv_ndatazones;
+	buf->f_bavail = buf->f_bfree = sysv_count_free_blocks(sb);
+	buf->f_files = sb->sv_ninodes;
+	buf->f_ffree = sysv_count_free_inodes(sb);
 	buf->f_namelen = SYSV_NAMELEN;
-	/* Don't know what value to put in buf->f_fsid */ /* file system id */
 	return 0;
 }
 
-
-/* bmap support for running executables and shared libraries. */
-
-static inline int inode_bmap(struct super_block * sb, struct inode * inode, int nr)
-{
-	int tmp = inode->u.sysv_i.i_data[nr];
-	if (!tmp)
-		return 0;
-	return tmp + sb->sv_block_base;
-}
-
-static int block_bmap(struct super_block * sb, struct buffer_head * bh, int nr, int convert)
-{
-	int tmp;
-
-	if (!bh)
-		return 0;
-	tmp = ((sysv_zone_t *) bh->b_data) [nr];
-	if (convert)
-		tmp = from_coh_ulong(tmp);
-	brelse(bh);
-	if (!tmp)
-		return 0;
-	return tmp + sb->sv_block_base;
-}
-
-static unsigned int sysv_block_map(struct inode *inode, unsigned int block)
-{
-	struct super_block *sb;
-	int i, ret, convert;
-
-	ret = 0;
-	lock_kernel();
-	sb = inode->i_sb;
-	if (block < 10) {
-		ret = inode_bmap(sb, inode, block);
-		goto out;
-	}
-	block -= 10;
-	convert = sb->sv_convert;
-	if (block < sb->sv_ind_per_block) {
-		i = inode_bmap(sb, inode, 10);
-		if (!i)
-			goto out;
-		ret = block_bmap(sb,
-				 bread(inode->i_dev, i, sb->sv_block_size),
-				 block, convert);
-		goto out;
-	}
-	block -= sb->sv_ind_per_block;
-	if (block < sb->sv_ind_per_block_2) {
-		i = inode_bmap(sb, inode, 11);
-		if (!i)
-			goto out;
-		i = block_bmap(sb,
-			       bread(inode->i_dev, i, sb->sv_block_size),
-			       (block >> sb->sv_ind_per_block_bits), convert);
-		if (!i)
-			goto out;
-		ret = block_bmap(sb,
-				 bread(inode->i_dev, i, sb->sv_block_size),
-				 (block & sb->sv_ind_per_block_1), convert);
-		goto out;
-	}
-	block -= sb->sv_ind_per_block_2;
-	if (block < sb->sv_ind_per_block_3) {
-		i = inode_bmap(sb, inode, 12);
-		if (!i)
-			goto out;
-		i = block_bmap(sb,
-			       bread(inode->i_dev, i, sb->sv_block_size),
-			       (block >> sb->sv_ind_per_block_2_bits), convert);
-		if (!i)
-			goto out;
-		ret = block_bmap(sb,
-				 bread(inode->i_dev, i, sb->sv_block_size),
-				 ((block >> sb->sv_ind_per_block_bits) &
-				  sb->sv_ind_per_block_1), convert);
-		if (!i)
-			goto out;
-		ret = block_bmap(sb,
-				 bread(inode->i_dev, i, sb->sv_block_size),
-				 (block & sb->sv_ind_per_block_1), convert);
-		goto out;
-	}
-	if ((int)block < 0)
-		printk("sysv_block_map: block < 0\n");
-	else
-		printk("sysv_block_map: block > big\n");
-out:
-	unlock_kernel();
-	return ret;
-}
-
-/* End of bmap support. */
-
-
-/* Access selected blocks of regular files (or directories) */
-
-static struct buffer_head *inode_getblk(struct inode *inode, int nr, int new_block,
-	int *err, int metadata, long *phys, int *new)
+/* 
+ * NXI <-> N0XI for PDP, XIN <-> XIN0 for le32, NIX <-> 0NIX for be32
+ */
+static inline void read3byte(struct super_block *sb,
+	unsigned char * from, unsigned char * to)
 {
-	struct super_block *sb;
-	u32 tmp;
-	u32 *p;
-	struct buffer_head * result;
-
-	sb = inode->i_sb;
-	p = inode->u.sysv_i.i_data + nr;
-repeat:
-	tmp = *p;
-	if (tmp) {
-		if (metadata) {
-			result = sv_getblk(sb, inode->i_dev, tmp);
-			if (tmp == *p)
-				return result;
-			brelse(result);
-			goto repeat;
-		} else {
-			*phys = tmp;
-			return NULL;
-		}
-	}
-
-	tmp = sysv_new_block(sb);
-	if (!tmp) {
-		*err = -ENOSPC;
-		return NULL;
-	}
-	if (metadata) {
-		result = sv_getblk(sb, inode->i_dev, tmp);
-		if (*p) {
-			sysv_free_block(sb, tmp);
-			brelse(result);
-			goto repeat;
-		}
+	if (sb->sv_bytesex == BYTESEX_PDP) {
+		to[0] = from[0];
+		to[1] = 0;
+		to[2] = from[1];
+		to[3] = from[2];
+	} else if (sb->sv_bytesex == BYTESEX_LE) {
+		to[0] = from[0];
+		to[1] = from[1];
+		to[2] = from[2];
+		to[3] = 0;
 	} else {
-		if (*p) {
-			/*
-			 * Nobody is allowed to change block allocation
-			 * state from under us:
-			 */
-			BUG();
-			sysv_free_block(sb, tmp);
-			goto repeat;
-		}
-		*phys = tmp;
-		result = NULL;
-		*err = 0;
-		*new = 1;
+		to[0] = 0;
+		to[1] = from[0];
+		to[2] = from[1];
+		to[3] = from[2];
 	}
-	*p = tmp;
-
-	inode->i_ctime = CURRENT_TIME;
-	mark_inode_dirty(inode);
-	return result;
 }
 
-static struct buffer_head *block_getblk(struct inode *inode,
-	struct buffer_head *bh, int nr, int new_block, int *err,
-	int metadata, long *phys, int *new)
-{
-	struct super_block *sb;
-	u32 tmp, block;
-	sysv_zone_t *p;
-	struct buffer_head * result;
-
-	result = NULL;
-	if (!bh)
-		goto out;
-	if (!buffer_uptodate(bh)) {
-		ll_rw_block(READ, 1, &bh);
-		wait_on_buffer(bh);
-		if (!buffer_uptodate(bh))
-			goto out;
-	}
-	sb = inode->i_sb;
-	p = nr + (sysv_zone_t *) bh->b_data;
-repeat:
-	block = tmp = *p;
-	if (sb->sv_convert)
-		block = from_coh_ulong(block);
-	if (tmp) {
-		if (metadata) {
-			result = sv_getblk(sb, bh->b_dev, block);
-			if (tmp == *p)
-				goto out;
-			brelse(result);
-			goto repeat;
-		} else {
-			*phys = tmp;
-			goto out;
-		}
-	}
-
-	block = sysv_new_block(sb);
-	if (!block)
-		goto out;
-	if (metadata) {
-		result = sv_getblk(sb, bh->b_dev, block);
-		if (*p) {
-			sysv_free_block(sb, block);
-			brelse(result);
-			goto repeat;
-		}
-		memset(result->b_data, 0, sb->sv_block_size);
-		mark_buffer_uptodate(result, 1);
-		mark_buffer_dirty(result);
+static inline void write3byte(struct super_block *sb,
+	unsigned char * from, unsigned char * to)
+{
+	if (sb->sv_bytesex == BYTESEX_PDP) {
+		to[0] = from[0];
+		to[1] = from[2];
+		to[2] = from[3];
+	} else if (sb->sv_bytesex == BYTESEX_LE) {
+		to[0] = from[0];
+		to[1] = from[1];
+		to[2] = from[2];
 	} else {
-		*phys = tmp;
-		*new = 1;
-	}
-	if (*p) {
-		sysv_free_block(sb, block);
-		brelse(result);
-		goto repeat;
+		to[0] = from[1];
+		to[1] = from[2];
+		to[2] = from[3];
 	}
-	*p = (sb->sv_convert ? to_coh_ulong(block) : block);
-	mark_buffer_dirty(bh);
-	*err = 0;
-out:
-	brelse(bh);
-	return result;
 }
 
-static int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
-{
-	struct super_block *sb;
-	int ret, err, new;
-	struct buffer_head *bh;
-	unsigned long ptr, phys;
-
-	if (!create) {
-		phys = sysv_block_map(inode, iblock);
-		if (phys) {
-			bh_result->b_dev = inode->i_dev;
-			bh_result->b_blocknr = phys;
-			bh_result->b_state |= (1UL << BH_Mapped);
-		}
-		return 0;
-	}
-
-	err = -EIO;
-	new = 0;
-	ret = 0;
-	bh = NULL;
-
-	lock_kernel();
-	sb = inode->i_sb;
-	if (iblock < 0)
-		goto abort_negative;
-	if (iblock > sb->sv_ind_per_block_3)
-		goto abort_too_big;
-
-	err = 0;
-	ptr = iblock;
-
-	/*
-	 * ok, these macros clean the logic up a bit and make
-	 * it much more readable:
-	 */
-#define GET_INODE_DATABLOCK(x) \
-		inode_getblk(inode, x, iblock, &err, 0, &phys, &new)
-#define GET_INODE_PTR(x) \
-		inode_getblk(inode, x, iblock, &err, 1, NULL, NULL)
-#define GET_INDIRECT_DATABLOCK(x) \
-		block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new);
-#define GET_INDIRECT_PTR(x) \
-		block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL);
-
-	if (ptr < 10) {
-		bh = GET_INODE_DATABLOCK(ptr);
-		goto out;
-	}
-	ptr -= 10;
-	if (ptr < sb->sv_ind_per_block) {
-		bh = GET_INODE_PTR(10);
-		goto get_indirect;
-	}
-	ptr -= sb->sv_ind_per_block;
-	if (ptr < sb->sv_ind_per_block_2) {
-		bh = GET_INODE_PTR(11);
-		goto get_double;
-	}
-	ptr -= sb->sv_ind_per_block_2;
-	bh = GET_INODE_PTR(12);
-	bh = GET_INDIRECT_PTR(ptr >> sb->sv_ind_per_block_2_bits);
-get_double:
-	bh = GET_INDIRECT_PTR((ptr >> sb->sv_ind_per_block_bits) & sb->sv_ind_per_block_1);
-get_indirect:
-	bh = GET_INDIRECT_DATABLOCK(ptr & sb->sv_ind_per_block_1);
-
-#undef GET_INODE_DATABLOCK
-#undef GET_INODE_PTR
-#undef GET_INDIRECT_DATABLOCK
-#undef GET_INDIRECT_PTR
-
-out:
-	if (err)
-		goto abort;
-	bh_result->b_dev = inode->i_dev;
-	bh_result->b_blocknr = phys;
-	bh_result->b_state |= (1UL << BH_Mapped);
-	if (new)
-		bh_result->b_state |= (1UL << BH_New);
-abort:
-	unlock_kernel();
-	return err;
-
-abort_negative:
-	printk("sysv_get_block: block < 0\n");
-	goto abort;
-
-abort_too_big:
-	printk("sysv_get_block: block > big\n");
-	goto abort;
-}
-
-static struct buffer_head *sysv_getblk(struct inode *inode, unsigned int block, int create)
-{
-	struct buffer_head dummy;
-	int error;
-
-	dummy.b_state = 0;
-	dummy.b_blocknr = -1000;
-	error = sysv_get_block(inode, block, &dummy, create);
-	if (!error && buffer_mapped(&dummy)) {
-		struct buffer_head *bh;
-		bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->sv_block_size);
-		if (buffer_new(&dummy)) {
-			memset(bh->b_data, 0, inode->i_sb->sv_block_size);
-			mark_buffer_uptodate(bh, 1);
-			mark_buffer_dirty(bh);
-		}
-		return bh;
-	}
-	return NULL;
-}
-
-struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create)
-{
-	struct buffer_head *bh;
-
-	bh = sysv_getblk(inode, block, create);
-	if (!bh || buffer_uptodate(bh))
-		return bh;
-	ll_rw_block(READ, 1, &bh);
-	wait_on_buffer(bh);
-	if (buffer_uptodate(bh))
-		return bh;
-	brelse(bh);
-	return NULL;
-}
-
-static int sysv_writepage(struct page *page)
-{
-	return block_write_full_page(page,sysv_get_block);
-}
-static int sysv_readpage(struct file *file, struct page *page)
-{
-	return block_read_full_page(page,sysv_get_block);
-}
-static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
-{
-	return block_prepare_write(page,from,to,sysv_get_block);
-}
-static int sysv_bmap(struct address_space *mapping, long block)
-{
-	return generic_block_bmap(mapping,block,sysv_get_block);
-}
-struct address_space_operations sysv_aops = {
-	readpage: sysv_readpage,
-	writepage: sysv_writepage,
-	sync_page: block_sync_page,
-	prepare_write: sysv_prepare_write,
-	commit_write: generic_commit_write,
-	bmap: sysv_bmap
-};
-
-#ifdef __BIG_ENDIAN
-
-static inline unsigned long read3byte (unsigned char * p)
-{
-	return (p[2] | (p[1]<<8) | (p[0]<<16));
-}
-
-static inline void write3byte (unsigned char *p , unsigned long val)
-{
-	p[2]=val&0xFF;
-	p[1]=(val>>8)&0xFF;
-	p[0]=(val>>16)&0xFF;
-}
-
-#else
-
-static inline unsigned long read3byte (unsigned char * p)
-{
-	return (unsigned long)(*(unsigned short *)p)
-	     | (unsigned long)(*(unsigned char *)(p+2)) << 16;
-}
-
-static inline void write3byte (unsigned char * p, unsigned long val)
-{
-	*(unsigned short *)p = (unsigned short) val;
-	*(unsigned char *)(p+2) = val >> 16;
-}
-
-#endif
-
-static inline unsigned long coh_read3byte (unsigned char * p)
-{
-	return (unsigned long)(*(unsigned char *)p) << 16
-	     | (unsigned long)(*(unsigned short *)(p+1));
-}
-
-static inline void coh_write3byte (unsigned char * p, unsigned long val)
-{
-	*(unsigned char *)p = val >> 16;
-	*(unsigned short *)(p+1) = (unsigned short) val;
-}
-
-struct inode_operations sysv_symlink_inode_operations = {
+static struct inode_operations sysv_symlink_inode_operations = {
 	readlink:	page_readlink,
 	follow_link:	page_follow_link,
 	setattr:	sysv_notify_change,
 };
 
+void sysv_set_inode(struct inode *inode, dev_t rdev)
+{
+	if (S_ISREG(inode->i_mode)) {
+		inode->i_op = &sysv_file_inode_operations;
+		inode->i_fop = &sysv_file_operations;
+		inode->i_mapping->a_ops = &sysv_aops;
+	} else if (S_ISDIR(inode->i_mode)) {
+		inode->i_op = &sysv_dir_inode_operations;
+		inode->i_fop = &sysv_dir_operations;
+		inode->i_mapping->a_ops = &sysv_aops;
+	} else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &sysv_symlink_inode_operations;
+		inode->i_mapping->a_ops = &sysv_aops;
+	} else
+		init_special_inode(inode, inode->i_mode, rdev);
+}
+
 static void sysv_read_inode(struct inode *inode)
 {
 	struct super_block * sb = inode->i_sb;
@@ -996,67 +142,41 @@
 	struct sysv_inode * raw_inode;
 	unsigned int block, ino;
 	umode_t mode;
+	dev_t rdev = 0;
 
 	ino = inode->i_ino;
-	inode->i_mode = 0;
 	if (!ino || ino > sb->sv_ninodes) {
 		printk("Bad inode number on dev %s"
 		       ": %d is out of range\n",
 		       kdevname(inode->i_dev), ino);
 		return;
 	}
-	block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits);
-	if (!(bh = sv_bread(sb,inode->i_dev,block))) {
-		printk("Major problem: unable to read inode from dev "
-		       "%s\n",
-		       kdevname(inode->i_dev));
+	raw_inode = sysv_raw_inode(sb, ino, &bh);
+	if (!raw_inode) {
+		printk("Major problem: unable to read inode from dev %s\n",
+		       bdevname(inode->i_dev));
 		return;
 	}
-	raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
-	mode = raw_inode->i_mode;
+	mode = fs16_to_cpu(sb, raw_inode->i_mode);
 	if (sb->sv_kludge_symlinks)
 		mode = from_coh_imode(mode);
 	/* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */
 	inode->i_mode = mode;
-	inode->i_uid = (uid_t)raw_inode->i_uid;
-	inode->i_gid = (gid_t)raw_inode->i_gid;
-	inode->i_nlink = raw_inode->i_nlink;
-	if (sb->sv_convert) {
-		inode->i_size = from_coh_ulong(raw_inode->i_size);
-		inode->i_atime = from_coh_ulong(raw_inode->i_atime);
-		inode->i_mtime = from_coh_ulong(raw_inode->i_mtime);
-		inode->i_ctime = from_coh_ulong(raw_inode->i_ctime);
-	} else {
-		inode->i_size = raw_inode->i_size;
-		inode->i_atime = raw_inode->i_atime;
-		inode->i_mtime = raw_inode->i_mtime;
-		inode->i_ctime = raw_inode->i_ctime;
-	}
+	inode->i_uid = (uid_t)fs16_to_cpu(sb, raw_inode->i_uid);
+	inode->i_gid = (gid_t)fs16_to_cpu(sb, raw_inode->i_gid);
+	inode->i_nlink = fs16_to_cpu(sb, raw_inode->i_nlink);
+	inode->i_size = fs32_to_cpu(sb, raw_inode->i_size);
+	inode->i_atime = fs32_to_cpu(sb, raw_inode->i_atime);
+	inode->i_mtime = fs32_to_cpu(sb, raw_inode->i_mtime);
+	inode->i_ctime = fs32_to_cpu(sb, raw_inode->i_ctime);
 	inode->i_blocks = inode->i_blksize = 0;
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		;
-	else
-	if (sb->sv_convert)
-		for (block = 0; block < 10+1+1+1; block++)
-			inode->u.sysv_i.i_data[block] =
-				coh_read3byte(&raw_inode->i_a.i_addb[3*block]);
-	else
-		for (block = 0; block < 10+1+1+1; block++)
-			inode->u.sysv_i.i_data[block] =
-				read3byte(&raw_inode->i_a.i_addb[3*block]);
-	if (S_ISREG(inode->i_mode)) {
-		inode->i_op = &sysv_file_inode_operations;
-		inode->i_fop = &sysv_file_operations;
-		inode->i_mapping->a_ops = &sysv_aops;
-	} else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &sysv_dir_inode_operations;
-		inode->i_fop = &sysv_dir_operations;
-	} else if (S_ISLNK(inode->i_mode)) {
-		inode->i_op = &sysv_symlink_inode_operations;
-		inode->i_mapping->a_ops = &sysv_aops;
-	} else
-		init_special_inode(inode, inode->i_mode,raw_inode->i_a.i_rdev);
+	for (block = 0; block < 10+1+1+1; block++)
+		read3byte(sb, &raw_inode->i_a.i_addb[3*block],
+			(unsigned char*)&inode->u.sysv_i.i_data[block]);
 	brelse(bh);
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+		rdev = (u16)fs32_to_cpu(sb, inode->u.sysv_i.i_data[0]);
+	sysv_set_inode(inode, rdev);
 }
 
 /* To avoid inconsistencies between inodes in memory and inodes on disk. */
@@ -1088,44 +208,32 @@
 
 	ino = inode->i_ino;
 	if (!ino || ino > sb->sv_ninodes) {
-		printk("Bad inode number on dev %s"
-		       ": %d is out of range\n",
-		       kdevname(inode->i_dev), ino);
+		printk("Bad inode number on dev %s: %d is out of range\n",
+		       bdevname(inode->i_dev), ino);
 		return 0;
 	}
-	block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits);
-	if (!(bh = sv_bread(sb,inode->i_dev,block))) {
+	raw_inode = sysv_raw_inode(sb, ino, &bh);
+	if (!raw_inode) {
 		printk("unable to read i-node block\n");
 		return 0;
 	}
-	raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
 	mode = inode->i_mode;
 	if (sb->sv_kludge_symlinks)
 		mode = to_coh_imode(mode);
-	raw_inode->i_mode = mode;
-	raw_inode->i_uid = fs_high2lowuid(inode->i_uid);
-	raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
-	raw_inode->i_nlink = inode->i_nlink;
-	if (sb->sv_convert) {
-		raw_inode->i_size = to_coh_ulong(inode->i_size);
-		raw_inode->i_atime = to_coh_ulong(inode->i_atime);
-		raw_inode->i_mtime = to_coh_ulong(inode->i_mtime);
-		raw_inode->i_ctime = to_coh_ulong(inode->i_ctime);
-	} else {
-		raw_inode->i_size = inode->i_size;
-		raw_inode->i_atime = inode->i_atime;
-		raw_inode->i_mtime = inode->i_mtime;
-		raw_inode->i_ctime = inode->i_ctime;
-	}
+	raw_inode->i_mode = cpu_to_fs16(sb, mode);
+	raw_inode->i_uid = cpu_to_fs16(sb, fs_high2lowuid(inode->i_uid));
+	raw_inode->i_gid = cpu_to_fs16(sb, fs_high2lowgid(inode->i_gid));
+	raw_inode->i_nlink = cpu_to_fs16(sb, inode->i_nlink);
+	raw_inode->i_size = cpu_to_fs32(sb, inode->i_size);
+	raw_inode->i_atime = cpu_to_fs32(sb, inode->i_atime);
+	raw_inode->i_mtime = cpu_to_fs32(sb, inode->i_mtime);
+	raw_inode->i_ctime = cpu_to_fs32(sb, inode->i_ctime);
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		raw_inode->i_a.i_rdev = kdev_t_to_nr(inode->i_rdev); /* write 2 or 3 bytes ?? */
-	else
-	if (sb->sv_convert)
-		for (block = 0; block < 10+1+1+1; block++)
-			coh_write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]);
-	else
-		for (block = 0; block < 10+1+1+1; block++)
-			write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]);
+		inode->u.sysv_i.i_data[0] = 
+			cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev));
+	for (block = 0; block < 10+1+1+1; block++)
+		write3byte(sb, (unsigned char*)&inode->u.sysv_i.i_data[block],
+			&raw_inode->i_a.i_addb[3*block]);
 	mark_buffer_dirty(bh);
 	return bh;
 }
@@ -1148,11 +256,9 @@
         if (bh && buffer_dirty(bh)) {
                 ll_rw_block(WRITE, 1, &bh);
                 wait_on_buffer(bh);
-                if (buffer_req(bh) && !buffer_uptodate(bh))
-                {
-                        printk ("IO error syncing sysv inode ["
-				"%s:%08lx]\n",
-                                kdevname(inode->i_dev), inode->i_ino);
+                if (buffer_req(bh) && !buffer_uptodate(bh)) {
+                        printk ("IO error syncing sysv inode [%s:%08lx]\n",
+                                bdevname(inode->i_dev), inode->i_ino);
                         err = -1;
                 }
         }
@@ -1162,21 +268,20 @@
         return err;
 }
 
-/* Every kernel module contains stuff like this. */
-
-static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
-
-static int __init init_sysv_fs(void)
-{
-	return register_filesystem(&sysv_fs_type);
-}
-
-static void __exit exit_sysv_fs(void)
+static void sysv_delete_inode(struct inode *inode)
 {
-	unregister_filesystem(&sysv_fs_type);
+	lock_kernel();
+	inode->i_size = 0;
+	sysv_truncate(inode);
+	sysv_free_inode(inode);
+	unlock_kernel();
 }
 
-EXPORT_NO_SYMBOLS;
-
-module_init(init_sysv_fs)
-module_exit(exit_sysv_fs)
+struct super_operations sysv_sops = {
+	read_inode:	sysv_read_inode,
+	write_inode:	sysv_write_inode,
+	delete_inode:	sysv_delete_inode,
+	put_super:	sysv_put_super,
+	write_super:	sysv_write_super,
+	statfs:		sysv_statfs,
+};
diff -urN linux-2.4.6-pre8/fs/sysv/itree.c linux/fs/sysv/itree.c
--- linux-2.4.6-pre8/fs/sysv/itree.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/sysv/itree.c	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,440 @@
+/*
+ *  linux/fs/sysv/itree.c
+ *
+ *  Handling of indirect blocks' trees.
+ *  AV, Sep--Dec 2000
+ */
+
+#include <linux/fs.h>
+#include <linux/sysv_fs.h>
+#include <linux/locks.h>
+#include <linux/smp_lock.h>
+
+enum {DIRECT = 10, DEPTH = 4};	/* Have triple indirect */
+
+static inline void dirty_indirect(struct buffer_head *bh, struct inode *inode)
+{
+	mark_buffer_dirty_inode(bh, inode);
+	if (IS_SYNC(inode)) {
+		ll_rw_block (WRITE, 1, &bh);
+		wait_on_buffer (bh);
+	}
+}
+
+static int block_to_path(struct inode *inode, long block, int offsets[DEPTH])
+{
+	struct super_block *sb = inode->i_sb;
+	int ptrs_bits = sb->sv_ind_per_block_bits;
+	unsigned long	indirect_blocks = sb->sv_ind_per_block,
+			double_blocks = sb->sv_ind_per_block_2;
+	int n = 0;
+
+	if (block < 0) {
+		printk("sysv_block_map: block < 0\n");
+	} else if (block < DIRECT) {
+		offsets[n++] = block;
+	} else if ( (block -= DIRECT) < indirect_blocks) {
+		offsets[n++] = DIRECT;
+		offsets[n++] = block;
+	} else if ((block -= indirect_blocks) < double_blocks) {
+		offsets[n++] = DIRECT+1;
+		offsets[n++] = block >> ptrs_bits;
+		offsets[n++] = block & (indirect_blocks - 1);
+	} else if (((block -= double_blocks) >> (ptrs_bits * 2)) < indirect_blocks) {
+		offsets[n++] = DIRECT+2;
+		offsets[n++] = block >> (ptrs_bits * 2);
+		offsets[n++] = (block >> ptrs_bits) & (indirect_blocks - 1);
+		offsets[n++] = block & (indirect_blocks - 1);
+	} else {
+		/* nothing */;
+	}
+	return n;
+}
+
+static inline int block_to_cpu(struct super_block *sb, u32 nr)
+{
+	return sb->sv_block_base + fs32_to_cpu(sb, nr);
+}
+
+typedef struct {
+	u32     *p;
+	u32     key;
+	struct buffer_head *bh;
+} Indirect;
+
+static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+{
+	p->key = *(p->p = v);
+	p->bh = bh;
+}
+
+static inline int verify_chain(Indirect *from, Indirect *to)
+{
+	while (from <= to && from->key == *from->p)
+		from++;
+	return (from > to);
+}
+
+static inline u32 *block_end(struct buffer_head *bh)
+{
+	return (u32*)((char*)bh->b_data + bh->b_size);
+}
+
+static Indirect *get_branch(struct inode *inode,
+			    int depth,
+			    int offsets[],
+			    Indirect chain[],
+			    int *err)
+{
+	kdev_t dev = inode->i_dev;
+	int size = inode->i_sb->s_blocksize;
+	Indirect *p = chain;
+	struct buffer_head *bh;
+
+	*err = 0;
+	add_chain (chain, NULL, inode->u.sysv_i.i_data + *offsets);
+	if (!p->key)
+		goto no_block;
+	while (--depth) {
+		int block = block_to_cpu(inode->i_sb, p->key);
+		bh = bread(dev, block, size);
+		if (!bh)
+			goto failure;
+		if (!verify_chain(chain, p))
+			goto changed;
+		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		if (!p->key)
+		goto no_block;
+	}
+	return NULL;
+
+changed:
+	*err = -EAGAIN;
+	goto no_block;
+failure:
+	*err = -EIO;
+no_block:
+	return p;
+}
+
+static int alloc_branch(struct inode *inode,
+			int num,
+			int *offsets,
+			Indirect *branch)
+{
+	int blocksize = inode->i_sb->s_blocksize;
+	int n = 0;
+	int i;
+
+	branch[0].key = sysv_new_block(inode->i_sb);
+	if (branch[0].key) for (n = 1; n < num; n++) {
+		struct buffer_head *bh;
+		int parent;
+		/* Allocate the next block */
+		branch[n].key = sysv_new_block(inode->i_sb);
+		if (!branch[n].key)
+			break;
+		/*
+		 * Get buffer_head for parent block, zero it out and set 
+		 * the pointer to new one, then send parent to disk.
+		 */
+		parent = block_to_cpu(inode->i_sb, branch[n-1].key);
+		bh = getblk(inode->i_dev, parent, blocksize);
+		lock_buffer(bh);
+		memset(bh->b_data, 0, blocksize);
+		branch[n].bh = bh;
+		branch[n].p = (u32*) bh->b_data + offsets[n];
+		*branch[n].p = branch[n].key;
+		mark_buffer_uptodate(bh, 1);
+		unlock_buffer(bh);
+		dirty_indirect(bh, inode);
+	}
+	if (n == num)
+		return 0;
+
+	/* Allocation failed, free what we already allocated */
+	for (i = 1; i < n; i++)
+		bforget(branch[i].bh);
+	for (i = 0; i < n; i++)
+		sysv_free_block(inode->i_sb, branch[i].key);
+	return -ENOSPC;
+}
+
+static inline int splice_branch(struct inode *inode,
+				Indirect chain[],
+				Indirect *where,
+				int num)
+{
+	int i;
+	/* Verify that place we are splicing to is still there and vacant */
+
+	if (!verify_chain(chain, where-1) || *where->p)
+		goto changed;
+
+	*where->p = where->key;
+	inode->i_ctime = CURRENT_TIME;
+
+	/* had we spliced it onto indirect block? */
+	if (where->bh)
+		dirty_indirect(where->bh, inode);
+
+	if (IS_SYNC(inode))
+		sysv_sync_inode(inode);
+	else
+		mark_inode_dirty(inode);
+	return 0;
+
+changed:
+	for (i = 1; i < num; i++)
+		bforget(where[i].bh);
+	for (i = 0; i < num; i++)
+		sysv_free_block(inode->i_sb, where[i].key);
+	return -EAGAIN;
+}
+
+static int get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+{
+	int err = -EIO;
+	int offsets[DEPTH];
+	Indirect chain[DEPTH];
+	struct super_block *sb = inode->i_sb;
+	Indirect *partial;
+	int left;
+	int depth = block_to_path(inode, iblock, offsets);
+
+	if (depth == 0)
+		goto out;
+
+	lock_kernel();
+reread:
+	partial = get_branch(inode, depth, offsets, chain, &err);
+
+	/* Simplest case - block found, no allocation needed */
+	if (!partial) {
+got_it:
+		bh_result->b_dev = sb->s_dev;
+		bh_result->b_blocknr = block_to_cpu(sb, chain[depth-1].key);
+		bh_result->b_state |= (1UL << BH_Mapped);
+		/* Clean up and exit */
+		partial = chain+depth-1; /* the whole chain */
+		goto cleanup;
+	}
+
+	/* Next simple case - plain lookup or failed read of indirect block */
+	if (!create || err == -EIO) {
+cleanup:
+		while (partial > chain) {
+			brelse(partial->bh);
+			partial--;
+		}
+		unlock_kernel();
+out:
+		return err;
+	}
+
+	/*
+	 * Indirect block might be removed by truncate while we were
+	 * reading it. Handling of that case (forget what we've got and
+	 * reread) is taken out of the main path.
+	 */
+	if (err == -EAGAIN)
+		goto changed;
+
+	left = (chain + depth) - partial;
+	err = alloc_branch(inode, left, offsets+(partial-chain), partial);
+	if (err)
+		goto cleanup;
+
+	if (splice_branch(inode, chain, partial, left) < 0)
+		goto changed;
+
+	bh_result->b_state |= (1UL << BH_New);
+	goto got_it;
+
+changed:
+	while (partial > chain) {
+		brelse(partial->bh);
+		partial--;
+	}
+	goto reread;
+}
+
+static inline int all_zeroes(u32 *p, u32 *q)
+{
+	while (p < q)
+		if (*p++)
+			return 0;
+	return 1;
+}
+
+static Indirect *find_shared(struct inode *inode,
+				int depth,
+				int offsets[],
+				Indirect chain[],
+				u32 *top)
+{
+	Indirect *partial, *p;
+	int k, err;
+
+	*top = 0;
+	for (k = depth; k > 1 && !offsets[k-1]; k--)
+		;
+	partial = get_branch(inode, k, offsets, chain, &err);
+	if (!partial)
+		partial = chain + k-1;
+	/*
+	 * If the branch acquired continuation since we've looked at it -
+	 * fine, it should all survive and (new) top doesn't belong to us.
+	 */
+	if (!partial->key && *partial->p)
+		goto no_top;
+	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+		;
+	/*
+	 * OK, we've found the last block that must survive. The rest of our
+	 * branch should be detached before unlocking. However, if that rest
+	 * of branch is all ours and does not grow immediately from the inode
+	 * it's easier to cheat and just decrement partial->p.
+	 */
+	if (p == chain + k - 1 && p > chain) {
+		p->p--;
+	} else {
+		*top = *p->p;
+		*p->p = 0;
+	}
+
+	while(partial > p) {
+		brelse(partial->bh);
+		partial--;
+	}
+no_top:
+	return partial;
+}
+
+static inline void free_data(struct inode *inode, u32 *p, u32 *q)
+{
+	for ( ; p < q ; p++) {
+		u32 nr = *p;
+		if (nr) {
+			*p = 0;
+			sysv_free_block(inode->i_sb, nr);
+			mark_inode_dirty(inode);
+		}
+	}
+}
+
+static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
+{
+	struct buffer_head * bh;
+	struct super_block *sb = inode->i_sb;
+
+	if (depth--) {
+		for ( ; p < q ; p++) {
+			int block;
+			u32 nr = *p;
+			if (!nr)
+				continue;
+			*p = 0;
+			block = block_to_cpu(sb, nr);
+			bh = bread(inode->i_dev, block, sb->s_blocksize);
+			if (!bh)
+				continue;
+			free_branches(inode, (u32*)bh->b_data,
+					block_end(bh), depth);
+			bforget(bh);
+			sysv_free_block(sb, nr);
+			mark_inode_dirty(inode);
+		}
+	} else
+		free_data(inode, p, q);
+}
+
+void sysv_truncate (struct inode * inode)
+{
+	u32 *i_data = inode->u.sysv_i.i_data;
+	int offsets[DEPTH];
+	Indirect chain[DEPTH];
+	Indirect *partial;
+	int nr = 0;
+	int n;
+	long iblock;
+	unsigned blocksize;
+
+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+	    S_ISLNK(inode->i_mode)))
+		return;
+
+	blocksize = inode->i_sb->s_blocksize;
+	iblock = (inode->i_size + blocksize-1)
+					>> inode->i_sb->s_blocksize_bits;
+
+	block_truncate_page(inode->i_mapping, inode->i_size, get_block);
+
+	n = block_to_path(inode, iblock, offsets);
+	if (n == 0)
+		return;
+
+	if (n == 1) {
+		free_data(inode, i_data+offsets[0], i_data + DIRECT);
+		goto do_indirects;
+	}
+
+	partial = find_shared(inode, n, offsets, chain, &nr);
+	/* Kill the top of shared branch (already detached) */
+	if (nr) {
+		if (partial == chain)
+			mark_inode_dirty(inode);
+		else
+			dirty_indirect(partial->bh, inode);
+		free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
+	}
+	/* Clear the ends of indirect blocks on the shared branch */
+	while (partial > chain) {
+		free_branches(inode, partial->p + 1, block_end(partial->bh),
+				(chain+n-1) - partial);
+		dirty_indirect(partial->bh, inode);
+		brelse (partial->bh);
+		partial--;
+	}
+do_indirects:
+	/* Kill the remaining (whole) subtrees (== subtrees deeper than...) */
+	while (n < DEPTH) {
+		nr = i_data[DIRECT + n - 1];
+		if (nr) {
+			i_data[DIRECT + n - 1] = 0;
+			mark_inode_dirty(inode);
+			free_branches(inode, &nr, &nr+1, n);
+		}
+		n++;
+	}
+	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	if (IS_SYNC(inode))
+		sysv_sync_inode (inode);
+	else
+		mark_inode_dirty(inode);
+}
+
+static int sysv_writepage(struct page *page)
+{
+	return block_write_full_page(page,get_block);
+}
+static int sysv_readpage(struct file *file, struct page *page)
+{
+	return block_read_full_page(page,get_block);
+}
+static int sysv_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,get_block);
+}
+static int sysv_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,get_block);
+}
+struct address_space_operations sysv_aops = {
+	readpage: sysv_readpage,
+	writepage: sysv_writepage,
+	sync_page: block_sync_page,
+	prepare_write: sysv_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: sysv_bmap
+};
diff -urN linux-2.4.6-pre8/fs/sysv/namei.c linux/fs/sysv/namei.c
--- linux-2.4.6-pre8/fs/sysv/namei.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/sysv/namei.c	Mon Dec  3 22:50:39 2001
@@ -12,108 +12,70 @@
  *  Copyright (C) 1997, 1998  Krzysztof G. Baranowski
  */
 
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
+#include <linux/pagemap.h>
 
-/* compare strings: name[0..len-1] (not zero-terminated) and
- * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
- */
-static inline int namecompare(int len, int maxlen,
-	const char * name, const char * buffer)
+static inline void inc_count(struct inode *inode)
 {
-	if (len > maxlen)
-		return 0;
-	if (len < maxlen && buffer[len])
-		return 0;
-	return !memcmp(name, buffer, len);
+	inode->i_nlink++;
+	mark_inode_dirty(inode);
 }
 
-/*
- * ok, we cannot use strncmp, as the name is not in our data space. [Now it is!]
- * Thus we'll have to use sysv_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, sysv_match returns 1 for success, 0 for failure.
- */
-static int sysv_match(int len, const char * name, struct sysv_dir_entry * de)
+static inline void dec_count(struct inode *inode)
 {
-	if (!de->inode || len > SYSV_NAMELEN)
-		return 0;
-	/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
-	if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
-		return 1;
-	return namecompare(len, SYSV_NAMELEN, name, de->name);
+	inode->i_nlink--;
+	mark_inode_dirty(inode);
 }
 
-/*
- *	sysv_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_dir). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
- */
-static struct buffer_head * sysv_find_entry(struct inode * dir,
-	const char * name, int namelen, struct sysv_dir_entry ** res_dir)
+static int add_nondir(struct dentry *dentry, struct inode *inode)
 {
-	struct super_block * sb;
-	unsigned long pos, block, offset; /* pos = block * block_size + offset */
-	struct buffer_head * bh;
-
-	*res_dir = NULL;
-	sb = dir->i_sb;
-	if (namelen > SYSV_NAMELEN) {
-		if (sb->sv_truncate)
-			namelen = SYSV_NAMELEN;
-		else
-			return NULL;
-	}
-	bh = NULL;
-	pos = block = offset = 0;
-	while (pos < dir->i_size) {
-		if (!bh) {
-			bh = sysv_file_bread(dir, block, 0);
-			if (!bh) {
-				/* offset = 0; */ block++;
-				pos += sb->sv_block_size;
-				continue;
-			}
-		}
-		if (sysv_match(namelen, name,
-			       *res_dir = (struct sysv_dir_entry *) (bh->b_data + offset) ))
-			return bh;
-		pos += SYSV_DIRSIZE;
-		offset += SYSV_DIRSIZE;
-		if (offset < sb->sv_block_size)
-			continue;
-		brelse(bh);
-		bh = NULL;
-		offset = 0; block++;
+	int err = sysv_add_link(dentry, inode);
+	if (!err) {
+		d_instantiate(dentry, inode);
+		return 0;
 	}
-	brelse(bh);
-	*res_dir = NULL;
-	return NULL;
+	dec_count(inode);
+	iput(inode);
+	return err;
 }
 
+static int sysv_hash(struct dentry *dentry, struct qstr *qstr)
+{
+	unsigned long hash;
+	int i;
+	const unsigned char *name;
+
+	i = SYSV_NAMELEN;
+	if (i >= qstr->len)
+		return 0;
+	/* Truncate the name in place, avoids having to define a compare
+	   function. */
+	qstr->len = i;
+	name = qstr->name;
+	hash = init_name_hash();
+	while (i--)
+		hash = partial_name_hash(*name++, hash);
+	qstr->hash = end_name_hash(hash);
+	return 0;
+}
+
+struct dentry_operations sysv_dentry_operations = {
+	d_hash:		sysv_hash,
+};
+
 static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry)
 {
 	struct inode * inode = NULL;
-	struct sysv_dir_entry * de;
-	struct buffer_head * bh;
+	ino_t ino;
 
-	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+	dentry->d_op = dir->i_sb->s_root->d_op;
+	if (dentry->d_name.len > SYSV_NAMELEN)
+		return ERR_PTR(-ENAMETOOLONG);
+	ino = sysv_inode_by_name(dentry);
 
-	if (bh) {
-		int ino = de->inode;
-		brelse(bh);
+	if (ino) {
 		inode = iget(dir->i_sb, ino);
-	
 		if (!inode) 
 			return ERR_PTR(-EACCES);
 	}
@@ -121,399 +83,146 @@
 	return NULL;
 }
 
-/*
- *	sysv_add_entry()
- *
- * adds a file entry to the specified directory, returning a possible
- * error value if it fails.
- *
- * NOTE!! The inode part of 'de' is left at 0 - which means you
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
-static int sysv_add_entry(struct inode * dir,
-	const char * name, int namelen,
-	struct buffer_head ** res_buf,
-	struct sysv_dir_entry ** res_dir)
+static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
 {
-	struct super_block * sb;
-	int i;
-	unsigned long pos, block, offset; /* pos = block * block_size + offset */
-	struct buffer_head * bh;
-	struct sysv_dir_entry * de;
-
-	*res_buf = NULL;
-	*res_dir = NULL;
-	sb = dir->i_sb;
-	if (namelen > SYSV_NAMELEN) {
-		if (sb->sv_truncate)
-			namelen = SYSV_NAMELEN;
-		else
-			return -ENAMETOOLONG;
-	}
-	if (!namelen)
-		return -ENOENT;
-	bh = NULL;
-	pos = block = offset = 0;
-	while (1) {
-		if (!bh) {
-			bh = sysv_file_bread(dir, block, 1);
-			if (!bh)
-				return -ENOSPC;
-		}
-		de = (struct sysv_dir_entry *) (bh->b_data + offset);
-		pos += SYSV_DIRSIZE;
-		offset += SYSV_DIRSIZE;
-		if (pos > dir->i_size) {
-			de->inode = 0;
-			dir->i_size = pos;
-			mark_inode_dirty(dir);
-		}
-		if (de->inode) {
-			if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) {
-				brelse(bh);
-				return -EEXIST;
-			}
-		} else {
-			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-			mark_inode_dirty(dir);
-			for (i = 0; i < SYSV_NAMELEN ; i++)
-				de->name[i] = (i < namelen) ? name[i] : 0;
-			mark_buffer_dirty(bh);
-			*res_dir = de;
-			break;
-		}
-		if (offset < sb->sv_block_size)
-			continue;
-		brelse(bh);
-		bh = NULL;
-		offset = 0; block++;
-	}
-	*res_buf = bh;
-	return 0;
+	struct inode * inode = sysv_new_inode(dir, mode);
+	if (!inode)
+		return -ENOSPC;
+	sysv_set_inode(inode, rdev);
+	mark_inode_dirty(inode);
+	return add_nondir(dentry, inode);
 }
 
 static int sysv_create(struct inode * dir, struct dentry * dentry, int mode)
 {
-	int error;
-	struct inode * inode;
-	struct buffer_head * bh;
-	struct sysv_dir_entry * de;
-
-	inode = sysv_new_inode(dir);
-	if (!inode) 
-		return -ENOSPC;
-	inode->i_op = &sysv_file_inode_operations;
-	inode->i_fop = &sysv_file_operations;
-	inode->i_mapping->a_ops = &sysv_aops;
-	inode->i_mode = mode;
-	mark_inode_dirty(inode);
-	error = sysv_add_entry(dir, dentry->d_name.name,
-			       dentry->d_name.len, &bh, &de);
-	if (error) {
-		inode->i_nlink--;
-		mark_inode_dirty(inode);
-		iput(inode);
-		return error;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh);
-	brelse(bh);
-	d_instantiate(dentry, inode);
-	return 0;
+	return sysv_mknod(dir, dentry, mode, 0);
 }
 
-static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
+static int sysv_symlink(struct inode * dir, struct dentry * dentry, 
+	const char * symname)
 {
-	int error;
+	int err = -ENAMETOOLONG;
+	int l = strlen(symname)+1;
 	struct inode * inode;
-	struct buffer_head * bh;
-	struct sysv_dir_entry * de;
 
-	bh = sysv_find_entry(dir, dentry->d_name.name,
-			     dentry->d_name.len, &de);
-	if (bh) {
-		brelse(bh);
-		return -EEXIST;
-	}
-	inode = sysv_new_inode(dir);
+	if (l > dir->i_sb->s_blocksize)
+		goto out;
+
+	err = -ENOSPC;
+	inode = sysv_new_inode(dir, S_IFLNK|0777);
 	if (!inode)
-		return -ENOSPC;
-	inode->i_uid = current->fsuid;
-	init_special_inode(inode, mode, rdev);
-	mark_inode_dirty(inode);
-	error = sysv_add_entry(dir, dentry->d_name.name, 
-			       dentry->d_name.len, &bh, &de);
-	if (error) {
-		inode->i_nlink--;
-		mark_inode_dirty(inode);
-		iput(inode);
-		return error;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh);
-	brelse(bh);
-	d_instantiate(dentry, inode);
-	return 0;
+		goto out;
+
+	sysv_set_inode(inode, 0);
+	err = block_symlink(inode, symname, l);
+	if (err)
+		goto out_fail;
+
+	err = add_nondir(dentry, inode);
+out:
+	return err;
+
+out_fail:
+	dec_count(inode);
+	iput(inode);
+	goto out;
 }
 
-static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode)
+static int sysv_link(struct dentry * old_dentry, struct inode * dir, 
+	struct dentry * dentry)
 {
-	int error;
-	struct inode * inode;
-	struct buffer_head * bh, *dir_block;
-	struct sysv_dir_entry * de;
+	struct inode *inode = old_dentry->d_inode;
 
-	bh = sysv_find_entry(dir, dentry->d_name.name,
-                              dentry->d_name.len, &de);
-	if (bh) {
-		brelse(bh);
-		return -EEXIST;
-	}
-	if (dir->i_nlink >= dir->i_sb->sv_link_max) 
+	if (S_ISDIR(inode->i_mode))
+		return -EPERM;
+
+	if (inode->i_nlink >= inode->i_sb->sv_link_max)
 		return -EMLINK;
-	inode = sysv_new_inode(dir);
-	if (!inode)
-		return -ENOSPC;
-	inode->i_op = &sysv_dir_inode_operations;
-	inode->i_fop = &sysv_dir_operations;
-	inode->i_size = 2 * SYSV_DIRSIZE;
-	dir_block = sysv_file_bread(inode,0,1);
-	if (!dir_block) {
-		inode->i_nlink--;
-		mark_inode_dirty(inode);
-		iput(inode);
-		return -ENOSPC;
-	}
-	de = (struct sysv_dir_entry *) (dir_block->b_data + 0*SYSV_DIRSIZE);
-	de->inode = inode->i_ino;
-	strcpy(de->name,"."); /* rest of de->name is zero, see sysv_new_block */
-	de = (struct sysv_dir_entry *) (dir_block->b_data + 1*SYSV_DIRSIZE);
-	de->inode = dir->i_ino;
-	strcpy(de->name,".."); /* rest of de->name is zero, see sysv_new_block */
-	inode->i_nlink = 2;
-	mark_buffer_dirty(dir_block);
-	brelse(dir_block);
-	inode->i_mode = S_IFDIR | mode;
-	if (dir->i_mode & S_ISGID)
-		inode->i_mode |= S_ISGID;
-	mark_inode_dirty(inode);
-	error = sysv_add_entry(dir, dentry->d_name.name,
-                               dentry->d_name.len, &bh, &de);
- 	if (error) {
-		inode->i_nlink=0;
-		iput(inode);
-		return error;
-	}
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh);
-	dir->i_nlink++;
-	mark_inode_dirty(dir);
-	brelse(bh);
-        d_instantiate(dentry, inode);
- 	return 0;
-}
 
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-static int empty_dir(struct inode * inode)
-{
-	struct super_block * sb;
-	unsigned long pos, block, offset; /* pos = block * block_size + offset */
-	struct buffer_head * bh;
-	struct sysv_dir_entry * de;
+	inode->i_ctime = CURRENT_TIME;
+	inc_count(inode);
+	atomic_inc(&inode->i_count);
 
-	block = 0;
-	bh = NULL;
-	pos = offset = 2*SYSV_DIRSIZE;
-	if ((unsigned long)(inode->i_size) % SYSV_DIRSIZE)
-		goto bad_dir;
-	if (inode->i_size < pos)
-		goto bad_dir;
-	bh = sysv_file_bread(inode, 0, 0);
-	if (!bh)
-		goto bad_dir;
-	de = (struct sysv_dir_entry *) (bh->b_data + 0*SYSV_DIRSIZE);
-	if (!de->inode || strcmp(de->name,"."))
-		goto bad_dir;
-	de = (struct sysv_dir_entry *) (bh->b_data + 1*SYSV_DIRSIZE);
-	if (!de->inode || strcmp(de->name,".."))
-		goto bad_dir;
-	sb = inode->i_sb;
-	while (pos < inode->i_size) {
-		if (!bh) {
-			bh = sysv_file_bread(inode, block, 0);
-			if (!bh) {
-				/* offset = 0; */ block++;
-				pos += sb->sv_block_size;
-				continue;
-			}
-		}
-		de = (struct sysv_dir_entry *) (bh->b_data + offset);
-		pos += SYSV_DIRSIZE;
-		offset += SYSV_DIRSIZE;
-		if (de->inode) {
-			brelse(bh);
-			return 0;
-		}
-		if (offset < sb->sv_block_size)
-			continue;
-		brelse(bh);
-		bh = NULL;
-		offset = 0; block++;
-	}
-	brelse(bh);
-	return 1;
-bad_dir:
-	brelse(bh);
-	printk("Bad directory on device %s\n",
-	       kdevname(inode->i_dev));
-	return 1;
+	return add_nondir(dentry, inode);
 }
 
-static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
+static int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode)
 {
-	int retval;
 	struct inode * inode;
-	struct buffer_head * bh;
-	struct sysv_dir_entry * de;
+	int err = -EMLINK;
 
-	inode = dentry->d_inode;
-	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
-	retval = -ENOENT;
-	if (!bh || de->inode != inode->i_ino)
-		goto end_rmdir;
-
-	if (!empty_dir(inode)) {
-		retval = -ENOTEMPTY;
-		goto end_rmdir;
-	}
-	if (inode->i_nlink != 2)
-		printk("empty directory has nlink!=2 (%d)\n", inode->i_nlink);
-	de->inode = 0;
-	mark_buffer_dirty(bh);
-	inode->i_nlink=0;
-	dir->i_nlink--;
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(inode);
-	mark_inode_dirty(dir);
-	retval = 0;
-end_rmdir:
-	brelse(bh);
-	return retval;
-}
+	if (dir->i_nlink >= dir->i_sb->sv_link_max) 
+		goto out;
 
-static int sysv_unlink(struct inode * dir, struct dentry * dentry)
-{
-	int retval;
-	struct inode * inode;
-	struct buffer_head * bh;
-	struct sysv_dir_entry * de;
+	inc_count(dir);
 
-	retval = -ENOENT;
-	inode = dentry->d_inode;
-	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
-	if (!bh || de->inode != inode->i_ino)
-		goto end_unlink;
-	if (!inode->i_nlink) {
-		printk("Deleting nonexistent file (%s:%lu), %d\n",
-		        kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
-		inode->i_nlink=1;
-	}
-	de->inode = 0;
-	mark_buffer_dirty(bh);
-	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(dir);
-	inode->i_nlink--;
-	inode->i_ctime = dir->i_ctime;
-	mark_inode_dirty(inode);
-	retval = 0;
-end_unlink:
-	brelse(bh);
-	return retval;
-}
+	if (dir->i_mode & S_ISGID)
+		mode |= S_ISGID;
 
-static int sysv_symlink(struct inode * dir, struct dentry * dentry, 
-		 const char * symname)
-{
-	struct inode * inode;
-	struct sysv_dir_entry * de;
-	struct buffer_head * bh;
-	int err;
-	int l;
-
-	err = -ENAMETOOLONG;
-	l = strlen(symname)+1;
-	if (l > dir->i_sb->sv_block_size_1)
-		goto out;
 	err = -ENOSPC;
-	if (!(inode = sysv_new_inode(dir)))
-		goto out;
+	inode = sysv_new_inode(dir, S_IFDIR|mode);
+	if (!inode)
+		goto out_dir;
+	sysv_set_inode(inode, 0);
 
-	inode->i_mode = S_IFLNK | 0777;
-	inode->i_op = &sysv_symlink_inode_operations;
-	inode->i_mapping->a_ops = &sysv_aops;
-	err = block_symlink(inode, symname, l);
+	inc_count(inode);
+
+	err = sysv_make_empty(inode, dir);
 	if (err)
-		goto out_no_entry;
-	mark_inode_dirty(inode);
-	err = sysv_add_entry(dir, dentry->d_name.name,
-                           dentry->d_name.len, &bh, &de);
+		goto out_fail;
+
+	err = sysv_add_link(dentry, inode);
 	if (err)
-		goto out_no_entry;
-	de->inode = inode->i_ino;
-	mark_buffer_dirty(bh);
-	brelse(bh);
+		goto out_fail;
+
         d_instantiate(dentry, inode);
 out:
 	return err;
-out_no_entry:
-	inode->i_nlink--;
-	mark_inode_dirty(inode);
+
+out_fail:
+	dec_count(inode);
+	dec_count(inode);
 	iput(inode);
+out_dir:
+	dec_count(dir);
 	goto out;
 }
 
-static int sysv_link(struct dentry * old_dentry, struct inode * dir, 
-	      struct dentry * dentry)
+static int sysv_unlink(struct inode * dir, struct dentry * dentry)
 {
-	struct inode *oldinode = old_dentry->d_inode;
-	int error;
+	struct inode * inode = dentry->d_inode;
+	struct page * page;
 	struct sysv_dir_entry * de;
-	struct buffer_head * bh;
+	int err = -ENOENT;
 
-	if (S_ISDIR(oldinode->i_mode)) {
-		return -EPERM;
-	}
-	if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) {
-		return -EMLINK;
-	}
-	bh = sysv_find_entry(dir, dentry->d_name.name,
-                             dentry->d_name.len, &de);
-	if (bh) {
-		brelse(bh);
-		return -EEXIST;
-	}
-	error = sysv_add_entry(dir, dentry->d_name.name,
-                               dentry->d_name.len, &bh, &de);
-	if (error) {
-		brelse(bh);
-		return error;
-	}
-	de->inode = oldinode->i_ino;
-	mark_buffer_dirty(bh);
-	brelse(bh);
-	oldinode->i_nlink++;
-	oldinode->i_ctime = CURRENT_TIME;
-	mark_inode_dirty(oldinode);
-	atomic_inc(&oldinode->i_count);
-        d_instantiate(dentry, oldinode);
-	return 0;
+	de = sysv_find_entry(dentry, &page);
+	if (!de)
+		goto out;
+
+	err = sysv_delete_entry (de, page);
+	if (err)
+		goto out;
+
+	inode->i_ctime = dir->i_ctime;
+	dec_count(inode);
+out:
+	return err;
 }
 
-#define PARENT_INO(buffer) \
-(((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode)
+static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	int err = -ENOTEMPTY;
+
+	if (sysv_empty_dir(inode)) {
+		err = sysv_unlink(dir, dentry);
+		if (!err) {
+			dec_count(inode);
+			dec_count(dir);
+		}
+	}
+	return err;
+}
 
 /*
  * Anybody can rename anything with this: the permission checks are left to the
@@ -522,83 +231,78 @@
 static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
 		  struct inode * new_dir, struct dentry * new_dentry)
 {
-	struct inode * old_inode, * new_inode;
-	struct buffer_head * old_bh, * new_bh, * dir_bh;
-	struct sysv_dir_entry * old_de, * new_de;
-	int retval;
-
-	old_inode = old_dentry->d_inode;
-	new_inode = new_dentry->d_inode;
-	new_bh = dir_bh = NULL;
-	old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name,
-				old_dentry->d_name.len, &old_de);
-	retval = -ENOENT;
-	if (!old_bh || old_de->inode != old_inode->i_ino)
-		goto end_rename;
-	retval = -EPERM;
-	new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name,
-				new_dentry->d_name.len, &new_de);
-	if (new_bh) {
-		if (!new_inode) {
-			brelse(new_bh);
-			new_bh = NULL;
-		}
-	}
+	struct inode * old_inode = old_dentry->d_inode;
+	struct inode * new_inode = new_dentry->d_inode;
+	struct page * dir_page = NULL;
+	struct sysv_dir_entry * dir_de = NULL;
+	struct page * old_page;
+	struct sysv_dir_entry * old_de;
+	int err = -ENOENT;
+
+	old_de = sysv_find_entry(old_dentry, &old_page);
+	if (!old_de)
+		goto out;
+
 	if (S_ISDIR(old_inode->i_mode)) {
-		if (new_inode) {
-			retval = -ENOTEMPTY;
-			if (!empty_dir(new_inode))
-				goto end_rename;
-		}
-		retval = -EIO;
-		dir_bh = sysv_file_bread(old_inode, 0, 0);
-		if (!dir_bh)
-			goto end_rename;
-		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
-			goto end_rename;
-		retval = -EMLINK;
-		if (!new_inode && new_dir != old_dir &&
-				new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
-			goto end_rename;
+		err = -EIO;
+		dir_de = sysv_dotdot(old_inode, &dir_page);
+		if (!dir_de)
+			goto out_old;
 	}
-	if (!new_bh) {
-		retval = sysv_add_entry(new_dir, new_dentry->d_name.name,
-					new_dentry->d_name.len, &new_bh, &new_de);
-		if (retval)
-			goto end_rename;
-	}
-	new_de->inode = old_inode->i_ino;
-	old_de->inode = 0;
-	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(old_dir);
-	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(new_dir);
+
 	if (new_inode) {
-		new_inode->i_nlink--;
+		struct page * new_page;
+		struct sysv_dir_entry * new_de;
+
+		err = -ENOTEMPTY;
+		if (dir_de && !sysv_empty_dir(new_inode))
+			goto out_dir;
+
+		err = -ENOENT;
+		new_de = sysv_find_entry(new_dentry, &new_page);
+		if (!new_de)
+			goto out_dir;
+		inc_count(old_inode);
+		sysv_set_link(new_de, new_page, old_inode);
 		new_inode->i_ctime = CURRENT_TIME;
-		mark_inode_dirty(new_inode);
-	}
-	mark_buffer_dirty(old_bh);
-	mark_buffer_dirty(new_bh);
-	if (dir_bh) {
-		PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
-		mark_buffer_dirty(dir_bh);
-		old_dir->i_nlink--;
-		mark_inode_dirty(old_dir);
-		if (new_inode) {
+		if (dir_de)
 			new_inode->i_nlink--;
-			mark_inode_dirty(new_inode);
-		} else {
-			new_dir->i_nlink++;
-			mark_inode_dirty(new_dir);
+		dec_count(new_inode);
+	} else {
+		if (dir_de) {
+			err = -EMLINK;
+			if (new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
+				goto out_dir;
+		}
+		inc_count(old_inode);
+		err = sysv_add_link(new_dentry, old_inode);
+		if (err) {
+			dec_count(old_inode);
+			goto out_dir;
 		}
+		if (dir_de)
+			inc_count(new_dir);
+	}
+
+	sysv_delete_entry(old_de, old_page);
+	dec_count(old_inode);
+
+	if (dir_de) {
+		sysv_set_link(dir_de, dir_page, new_dir);
+		dec_count(old_dir);
 	}
-	retval = 0;
-end_rename:
-	brelse(dir_bh);
-	brelse(old_bh);
-	brelse(new_bh);
-	return retval;
+	return 0;
+
+out_dir:
+	if (dir_de) {
+		kunmap(dir_page);
+		page_cache_release(dir_page);
+	}
+out_old:
+	kunmap(old_page);
+	page_cache_release(old_page);
+out:
+	return err;
 }
 
 /*
diff -urN linux-2.4.6-pre8/fs/sysv/super.c linux/fs/sysv/super.c
--- linux-2.4.6-pre8/fs/sysv/super.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/sysv/super.c	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,467 @@
+/*
+ *  linux/fs/sysv/inode.c
+ *
+ *  minix/inode.c
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  xenix/inode.c
+ *  Copyright (C) 1992  Doug Evans
+ *
+ *  coh/inode.c
+ *  Copyright (C) 1993  Pascal Haible, Bruno Haible
+ *
+ *  sysv/inode.c
+ *  Copyright (C) 1993  Paul B. Monday
+ *
+ *  sysv/inode.c
+ *  Copyright (C) 1993  Bruno Haible
+ *  Copyright (C) 1997, 1998  Krzysztof G. Baranowski
+ *
+ *  This file contains code for read/parsing the superblock.
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/sysv_fs.h>
+#include <linux/init.h>
+
+/* The following functions try to recognize specific filesystems.
+ * We recognize:
+ * - Xenix FS by its magic number.
+ * - SystemV FS by its magic number.
+ * - Coherent FS by its funny fname/fpack field.
+ * We discriminate among SystemV4 and SystemV2 FS by the assumption that
+ * the time stamp is not < 01-01-1980.
+ */
+
+enum {
+	JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60
+};
+
+static void detected_xenix(struct super_block *sb)
+{
+	struct buffer_head *bh1 = sb->sv_bh1;
+	struct buffer_head *bh2 = sb->sv_bh2;
+	struct xenix_super_block * sbd1;
+	struct xenix_super_block * sbd2;
+
+	if (bh1 != bh2)
+		sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data;
+	else {
+		/* block size = 512, so bh1 != bh2 */
+		sbd1 = (struct xenix_super_block *) bh1->b_data;
+		sbd2 = (struct xenix_super_block *) (bh2->b_data - 512);
+	}
+
+	sb->sv_link_max = XENIX_LINK_MAX;
+	sb->sv_fic_size = XENIX_NICINOD;
+	sb->sv_flc_size = XENIX_NICFREE;
+	sb->sv_sbd1 = (char *) sbd1;
+	sb->sv_sbd2 = (char *) sbd2;
+	sb->sv_sb_fic_count = &sbd1->s_ninode;
+	sb->sv_sb_fic_inodes = &sbd1->s_inode[0];
+	sb->sv_sb_total_free_inodes = &sbd2->s_tinode;
+	sb->sv_bcache_count = &sbd1->s_nfree;
+	sb->sv_bcache = &sbd1->s_free[0];
+	sb->sv_free_blocks = &sbd2->s_tfree;
+	sb->sv_sb_time = &sbd2->s_time;
+	sb->sv_firstdatazone = fs16_to_cpu(sb, sbd1->s_isize);
+	sb->sv_nzones = fs32_to_cpu(sb, sbd1->s_fsize);
+}
+
+static void detected_sysv4(struct super_block *sb)
+{
+	struct sysv4_super_block * sbd;
+	struct buffer_head *bh1 = sb->sv_bh1;
+	struct buffer_head *bh2 = sb->sv_bh2;
+
+	if (bh1 == bh2)
+		sbd = (struct sysv4_super_block *) (bh1->b_data + BLOCK_SIZE/2);
+	else
+		sbd = (struct sysv4_super_block *) bh2->b_data;
+
+	sb->sv_link_max = SYSV_LINK_MAX;
+	sb->sv_fic_size = SYSV_NICINOD;
+	sb->sv_flc_size = SYSV_NICFREE;
+	sb->sv_sbd1 = (char *) sbd;
+	sb->sv_sbd2 = (char *) sbd;
+	sb->sv_sb_fic_count = &sbd->s_ninode;
+	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
+	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
+	sb->sv_bcache_count = &sbd->s_nfree;
+	sb->sv_bcache = &sbd->s_free[0];
+	sb->sv_free_blocks = &sbd->s_tfree;
+	sb->sv_sb_time = &sbd->s_time;
+	sb->sv_sb_state = &sbd->s_state;
+	sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize);
+	sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize);
+}
+
+static void detected_sysv2(struct super_block *sb)
+{
+	struct sysv2_super_block * sbd;
+	struct buffer_head *bh1 = sb->sv_bh1;
+	struct buffer_head *bh2 = sb->sv_bh2;
+
+	if (bh1 == bh2)
+		sbd = (struct sysv2_super_block *) (bh1->b_data + BLOCK_SIZE/2);
+	else
+		sbd = (struct sysv2_super_block *) bh2->b_data;
+
+	sb->sv_link_max = SYSV_LINK_MAX;
+	sb->sv_fic_size = SYSV_NICINOD;
+	sb->sv_flc_size = SYSV_NICFREE;
+	sb->sv_sbd1 = (char *) sbd;
+	sb->sv_sbd2 = (char *) sbd;
+	sb->sv_sb_fic_count = &sbd->s_ninode;
+	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
+	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
+	sb->sv_bcache_count = &sbd->s_nfree;
+	sb->sv_bcache = &sbd->s_free[0];
+	sb->sv_free_blocks = &sbd->s_tfree;
+	sb->sv_sb_time = &sbd->s_time;
+	sb->sv_sb_state = &sbd->s_state;
+	sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize);
+	sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize);
+}
+
+static void detected_coherent(struct super_block *sb)
+{
+	struct coh_super_block * sbd;
+	struct buffer_head *bh1 = sb->sv_bh1;
+
+	sbd = (struct coh_super_block *) bh1->b_data;
+
+	sb->sv_link_max = COH_LINK_MAX;
+	sb->sv_fic_size = COH_NICINOD;
+	sb->sv_flc_size = COH_NICFREE;
+	sb->sv_sbd1 = (char *) sbd;
+	sb->sv_sbd2 = (char *) sbd;
+	sb->sv_sb_fic_count = &sbd->s_ninode;
+	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
+	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
+	sb->sv_bcache_count = &sbd->s_nfree;
+	sb->sv_bcache = &sbd->s_free[0];
+	sb->sv_free_blocks = &sbd->s_tfree;
+	sb->sv_sb_time = &sbd->s_time;
+	sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize);
+	sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize);
+}
+
+static void detected_v7(struct super_block *sb)
+{
+	struct buffer_head *bh2 = sb->sv_bh2;
+	struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data;
+
+	sb->sv_link_max = V7_LINK_MAX;
+	sb->sv_fic_size = V7_NICINOD;
+	sb->sv_flc_size = V7_NICFREE;
+	sb->sv_sbd1 = (char *)sbd;
+	sb->sv_sbd2 = (char *)sbd;
+	sb->sv_sb_fic_count = &sbd->s_ninode;
+	sb->sv_sb_fic_inodes = &sbd->s_inode[0];
+	sb->sv_sb_total_free_inodes = &sbd->s_tinode;
+	sb->sv_bcache_count = &sbd->s_nfree;
+	sb->sv_bcache = &sbd->s_free[0];
+	sb->sv_free_blocks = &sbd->s_tfree;
+	sb->sv_sb_time = &sbd->s_time;
+	sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize);
+	sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize);
+}
+
+static int detect_xenix (struct super_block *sb, struct buffer_head *bh)
+{
+	struct xenix_super_block * sbd = (struct xenix_super_block *)bh->b_data;
+	if (sbd->s_magic == cpu_to_le32(0x2b5544))
+		sb->sv_bytesex = BYTESEX_LE;
+	else if (sbd->s_magic == cpu_to_be32(0x2b5544))
+		sb->sv_bytesex = BYTESEX_BE;
+	else
+		return 0;
+	if (sbd->s_type > 2 || sbd->s_type < 1)
+		return 0;
+	sb->sv_type = FSTYPE_XENIX;
+	return sbd->s_type;
+}
+
+static int detect_sysv (struct super_block *sb, struct buffer_head *bh)
+{
+	/* All relevant fields are at the same offsets in R2 and R4 */
+	struct sysv4_super_block * sbd;
+
+	sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
+	if (sbd->s_magic == cpu_to_le32(0xfd187e20))
+		sb->sv_bytesex = BYTESEX_LE;
+	else if (sbd->s_magic == cpu_to_be32(0xfd187e20))
+		sb->sv_bytesex = BYTESEX_BE;
+	else
+		return 0;
+	if (sbd->s_time < JAN_1_1980) {
+		/* this is likely to happen on SystemV2 FS */
+		if (sbd->s_type > 3 || sbd->s_type < 1)
+			return 0;
+		sb->sv_type = FSTYPE_SYSV2;
+		return sbd->s_type;
+	}
+	if ((sbd->s_type > 3 || sbd->s_type < 1) &&
+	    (sbd->s_type > 0x30 || sbd->s_type < 0x10))
+		return 0;
+
+	/* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10,
+	   0x20 or 0x30 indicates that symbolic links and the 14-character
+	   filename limit is gone. Due to lack of information about this
+           feature read-only mode seems to be a reasonable approach... -KGB */
+
+	if (sbd->s_type >= 0x10) {
+		printk("SysV FS: can't handle long file names on %s, "
+		       "forcing read-only mode.\n", kdevname(sb->s_dev));
+		sb->s_flags |= MS_RDONLY;
+	}
+
+	sb->sv_type = FSTYPE_SYSV4;
+	return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type;
+}
+
+static int detect_coherent (struct super_block *sb, struct buffer_head *bh)
+{
+	struct coh_super_block * sbd;
+
+	sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2);
+	if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6))
+	    || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6)))
+		return 0;
+	sb->sv_bytesex = BYTESEX_PDP;
+	sb->sv_type = FSTYPE_COH;
+	return 1;
+}
+
+static int detect_sysv_odd(struct super_block *sb, struct buffer_head *bh)
+{
+	int size = detect_sysv(sb, bh);
+
+	return size>2 ? 0 : size;
+}
+
+static struct {
+	int block;
+	int (*test)(struct super_block *, struct buffer_head *);
+} flavours[] = {
+	{1, detect_xenix},
+	{0, detect_sysv},
+	{0, detect_coherent},
+	{9, detect_sysv_odd},
+	{15,detect_sysv_odd},
+	{18,detect_sysv},
+};
+
+static char *flavour_names[] = {
+	[FSTYPE_XENIX]	"Xenix",
+	[FSTYPE_SYSV4]	"SystemV",
+	[FSTYPE_SYSV2]	"SystemV Release 2",
+	[FSTYPE_COH]	"Coherent",
+	[FSTYPE_V7]	"V7",
+};
+
+static void (*flavour_setup[])(struct super_block *) = {
+	[FSTYPE_XENIX]	detected_xenix,
+	[FSTYPE_SYSV4]	detected_sysv4,
+	[FSTYPE_SYSV2]	detected_sysv2,
+	[FSTYPE_COH]	detected_coherent,
+	[FSTYPE_V7]	detected_v7,
+};
+
+static int complete_read_super(struct super_block *sb, int silent, int size)
+{
+	struct inode *root_inode;
+	char *found = flavour_names[sb->sv_type];
+	u_char n_bits = size+8;
+	int bsize = 1 << n_bits;
+	int bsize_4 = bsize >> 2;
+
+	sb->sv_kludge_symlinks = 1;
+	sb->sv_firstinodezone = 2;
+
+	flavour_setup[sb->sv_type](sb);
+	
+	sb->sv_truncate = 1;
+	sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone;
+	sb->sv_inodes_per_block = bsize >> 6;
+	sb->sv_inodes_per_block_1 = (bsize >> 6)-1;
+	sb->sv_inodes_per_block_bits = n_bits-6;
+	sb->sv_ind_per_block = bsize_4;
+	sb->sv_ind_per_block_2 = bsize_4*bsize_4;
+	sb->sv_toobig_block = 10 + bsize_4 * (1 + bsize_4 * (1 + bsize_4));
+	sb->sv_ind_per_block_bits = n_bits-2;
+
+	sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits;
+
+	sb->s_blocksize = bsize;
+	sb->s_blocksize_bits = n_bits;
+	if (!silent)
+		printk("VFS: Found a %s FS (block size = %ld) on device %s\n",
+		       found, sb->s_blocksize, bdevname(sb->s_dev));
+
+	sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type;
+	/* set up enough so that it can read an inode */
+	sb->s_op = &sysv_sops;
+	root_inode = iget(sb,SYSV_ROOT_INO);
+	if (!root_inode) {
+		printk("SysV FS: get root inode failed\n");
+		return 0;
+	}
+	sb->s_root = d_alloc_root(root_inode);
+	if (!sb->s_root) {
+		iput(root_inode);
+		printk("SysV FS: get root dentry failed\n");
+		return 0;
+	}
+	if (sb->sv_truncate)
+		sb->s_root->d_op = &sysv_dentry_operations;
+	sb->s_flags |= MS_RDONLY;
+	sb->s_dirt = 1;
+	return 1;
+}
+
+static struct super_block *sysv_read_super(struct super_block *sb,
+					   void *data, int silent)
+{
+	struct buffer_head *bh1;
+	struct buffer_head *bh = NULL;
+	kdev_t dev = sb->s_dev;
+	unsigned long blocknr;
+	int size = 0;
+	int i;
+	
+	if (1024 != sizeof (struct xenix_super_block))
+		panic("Xenix FS: bad super-block size");
+	if ((512 != sizeof (struct sysv4_super_block))
+            || (512 != sizeof (struct sysv2_super_block)))
+		panic("SystemV FS: bad super-block size");
+	if (500 != sizeof (struct coh_super_block))
+		panic("Coherent FS: bad super-block size");
+	if (64 != sizeof (struct sysv_inode))
+		panic("sysv fs: bad i-node size");
+	set_blocksize(dev,BLOCK_SIZE);
+	sb->sv_block_base = 0;
+
+	for (i = 0; i < sizeof(flavours)/sizeof(flavours[0]) && !size; i++) {
+		struct buffer_head *next_bh;
+		next_bh = bread(dev, flavours[i].block, BLOCK_SIZE);
+		if (!next_bh)
+			continue;
+		brelse(bh);
+		bh = next_bh;
+
+		size = flavours[i].test(sb, bh);
+	}
+
+	if (!size)
+		goto Eunknown;
+
+	switch (size) {
+		case 1:
+			blocknr = bh->b_blocknr << 1;
+			brelse(bh);
+			set_blocksize(dev, 512);
+			bh1 = bread(dev, blocknr, 512);
+			bh = bread(dev, blocknr + 1, 512);
+			break;
+		case 2:
+			bh1 = bh;
+			break;
+		case 3:
+			blocknr = bh->b_blocknr >> 1;
+			brelse(bh);
+			set_blocksize(dev, 2048);
+			bh1 = bh = bread(dev, blocknr, 2048);
+			break;
+		default:
+			goto Ebadsize;
+	}
+
+	if (bh && bh1) {
+		sb->sv_bh1 = bh1;
+		sb->sv_bh2 = bh;
+		if (complete_read_super(sb, silent, size))
+			return sb;
+	}
+
+	brelse(bh1);
+	brelse(bh);
+	set_blocksize(sb->s_dev,BLOCK_SIZE);
+	printk("oldfs: cannot read superblock\n");
+failed:
+	return NULL;
+
+Eunknown:
+	brelse(bh);
+	if (!silent)
+		printk("VFS: unable to find oldfs superblock on device %s\n",
+			bdevname(dev));
+	goto failed;
+Ebadsize:
+	brelse(bh);
+	if (!silent)
+		printk("VFS: oldfs: unsupported block size (%dKb)\n",
+			1<<(size-2));
+	goto failed;
+}
+
+static struct super_block *v7_read_super(struct super_block *sb,void *data,
+				  int silent)
+{
+	struct buffer_head *bh;
+	kdev_t dev = sb->s_dev;
+
+	if (440 != sizeof (struct v7_super_block))
+		panic("V7 FS: bad super-block size");
+	if (64 != sizeof (struct sysv_inode))
+		panic("sysv fs: bad i-node size");
+
+	sb->sv_type = FSTYPE_V7;
+	sb->sv_bytesex = BYTESEX_PDP;
+
+	set_blocksize(dev,512);
+
+	if ((bh = bread(dev, 1, 512)) == NULL) {
+		if (!silent)
+			printk("VFS: unable to read V7 FS superblock on device "
+			       "%s.\n", bdevname(dev));
+		goto failed;
+	}
+
+
+	sb->sv_bh1 = bh;
+	sb->sv_bh2 = bh;
+	if (complete_read_super(sb, silent, 1))
+		return sb;
+
+	brelse(bh);
+failed:
+	return NULL;
+}
+
+/* Every kernel module contains stuff like this. */
+
+static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
+static DECLARE_FSTYPE_DEV(v7_fs_type, "v7", v7_read_super);
+
+static int __init init_sysv_fs(void)
+{
+	int err = register_filesystem(&sysv_fs_type);
+	if (!err)
+		err = register_filesystem(&v7_fs_type);
+	return err;
+}
+
+static void __exit exit_sysv_fs(void)
+{
+	unregister_filesystem(&sysv_fs_type);
+	unregister_filesystem(&v7_fs_type);
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_sysv_fs)
+module_exit(exit_sysv_fs)
diff -urN linux-2.4.6-pre8/fs/sysv/truncate.c linux/fs/sysv/truncate.c
--- linux-2.4.6-pre8/fs/sysv/truncate.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/sysv/truncate.c	Wed Dec 31 16:00:00 1969
@@ -1,293 +0,0 @@
-/*
- *  linux/fs/sysv/truncate.c
- *
- *  minix/truncate.c
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  coh/truncate.c
- *  Copyright (C) 1993  Pascal Haible, Bruno Haible
- *
- *  sysv/truncate.c
- *  Copyright (C) 1993  Bruno Haible
- */
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/sysv_fs.h>
-#include <linux/stat.h>
-
-
-/* Linus' implementation of truncate.
- * It doesn't need locking because it can tell from looking at bh->b_count
- * whether a given block is in use elsewhere.
- */
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**, especially as I don't do any locking.
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-#define DATA_BUFFER_USED(bh) \
-	(atomic_read(&bh->b_count)>1 || buffer_locked(bh))
-
-/* We throw away any data beyond inode->i_size. */
-
-static int trunc_direct(struct inode * inode)
-{
-	struct super_block * sb;
-	unsigned int i;
-	u32 * p;
-	u32 block;
-	struct buffer_head * bh;
-	int retry = 0;
-
-	sb = inode->i_sb;
-repeat:
-	for (i = ((unsigned long) inode->i_size + sb->sv_block_size_1) >> sb->sv_block_size_bits; i < 10; i++) {
-		p = inode->u.sysv_i.i_data + i;
-		block = *p;
-		if (!block)
-			continue;
-		bh = sv_get_hash_table(sb, inode->i_dev, block);
-		if ((i << sb->sv_block_size_bits) < inode->i_size) {
-			brelse(bh);
-			goto repeat;
-		}
-		if ((bh && DATA_BUFFER_USED(bh)) || (block != *p)) {
-			retry = 1;
-			brelse(bh);
-			continue;
-		}
-		*p = 0;
-		mark_inode_dirty(inode);
-		brelse(bh);
-		sysv_free_block(sb,block);
-	}
-	return retry;
-}
-
-static int trunc_indirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt)
-{
-	unsigned long indtmp, indblock;
-	struct super_block * sb;
-	struct buffer_head * indbh;
-	unsigned int i;
-	sysv_zone_t * ind;
-	unsigned long tmp, block;
-	struct buffer_head * bh;
-	int retry = 0;
-
-	indblock = indtmp = *p;
-	if (convert)
-		indblock = from_coh_ulong(indblock);
-	if (!indblock)
-		return 0;
-	sb = inode->i_sb;
-	indbh = sv_bread(sb, inode->i_dev, indblock);
-	if (indtmp != *p) {
-		brelse(indbh);
-		return 1;
-	}
-	if (!indbh) {
-		*p = 0;
-		*dirt = 1;
-		return 0;
-	}
-repeat:
-	if (inode->i_size < offset)
-		i = 0;
-	else
-		i = (inode->i_size - offset + sb->sv_block_size_1) >> sb->sv_block_size_bits;
-	for (; i < sb->sv_ind_per_block; i++) {
-		ind = ((sysv_zone_t *) indbh->b_data) + i;
-		block = tmp = *ind;
-		if (sb->sv_convert)
-			block = from_coh_ulong(block);
-		if (!block)
-			continue;
-		bh = sv_get_hash_table(sb, inode->i_dev, block);
-		if ((i << sb->sv_block_size_bits) + offset < inode->i_size) {
-			brelse(bh);
-			goto repeat;
-		}
-		if ((bh && DATA_BUFFER_USED(bh)) || (tmp != *ind)) {
-			retry = 1;
-			brelse(bh);
-			continue;
-		}
-		*ind = 0;
-		mark_buffer_dirty(indbh);
-		brelse(bh);
-		sysv_free_block(sb,block);
-	}
-	for (i = 0; i < sb->sv_ind_per_block; i++)
-		if (((sysv_zone_t *) indbh->b_data)[i])
-			goto done;
-	if (DATA_BUFFER_USED(indbh) || (indtmp != *p)) {
-		brelse(indbh);
-		return 1;
-	}
-	*p = 0;
-	*dirt = 1;
-	sysv_free_block(sb,indblock);
-done:
-	brelse(indbh);
-	return retry;
-}
-
-static int trunc_dindirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt)
-{
-	u32 indtmp, indblock;
-	struct super_block * sb;
-	struct buffer_head * indbh;
-	unsigned int i;
-	sysv_zone_t * ind;
-	u32 tmp, block;
-	int retry = 0;
-
-	indblock = indtmp = *p;
-	if (convert)
-		indblock = from_coh_ulong(indblock);
-	if (!indblock)
-		return 0;
-	sb = inode->i_sb;
-	indbh = sv_bread(sb, inode->i_dev, indblock);
-	if (indtmp != *p) {
-		brelse(indbh);
-		return 1;
-	}
-	if (!indbh) {
-		*p = 0;
-		*dirt = 1;
-		return 0;
-	}
-	if (inode->i_size < offset)
-		i = 0;
-	else
-		i = (inode->i_size - offset + sb->sv_ind_per_block_block_size_1) >> sb->sv_ind_per_block_block_size_bits;
-	for (; i < sb->sv_ind_per_block; i++) {
-		unsigned char dirty = 0;
-		ind = ((sysv_zone_t *) indbh->b_data) + i;
-		block = tmp = *ind;
-		if (sb->sv_convert)
-			block = from_coh_ulong(block);
-		if (!block)
-			continue;
-		retry |= trunc_indirect(inode,offset+(i<<sb->sv_ind_per_block_bits),ind,sb->sv_convert,&dirty);
-		if (dirty)
-			mark_buffer_dirty(indbh);
-	}
-	for (i = 0; i < sb->sv_ind_per_block; i++)
-		if (((sysv_zone_t *) indbh->b_data)[i])
-			goto done;
-	if (DATA_BUFFER_USED(indbh) || (indtmp != *p)) {
-		brelse(indbh);
-		return 1;
-	}
-	*p = 0;
-	*dirt = 1;
-	sysv_free_block(sb,indblock);
-done:
-	brelse(indbh);
-	return retry;
-}
-
-static int trunc_tindirect(struct inode * inode, unsigned long offset, sysv_zone_t * p, int convert, unsigned char * dirt)
-{
-	u32 indtmp, indblock;
-	struct super_block * sb;
-	struct buffer_head * indbh;
-	unsigned int i;
-	sysv_zone_t * ind;
-	u32 tmp, block;
-	int retry = 0;
-
-	indblock = indtmp = *p;
-	if (convert)
-		indblock = from_coh_ulong(indblock);
-	if (!indblock)
-		return 0;
-	sb = inode->i_sb;
-	indbh = sv_bread(sb, inode->i_dev, indblock);
-	if (indtmp != *p) {
-		brelse(indbh);
-		return 1;
-	}
-	if (!indbh) {
-		*p = 0;
-		*dirt = 1;
-		return 0;
-	}
-	if (inode->i_size < offset)
-		i = 0;
-	else
-		i = (inode->i_size - offset + sb->sv_ind_per_block_2_block_size_1) >> sb->sv_ind_per_block_2_block_size_bits;
-	for (; i < sb->sv_ind_per_block; i++) {
-		unsigned char dirty = 0;
-		ind = ((sysv_zone_t *) indbh->b_data) + i;
-		block = tmp = *ind;
-		if (sb->sv_convert)
-			block = from_coh_ulong(block);
-		if (!block)
-			continue;
-		retry |= trunc_dindirect(inode,offset+(i<<sb->sv_ind_per_block_2_bits),ind,sb->sv_convert,&dirty);
-		if (dirty)
-			mark_buffer_dirty(indbh);
-	}
-	for (i = 0; i < sb->sv_ind_per_block; i++)
-		if (((sysv_zone_t *) indbh->b_data)[i])
-			goto done;
-	if (DATA_BUFFER_USED(indbh) || (indtmp != *p)) {
-		brelse(indbh);
-		return 1;
-	}
-	*p = 0;
-	*dirt = 1;
-	sysv_free_block(sb,indblock);
-done:
-	brelse(indbh);
-	return retry;
-}
-
-static int trunc_all(struct inode * inode)
-{
-	struct super_block * sb;
-	char dirty;
-
-	sb = inode->i_sb;
-	return trunc_direct(inode)
-	     | trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,&dirty)
-	     | trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,&dirty)
-	     | trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,&dirty);
-}
-
-
-void sysv_truncate(struct inode * inode)
-{
-	/* If this is called from sysv_put_inode, we needn't worry about
-	 * races as we are just losing the last reference to the inode.
-	 * If this is called from another place, let's hope it's a regular
-	 * file.
-	 * Truncating symbolic links is strange. We assume we don't truncate
-	 * a directory we are just modifying. We ensure we don't truncate
-	 * a regular file we are just writing to, by use of a lock.
-	 */
-	if (S_ISLNK(inode->i_mode))
-		printk("sysv_truncate: truncating symbolic link\n");
-	else if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
-		return;
-	while (trunc_all(inode)) {
-		current->counter = 0;
-		schedule();
-	}
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	mark_inode_dirty(inode);
-}
diff -urN linux-2.4.6-pre8/fs/udf/ialloc.c linux/fs/udf/ialloc.c
--- linux-2.4.6-pre8/fs/udf/ialloc.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/udf/ialloc.c	Mon Dec  3 22:50:39 2001
@@ -144,8 +144,10 @@
 		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
 	else
 		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	UDF_I_UMTIME(inode) = UDF_I_UATIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME;
+	inode->i_mtime = inode->i_atime = inode->i_ctime =
+		UDF_I_CRTIME(inode) = CURRENT_TIME;
+	UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
+		UDF_I_UCRTIME(inode) = CURRENT_UTIME;
 	UDF_I_NEW_INODE(inode) = 1;
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
diff -urN linux-2.4.6-pre8/fs/udf/inode.c linux/fs/udf/inode.c
--- linux-2.4.6-pre8/fs/udf/inode.c	Mon Dec  3 22:50:28 2001
+++ linux/fs/udf/inode.c	Mon Dec  3 22:50:39 2001
@@ -203,7 +203,6 @@
 		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
 	else
 		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
-	inode->i_blocks = inode->i_sb->s_blocksize / 512;
 	mark_buffer_dirty_inode(bh, inode);
 	udf_release_data(bh);
 
@@ -1080,31 +1079,37 @@
 			(inode->i_sb->s_blocksize_bits - 9);
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(fe->accessTime)) )
+		{
+			inode->i_atime = convtime;
+		}
+		else
+		{
+			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+		}
+
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(fe->modificationTime)) )
 		{
 			inode->i_mtime = convtime;
 			UDF_I_UMTIME(inode) = convtime_usec;
-			inode->i_ctime = convtime;
-			UDF_I_UCTIME(inode) = convtime_usec;
 		}
 		else
 		{
 			inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
 			UDF_I_UMTIME(inode) = 0;
-			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
-			UDF_I_UCTIME(inode) = 0;
 		}
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
-			lets_to_cpu(fe->accessTime)) ) 
+			lets_to_cpu(fe->attrTime)) )
 		{
-			inode->i_atime = convtime;
-			UDF_I_UATIME(inode) = convtime_usec;
+			inode->i_ctime = convtime;
+			UDF_I_UCTIME(inode) = convtime_usec;
 		}
 		else
 		{
-			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
-			UDF_I_UATIME(inode) = convtime_usec;
+			inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UCTIME(inode) = 0;
 		}
 
 		UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
@@ -1119,6 +1124,16 @@
 			(inode->i_sb->s_blocksize_bits - 9);
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
+			lets_to_cpu(efe->accessTime)) )
+		{
+			inode->i_atime = convtime;
+		}
+		else
+		{
+			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+		}
+
+		if ( udf_stamp_to_time(&convtime, &convtime_usec,
 			lets_to_cpu(efe->modificationTime)) )
 		{
 			inode->i_mtime = convtime;
@@ -1131,19 +1146,19 @@
 		}
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
-			lets_to_cpu(efe->accessTime)) )
+			lets_to_cpu(efe->createTime)) )
 		{
-			inode->i_atime = convtime;
-			UDF_I_UATIME(inode) = convtime_usec;
+			UDF_I_CRTIME(inode) = convtime;
+			UDF_I_UCRTIME(inode) = convtime_usec;
 		}
 		else
 		{
-			inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
-			UDF_I_UATIME(inode) = 0;
+			UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb);
+			UDF_I_UCRTIME(inode) = 0;
 		}
 
 		if ( udf_stamp_to_time(&convtime, &convtime_usec,
-			lets_to_cpu(efe->createTime)) )
+			lets_to_cpu(efe->attrTime)) )
 		{
 			inode->i_ctime = convtime;
 			UDF_I_UCTIME(inode) = convtime_usec;
@@ -1171,6 +1186,7 @@
 			inode->i_nlink ++;
 			break;
 		}
+		case FILE_TYPE_REALTIME:
 		case FILE_TYPE_REGULAR:
 		case FILE_TYPE_NONE:
 		{
@@ -1399,13 +1415,12 @@
 			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
 			(inode->i_sb->s_blocksize_bits - 9));
 
-		if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode)))
+		if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0))
 			fe->accessTime = cpu_to_lets(cpu_time);
 		if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
-		{
 			fe->modificationTime = cpu_to_lets(cpu_time);
+		if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
 			fe->attrTime = cpu_to_lets(cpu_time);
-		}
 		memset(&(fe->impIdent), 0, sizeof(EntityID));
 		strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
 		fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
@@ -1418,19 +1433,40 @@
 	}
 	else
 	{
+		efe->objectSize = cpu_to_le64(inode->i_size);
 		efe->logicalBlocksRecorded = cpu_to_le64(
-			(inode->i_blocks + (2 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
+			(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
 			(inode->i_sb->s_blocksize_bits - 9));
 
-		if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode)))
+		if (UDF_I_CRTIME(inode) >= inode->i_atime)
+		{
+			UDF_I_CRTIME(inode) = inode->i_atime;
+			UDF_I_UCRTIME(inode) = 0;
+		}
+		if (UDF_I_CRTIME(inode) > inode->i_mtime ||
+			(UDF_I_CRTIME(inode) == inode->i_mtime &&
+			 UDF_I_UCRTIME(inode) > UDF_I_UMTIME(inode)))
+		{
+			UDF_I_CRTIME(inode) = inode->i_mtime;
+			UDF_I_UCRTIME(inode) = UDF_I_UMTIME(inode);
+		}
+		if (UDF_I_CRTIME(inode) > inode->i_ctime ||
+			(UDF_I_CRTIME(inode) == inode->i_ctime &&
+			 UDF_I_UCRTIME(inode) > UDF_I_UCTIME(inode)))
+		{
+			UDF_I_CRTIME(inode) = inode->i_ctime;
+			UDF_I_UCRTIME(inode) = UDF_I_UCTIME(inode);
+		}
+
+		if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0))
 			efe->accessTime = cpu_to_lets(cpu_time);
 		if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
 			efe->modificationTime = cpu_to_lets(cpu_time);
-		if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
-		{
+		if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode), UDF_I_UCRTIME(inode)))
 			efe->createTime = cpu_to_lets(cpu_time);
+		if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
 			efe->attrTime = cpu_to_lets(cpu_time);
-		}
+
 		memset(&(efe->impIdent), 0, sizeof(EntityID));
 		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
 		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
diff -urN linux-2.4.6-pre8/fs/udf/udf_i.h linux/fs/udf/udf_i.h
--- linux-2.4.6-pre8/fs/udf/udf_i.h	Mon Dec  3 22:50:28 2001
+++ linux/fs/udf/udf_i.h	Mon Dec  3 22:50:39 2001
@@ -14,8 +14,9 @@
 #define UDF_I_NEW_INODE(X)	( UDF_I(X)->i_new_inode )
 #define UDF_I_NEXT_ALLOC_BLOCK(X)	( UDF_I(X)->i_next_alloc_block )
 #define UDF_I_NEXT_ALLOC_GOAL(X)	( UDF_I(X)->i_next_alloc_goal )
-#define UDF_I_UATIME(X)		( UDF_I(X)->i_uatime )
 #define UDF_I_UMTIME(X)		( UDF_I(X)->i_umtime )
 #define UDF_I_UCTIME(X)		( UDF_I(X)->i_uctime )
+#define UDF_I_CRTIME(X)		( UDF_I(X)->i_crtime )
+#define UDF_I_UCRTIME(X)	( UDF_I(X)->i_ucrtime )
 
 #endif /* !defined(_LINUX_UDF_I_H) */
diff -urN linux-2.4.6-pre8/include/asm-i386/elf.h linux/include/asm-i386/elf.h
--- linux-2.4.6-pre8/include/asm-i386/elf.h	Fri May 25 18:01:26 2001
+++ linux/include/asm-i386/elf.h	Mon Dec  3 22:50:39 2001
@@ -55,7 +55,7 @@
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
 
 /* Wow, the "main" arch needs arch dependent functions too.. :) */
 
diff -urN linux-2.4.6-pre8/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- linux-2.4.6-pre8/include/asm-i386/uaccess.h	Fri May 25 18:01:28 2001
+++ linux/include/asm-i386/uaccess.h	Mon Dec  3 22:50:39 2001
@@ -129,12 +129,6 @@
 
 extern void __put_user_bad(void);
 
-#define __put_user_x(size,ret,x,ptr)					\
-	__asm__ __volatile__("call __put_user_" #size			\
-		:"=a" (ret)						\
-		:"0" (ptr),"d" (x)					\
-		:"cx")
-
 #define put_user(x,ptr)							\
   __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
diff -urN linux-2.4.6-pre8/include/asm-mips/addrspace.h linux/include/asm-mips/addrspace.h
--- linux-2.4.6-pre8/include/asm-mips/addrspace.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/addrspace.h	Mon Dec  3 22:50:39 2001
@@ -4,6 +4,7 @@
  * for more details.
  *
  * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 2000 by Maciej W. Rozycki
  *
  * Defitions for the address spaces of the MIPS CPUs.
  */
@@ -19,23 +20,40 @@
 #define KSEG2                   0xc0000000
 #define KSEG3                   0xe0000000
 
+#define K0BASE  KSEG0
+
 /*
  * Returns the kernel segment base of a given address
  */
+#ifndef __ASSEMBLY__
 #define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+#else
+#define KSEGX(a)                ((a) & 0xe0000000)
+#endif
 
 /*
  * Returns the physical address of a KSEG0/KSEG1 address
  */
+#ifndef __ASSEMBLY__
 #define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff)
+#else
+#define PHYSADDR(a)		((a) & 0x1fffffff)
+#endif
 
 /*
  * Map an address to a certain kernel segment
  */
+#ifndef __ASSEMBLY__
 #define KSEG0ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
 #define KSEG1ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
 #define KSEG2ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
 #define KSEG3ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+#else
+#define KSEG0ADDR(a)		(((a) & 0x1fffffff) | KSEG0)
+#define KSEG1ADDR(a)		(((a) & 0x1fffffff) | KSEG1)
+#define KSEG2ADDR(a)		(((a) & 0x1fffffff) | KSEG2)
+#define KSEG3ADDR(a)		(((a) & 0x1fffffff) | KSEG3)
+#endif
 
 /*
  * Memory segments (64bit kernel mode addresses)
diff -urN linux-2.4.6-pre8/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h
--- linux-2.4.6-pre8/include/asm-mips/asmmacro.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/asmmacro.h	Mon Dec  3 22:50:39 2001
@@ -3,124 +3,122 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1998 Ralf Baechle
- *
- * $Id: asmmacro.h,v 1.3 1998/03/27 04:47:58 ralf Exp $
  */
-#ifndef __MIPS_ASMMACRO_H
-#define __MIPS_ASMMACRO_H
+#ifndef _ASM_ASMMACRO_H
+#define _ASM_ASMMACRO_H
 
 #include <asm/offset.h>
 
 #define FPU_SAVE_DOUBLE(thread, tmp) \
 	cfc1	tmp,  fcr31;                    \
 	sdc1	$f0,  (THREAD_FPU + 0x000)(thread); \
-	sdc1	$f2,  (THREAD_FPU + 0x008)(thread); \
-	sdc1	$f4,  (THREAD_FPU + 0x010)(thread); \
-	sdc1	$f6,  (THREAD_FPU + 0x018)(thread); \
-	sdc1	$f8,  (THREAD_FPU + 0x020)(thread); \
-	sdc1	$f10, (THREAD_FPU + 0x028)(thread); \
-	sdc1	$f12, (THREAD_FPU + 0x030)(thread); \
-	sdc1	$f14, (THREAD_FPU + 0x038)(thread); \
-	sdc1	$f16, (THREAD_FPU + 0x040)(thread); \
-	sdc1	$f18, (THREAD_FPU + 0x048)(thread); \
-	sdc1	$f20, (THREAD_FPU + 0x050)(thread); \
-	sdc1	$f22, (THREAD_FPU + 0x058)(thread); \
-	sdc1	$f24, (THREAD_FPU + 0x060)(thread); \
-	sdc1	$f26, (THREAD_FPU + 0x068)(thread); \
-	sdc1	$f28, (THREAD_FPU + 0x070)(thread); \
-	sdc1	$f30, (THREAD_FPU + 0x078)(thread); \
-	sw	tmp,  (THREAD_FPU + 0x080)(thread)
+	sdc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	sdc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	sdc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	sdc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	sdc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	sdc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	sdc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	sdc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	sdc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	sdc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	sdc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	sdc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	sdc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	sdc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	sdc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	sw	tmp,  (THREAD_FPU + 0x100)(thread)
 
 #define FPU_SAVE_SINGLE(thread,tmp)                 \
 	cfc1	tmp,  fcr31;                        \
 	swc1	$f0,  (THREAD_FPU + 0x000)(thread); \
-	swc1	$f1,  (THREAD_FPU + 0x004)(thread); \
-	swc1	$f2,  (THREAD_FPU + 0x008)(thread); \
-	swc1	$f3,  (THREAD_FPU + 0x00c)(thread); \
-	swc1	$f4,  (THREAD_FPU + 0x010)(thread); \
-	swc1	$f5,  (THREAD_FPU + 0x014)(thread); \
-	swc1	$f6,  (THREAD_FPU + 0x018)(thread); \
-	swc1	$f7,  (THREAD_FPU + 0x01c)(thread); \
-	swc1	$f8,  (THREAD_FPU + 0x020)(thread); \
-	swc1	$f9,  (THREAD_FPU + 0x024)(thread); \
-	swc1	$f10, (THREAD_FPU + 0x028)(thread); \
-	swc1	$f11, (THREAD_FPU + 0x02c)(thread); \
-	swc1	$f12, (THREAD_FPU + 0x030)(thread); \
-	swc1	$f13, (THREAD_FPU + 0x034)(thread); \
-	swc1	$f14, (THREAD_FPU + 0x038)(thread); \
-	swc1	$f15, (THREAD_FPU + 0x03c)(thread); \
-	swc1	$f16, (THREAD_FPU + 0x040)(thread); \
-	swc1	$f17, (THREAD_FPU + 0x044)(thread); \
-	swc1	$f18, (THREAD_FPU + 0x048)(thread); \
-	swc1	$f19, (THREAD_FPU + 0x04c)(thread); \
-	swc1	$f20, (THREAD_FPU + 0x050)(thread); \
-	swc1	$f21, (THREAD_FPU + 0x054)(thread); \
-	swc1	$f22, (THREAD_FPU + 0x058)(thread); \
-	swc1	$f23, (THREAD_FPU + 0x05c)(thread); \
-	swc1	$f24, (THREAD_FPU + 0x060)(thread); \
-	swc1	$f25, (THREAD_FPU + 0x064)(thread); \
-	swc1	$f26, (THREAD_FPU + 0x068)(thread); \
-	swc1	$f27, (THREAD_FPU + 0x06c)(thread); \
-	swc1	$f28, (THREAD_FPU + 0x070)(thread); \
-	swc1	$f29, (THREAD_FPU + 0x074)(thread); \
-	swc1	$f30, (THREAD_FPU + 0x078)(thread); \
-	swc1	$f31, (THREAD_FPU + 0x07c)(thread); \
-	sw	tmp,  (THREAD_FPU + 0x080)(thread)
+	swc1	$f1,  (THREAD_FPU + 0x008)(thread); \
+	swc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	swc1	$f3,  (THREAD_FPU + 0x018)(thread); \
+	swc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	swc1	$f5,  (THREAD_FPU + 0x028)(thread); \
+	swc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	swc1	$f7,  (THREAD_FPU + 0x038)(thread); \
+	swc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	swc1	$f9,  (THREAD_FPU + 0x048)(thread); \
+	swc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	swc1	$f11, (THREAD_FPU + 0x058)(thread); \
+	swc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	swc1	$f13, (THREAD_FPU + 0x068)(thread); \
+	swc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	swc1	$f15, (THREAD_FPU + 0x078)(thread); \
+	swc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	swc1	$f17, (THREAD_FPU + 0x088)(thread); \
+	swc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	swc1	$f19, (THREAD_FPU + 0x098)(thread); \
+	swc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	swc1	$f21, (THREAD_FPU + 0x0a8)(thread); \
+	swc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	swc1	$f23, (THREAD_FPU + 0x0b8)(thread); \
+	swc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	swc1	$f25, (THREAD_FPU + 0x0c8)(thread); \
+	swc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	swc1	$f27, (THREAD_FPU + 0x0d8)(thread); \
+	swc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	swc1	$f29, (THREAD_FPU + 0x0e8)(thread); \
+	swc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	swc1	$f31, (THREAD_FPU + 0x0f8)(thread); \
+	sw	tmp,  (THREAD_FPU + 0x100)(thread)
 
 #define FPU_RESTORE_DOUBLE(thread, tmp) \
-	lw	tmp,  (THREAD_FPU + 0x080)(thread); \
+	lw	tmp,  (THREAD_FPU + 0x100)(thread); \
 	ldc1	$f0,  (THREAD_FPU + 0x000)(thread); \
-	ldc1	$f2,  (THREAD_FPU + 0x008)(thread); \
-	ldc1	$f4,  (THREAD_FPU + 0x010)(thread); \
-	ldc1	$f6,  (THREAD_FPU + 0x018)(thread); \
-	ldc1	$f8,  (THREAD_FPU + 0x020)(thread); \
-	ldc1	$f10, (THREAD_FPU + 0x028)(thread); \
-	ldc1	$f12, (THREAD_FPU + 0x030)(thread); \
-	ldc1	$f14, (THREAD_FPU + 0x038)(thread); \
-	ldc1	$f16, (THREAD_FPU + 0x040)(thread); \
-	ldc1	$f18, (THREAD_FPU + 0x048)(thread); \
-	ldc1	$f20, (THREAD_FPU + 0x050)(thread); \
-	ldc1	$f22, (THREAD_FPU + 0x058)(thread); \
-	ldc1	$f24, (THREAD_FPU + 0x060)(thread); \
-	ldc1	$f26, (THREAD_FPU + 0x068)(thread); \
-	ldc1	$f28, (THREAD_FPU + 0x070)(thread); \
-	ldc1	$f30, (THREAD_FPU + 0x078)(thread); \
+	ldc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	ldc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	ldc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	ldc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	ldc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	ldc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	ldc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	ldc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	ldc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	ldc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	ldc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	ldc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	ldc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	ldc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	ldc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
 	ctc1	tmp,  fcr31
 
 #define FPU_RESTORE_SINGLE(thread,tmp)              \
-	lw	tmp,  (THREAD_FPU + 0x080)(thread); \
+	lw	tmp,  (THREAD_FPU + 0x100)(thread); \
 	lwc1	$f0,  (THREAD_FPU + 0x000)(thread); \
-	lwc1	$f1,  (THREAD_FPU + 0x004)(thread); \
-	lwc1	$f2,  (THREAD_FPU + 0x008)(thread); \
-	lwc1	$f3,  (THREAD_FPU + 0x00c)(thread); \
-	lwc1	$f4,  (THREAD_FPU + 0x010)(thread); \
-	lwc1	$f5,  (THREAD_FPU + 0x014)(thread); \
-	lwc1	$f6,  (THREAD_FPU + 0x018)(thread); \
-	lwc1	$f7,  (THREAD_FPU + 0x01c)(thread); \
-	lwc1	$f8,  (THREAD_FPU + 0x020)(thread); \
-	lwc1	$f9,  (THREAD_FPU + 0x024)(thread); \
-	lwc1	$f10, (THREAD_FPU + 0x028)(thread); \
-	lwc1	$f11, (THREAD_FPU + 0x02c)(thread); \
-	lwc1	$f12, (THREAD_FPU + 0x030)(thread); \
-	lwc1	$f13, (THREAD_FPU + 0x034)(thread); \
-	lwc1	$f14, (THREAD_FPU + 0x038)(thread); \
-	lwc1	$f15, (THREAD_FPU + 0x03c)(thread); \
-	lwc1	$f16, (THREAD_FPU + 0x040)(thread); \
-	lwc1	$f17, (THREAD_FPU + 0x044)(thread); \
-	lwc1	$f18, (THREAD_FPU + 0x048)(thread); \
-	lwc1	$f19, (THREAD_FPU + 0x04c)(thread); \
-	lwc1	$f20, (THREAD_FPU + 0x050)(thread); \
-	lwc1	$f21, (THREAD_FPU + 0x054)(thread); \
-	lwc1	$f22, (THREAD_FPU + 0x058)(thread); \
-	lwc1	$f23, (THREAD_FPU + 0x05c)(thread); \
-	lwc1	$f24, (THREAD_FPU + 0x060)(thread); \
-	lwc1	$f25, (THREAD_FPU + 0x064)(thread); \
-	lwc1	$f26, (THREAD_FPU + 0x068)(thread); \
-	lwc1	$f27, (THREAD_FPU + 0x06c)(thread); \
-	lwc1	$f28, (THREAD_FPU + 0x070)(thread); \
-	lwc1	$f29, (THREAD_FPU + 0x074)(thread); \
-	lwc1	$f30, (THREAD_FPU + 0x078)(thread); \
-	lwc1	$f31, (THREAD_FPU + 0x07c)(thread); \
+	lwc1	$f1,  (THREAD_FPU + 0x008)(thread); \
+	lwc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	lwc1	$f3,  (THREAD_FPU + 0x018)(thread); \
+	lwc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	lwc1	$f5,  (THREAD_FPU + 0x028)(thread); \
+	lwc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	lwc1	$f7,  (THREAD_FPU + 0x038)(thread); \
+	lwc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	lwc1	$f9,  (THREAD_FPU + 0x048)(thread); \
+	lwc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	lwc1	$f11, (THREAD_FPU + 0x058)(thread); \
+	lwc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	lwc1	$f13, (THREAD_FPU + 0x068)(thread); \
+	lwc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	lwc1	$f15, (THREAD_FPU + 0x078)(thread); \
+	lwc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	lwc1	$f17, (THREAD_FPU + 0x088)(thread); \
+	lwc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	lwc1	$f19, (THREAD_FPU + 0x098)(thread); \
+	lwc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	lwc1	$f21, (THREAD_FPU + 0x0a8)(thread); \
+	lwc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	lwc1	$f23, (THREAD_FPU + 0x0b8)(thread); \
+	lwc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	lwc1	$f25, (THREAD_FPU + 0x0c8)(thread); \
+	lwc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	lwc1	$f27, (THREAD_FPU + 0x0d8)(thread); \
+	lwc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	lwc1	$f29, (THREAD_FPU + 0x0e8)(thread); \
+	lwc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	lwc1	$f31, (THREAD_FPU + 0x0f8)(thread); \
 	ctc1	tmp,  fcr31
 
 #define CPU_SAVE_NONSCRATCH(thread) \
@@ -148,4 +146,4 @@
 	lw	fp, THREAD_REG30(thread); \
 	lw	ra, THREAD_REG31(thread)
 
-#endif /* !(__MIPS_ASMMACRO_H) */
+#endif /* _ASM_ASMMACRO_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h
--- linux-2.4.6-pre8/include/asm-mips/atomic.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/atomic.h	Mon Dec  3 22:50:39 2001
@@ -9,25 +9,35 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997 by Ralf Baechle
- *
- * $Id: atomic.h,v 1.6 1999/07/26 19:42:42 harald Exp $
+ * Copyright (C) 1996, 1997, 2000 by Ralf Baechle
  */
 #ifndef __ASM_ATOMIC_H
 #define __ASM_ATOMIC_H
 
 #include <linux/config.h>
 
-#ifdef CONFIG_SMP
 typedef struct { volatile int counter; } atomic_t;
-#else
-typedef struct { int counter; } atomic_t;
-#endif
 
 #ifdef __KERNEL__
 #define ATOMIC_INIT(i)    { (i) }
 
+/*
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
 #define atomic_read(v)	((v)->counter)
+
+/*
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
 #define atomic_set(v,i)	((v)->counter = (i))
 
 #if !defined(CONFIG_CPU_HAS_LLSC)
@@ -37,8 +47,15 @@
 /*
  * The MIPS I implementation is only atomic with respect to
  * interrupts.  R3000 based multiprocessor machines are rare anyway ...
+ *
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.  Note that the guaranteed useful range
+ * of an atomic_t is only 24 bits.
  */
-extern __inline__ void atomic_add(int i, volatile atomic_t * v)
+extern __inline__ void atomic_add(int i, atomic_t * v)
 {
 	int	flags;
 
@@ -48,7 +65,15 @@
 	restore_flags(flags);
 }
 
-extern __inline__ void atomic_sub(int i, volatile atomic_t * v)
+/*
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+extern __inline__ void atomic_sub(int i, atomic_t * v)
 {
 	int	flags;
 
@@ -86,21 +111,6 @@
 	return temp;
 }
 
-extern __inline__ void atomic_clear_mask(unsigned long mask, unsigned long * v)
-{
-        unsigned long temp;
-        int     flags;
-
-        save_flags(flags);
-        cli();
-        temp = *v;
-        temp &= ~mask;
-        *v = temp;
-        restore_flags(flags);
-
-        return;
-}
-
 #else
 
 /*
@@ -109,40 +119,45 @@
  */
 
 /*
- * Make sure gcc doesn't try to be clever and move things around
- * on us. We need to use _exactly_ the address the user gave us,
- * not some alias that contains the same information.
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.  Note that the guaranteed useful range
+ * of an atomic_t is only 24 bits.
  */
-#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
-
-extern __inline__ void atomic_add(int i, volatile atomic_t * v)
+extern __inline__ void atomic_add(int i, atomic_t * v)
 {
 	unsigned long temp;
 
 	__asm__ __volatile__(
-		"1:\tll\t%0,%1\n\t"
-		"addu\t%0,%2\n\t"
-		"sc\t%0,%1\n\t"
-		"beqz\t%0,1b"
-		:"=&r" (temp),
-		 "=m" (__atomic_fool_gcc(v))
-		:"Ir" (i),
-		 "m" (__atomic_fool_gcc(v)));
+		"1:   ll      %0, %1      # atomic_add\n"
+		"     addu    %0, %2                  \n"
+		"     sc      %0, %1                  \n"
+		"     beqz    %0, 1b                  \n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
 }
 
-extern __inline__ void atomic_sub(int i, volatile atomic_t * v)
+/*
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+extern __inline__ void atomic_sub(int i, atomic_t * v)
 {
 	unsigned long temp;
 
 	__asm__ __volatile__(
-		"1:\tll\t%0,%1\n\t"
-		"subu\t%0,%2\n\t"
-		"sc\t%0,%1\n\t"
-		"beqz\t%0,1b"
-		:"=&r" (temp),
-		 "=m" (__atomic_fool_gcc(v))
-		:"Ir" (i),
-		 "m" (__atomic_fool_gcc(v)));
+		"1:   ll      %0, %1      # atomic_sub\n"
+		"     subu    %0, %2                  \n"
+		"     sc      %0, %1                  \n"
+		"     beqz    %0, 1b                  \n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
 }
 
 /*
@@ -153,18 +168,17 @@
 	unsigned long temp, result;
 
 	__asm__ __volatile__(
-		".set\tnoreorder\n"
-		"1:\tll\t%1,%2\n\t"
-		"addu\t%0,%1,%3\n\t"
-		"sc\t%0,%2\n\t"
-		"beqz\t%0,1b\n\t"
-		"addu\t%0,%1,%3\n\t"
-		".set\treorder"
-		:"=&r" (result),
-		 "=&r" (temp),
-		 "=m" (__atomic_fool_gcc(v))
-		:"Ir" (i),
-		 "m" (__atomic_fool_gcc(v)));
+		".set push               # atomic_add_return\n"
+		".set noreorder                             \n"
+		"1:   ll      %1, %2                        \n"
+		"     addu    %0, %1, %3                    \n"
+		"     sc      %0, %2                        \n"
+		"     beqz    %0, 1b                        \n"
+		"     addu    %0, %1, %3                    \n"
+		".set pop                                   \n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
 
 	return result;
 }
@@ -174,18 +188,17 @@
 	unsigned long temp, result;
 
 	__asm__ __volatile__(
-		".set\tnoreorder\n"
-		"1:\tll\t%1,%2\n\t"
-		"subu\t%0,%1,%3\n\t"
-		"sc\t%0,%2\n\t"
-		"beqz\t%0,1b\n\t"
-		"subu\t%0,%1,%3\n\t"
-		".set\treorder"
-		:"=&r" (result),
-		 "=&r" (temp),
-		 "=m" (__atomic_fool_gcc(v))
-		:"Ir" (i),
-		 "m" (__atomic_fool_gcc(v)));
+		".set push                                   \n"
+		".set noreorder           # atomic_sub_return\n"
+		"1:   ll    %1, %2                           \n"
+		"     subu  %0, %1, %3                       \n"
+		"     sc    %0, %2                           \n"
+		"     beqz  %0, 1b                           \n"
+		"     subu  %0, %1, %3                       \n"
+		".set pop                                    \n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
 
 	return result;
 }
@@ -194,11 +207,71 @@
 #define atomic_dec_return(v) atomic_sub_return(1,(v))
 #define atomic_inc_return(v) atomic_add_return(1,(v))
 
+/*
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0)
+
+/*
+ * atomic_dec_and_test - decrement by 1 and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
+/*
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
 #define atomic_inc(v) atomic_add(1,(v))
+
+/*
+ * atomic_dec - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
 #define atomic_dec(v) atomic_sub(1,(v))
+
+/*
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.  Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ *
+ * Currently not implemented for MIPS.
+ */
+
 #endif /* defined(__KERNEL__) */
 
-#endif /* __ASM_MIPS_ATOMIC_H */
+#endif /* __ASM_ATOMIC_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/bcache.h linux/include/asm-mips/bcache.h
--- linux-2.4.6-pre8/include/asm-mips/bcache.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/bcache.h	Mon Dec  3 22:50:39 2001
@@ -1,14 +1,19 @@
-/* $Id$
- *
+/*
  * 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) 1997, 1999 by Ralf Baechle
+ * Copyright (c) 1997, 1999, 2000 by Ralf Baechle
+ * Copyright (c) 2000 by Silicon Graphics, Inc.
  */
 #ifndef _ASM_BCACHE_H
 #define _ASM_BCACHE_H
 
+#include <linux/config.h>
+
+/* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent,
+   chipset implemented caches.  On machines with other CPUs the CPU does the
+   cache thing itself. */
 struct bcache_ops {
 	void (*bc_enable)(void);
 	void (*bc_disable)(void);
@@ -19,6 +24,39 @@
 extern void indy_sc_init(void);
 extern void sni_pcimt_sc_init(void);
 
+#ifdef CONFIG_BOARD_SCACHE
+
 extern struct bcache_ops *bcops;
+
+extern inline void bc_enable(void)
+{
+	bcops->bc_enable();
+}
+
+extern inline void bc_disable(void)
+{
+	bcops->bc_disable();
+}
+
+extern inline void bc_wback_inv(unsigned long page, unsigned long size)
+{
+	bcops->bc_wback_inv(page, size);
+}
+
+extern inline void bc_inv(unsigned long page, unsigned long size)
+{
+	bcops->bc_inv(page, size);
+}
+
+#else /* !defined(CONFIG_BOARD_SCACHE) */
+
+/* Not R4000 / R4400 / R4600 / R5000.  */
+
+#define bc_enable() do { } while (0)
+#define bc_disable() do { } while (0)
+#define bc_wback_inv(page, size) do { } while (0)
+#define bc_inv(page, size) do { } while (0)
+
+#endif /* !defined(CONFIG_BOARD_SCACHE) */
 
 #endif /* _ASM_BCACHE_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h
--- linux-2.4.6-pre8/include/asm-mips/bitops.h	Wed Jul  5 22:15:26 2000
+++ linux/include/asm-mips/bitops.h	Mon Dec  3 22:50:39 2001
@@ -1,10 +1,10 @@
-/* $Id: bitops.h,v 1.7 1999/08/19 22:56:33 ralf Exp $
- *
+/*
  * 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 - 1997, 1999  Ralf Baechle (ralf@gnu.org)
+ * Copyright (c) 1994 - 1997, 1999, 2000  Ralf Baechle (ralf@gnu.org)
+ * Copyright (c) 2000  Silicon Graphics, Inc.
  */
 #ifndef _ASM_BITOPS_H
 #define _ASM_BITOPS_H
@@ -19,6 +19,12 @@
 #include <linux/config.h>
 
 /*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+/*
  * Only disable interrupt for kernel mode stuff to keep usermode stuff
  * that dares to use kernel include files alive.
  */
@@ -35,25 +41,6 @@
 #define __bi_restore_flags(x)
 #endif /* __KERNEL__ */
 
-/*
- * Note that the bit operations are defined on arrays of 32 bit sized
- * elements.  With respect to a future 64 bit implementation it is
- * wrong to use long *.  Use u32 * or int *.
- */
-extern __inline__ void set_bit(int nr, void *addr);
-extern __inline__ void clear_bit(int nr, void *addr);
-extern __inline__ void change_bit(int nr, void *addr);
-extern __inline__ int test_and_set_bit(int nr, void *addr);
-extern __inline__ int test_and_clear_bit(int nr, void *addr);
-extern __inline__ int test_and_change_bit(int nr, void *addr);
-
-extern __inline__ int test_bit(int nr, const void *addr);
-#ifndef __MIPSEB__
-extern __inline__ int find_first_zero_bit (void *addr, unsigned size);
-#endif
-extern __inline__ int find_next_zero_bit (void * addr, int size, int offset);
-extern __inline__ unsigned long ffz(unsigned long word);
-
 #if defined(CONFIG_CPU_HAS_LLSC)
 
 #include <asm/mipsregs.h>
@@ -64,92 +51,281 @@
  */
 
 /*
- * The following functions will only work for the R4000!
- */
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+extern __inline__ void
+set_bit(int nr, volatile void *addr)
+{
+	unsigned long *m = ((unsigned long *) addr) + (nr >> 5);
+	unsigned long temp;
+
+	__asm__ __volatile__(
+		"1:\tll\t%0, %1\t\t# set_bit\n\t"
+		"or\t%0, %2\n\t"
+		"sc\t%0, %1\n\t"
+		"beqz\t%0, 1b"
+		: "=&r" (temp), "=m" (*m)
+		: "ir" (1UL << (nr & 0x1f)), "m" (*m));
+}
 
-extern __inline__ void set_bit(int nr, void *addr)
+/*
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_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.
+ */
+extern __inline__ void __set_bit(int nr, volatile void * addr)
 {
-	int	mask, mw;
+	unsigned long * m = ((unsigned long *) addr) + (nr >> 5);
 
-	addr += ((nr >> 3) & ~3);
-	mask = 1 << (nr & 0x1f);
-	do {
-		mw = load_linked(addr);
-	} while (!store_conditional(addr, mw|mask));
+	*m |= 1UL << (nr & 31);
+}
+
+/*
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+extern __inline__ void
+clear_bit(int nr, volatile void *addr)
+{
+	unsigned long *m = ((unsigned long *) addr) + (nr >> 5);
+	unsigned long temp;
+
+	__asm__ __volatile__(
+		"1:\tll\t%0, %1\t\t# clear_bit\n\t"
+		"and\t%0, %2\n\t"
+		"sc\t%0, %1\n\t"
+		"beqz\t%0, 1b\n\t"
+		: "=&r" (temp), "=m" (*m)
+		: "ir" (~(1UL << (nr & 0x1f))), "m" (*m));
 }
 
-extern __inline__ void clear_bit(int nr, void *addr)
+/*
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+extern __inline__ void
+change_bit(int nr, volatile void *addr)
+{
+	unsigned long *m = ((unsigned long *) addr) + (nr >> 5);
+	unsigned long temp;
+
+	__asm__ __volatile__(
+		"1:\tll\t%0, %1\t\t# change_bit\n\t"
+		"xor\t%0, %2\n\t"
+		"sc\t%0, %1\n\t"
+		"beqz\t%0, 1b"
+		: "=&r" (temp), "=m" (*m)
+		: "ir" (1UL << (nr & 0x1f)), "m" (*m));
+}
+
+/*
+ * __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.
+ */
+extern __inline__ void __change_bit(int nr, volatile void * addr)
 {
-	int	mask, mw;
+	unsigned long * m = ((unsigned long *) addr) + (nr >> 5);
 
-	addr += ((nr >> 3) & ~3);
-	mask = 1 << (nr & 0x1f);
-	do {
-		mw = load_linked(addr);
-		}
-	while (!store_conditional(addr, mw & ~mask));
+	*m ^= 1UL << (nr & 31);
 }
 
-extern __inline__ void change_bit(int nr, void *addr)
+/*
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+extern __inline__ int
+test_and_set_bit(int nr, volatile void *addr)
 {
-	int	mask, mw;
+	unsigned long *m = ((unsigned long *) addr) + (nr >> 5);
+	unsigned long temp, res;
 
-	addr += ((nr >> 3) & ~3);
-	mask = 1 << (nr & 0x1f);
-	do {
-		mw = load_linked(addr);
-	} while (!store_conditional(addr, mw ^ mask));
+	__asm__ __volatile__(
+		".set\tnoreorder\t\t# test_and_set_bit\n"
+		"1:\tll\t%0, %1\n\t"
+		"or\t%2, %0, %3\n\t"
+		"sc\t%2, %1\n\t"
+		"beqz\t%2, 1b\n\t"
+		" and\t%2, %0, %3\n\t"
+		".set\treorder"
+		: "=&r" (temp), "=m" (*m), "=&r" (res)
+		: "r" (1UL << (nr & 0x1f)), "m" (*m)
+		: "memory");
+
+	return res != 0;
 }
 
-extern __inline__ int test_and_set_bit(int nr, void *addr)
+/*
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+extern __inline__ int __test_and_set_bit(int nr, volatile void * addr)
 {
-	int	mask, retval, mw;
+	int mask, retval;
+	volatile int *a = addr;
 
-	addr += ((nr >> 3) & ~3);
+	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	do {
-		mw = load_linked(addr);
-		retval = (mask & mw) != 0;
-	} while (!store_conditional(addr, mw|mask));
+	retval = (mask & *a) != 0;
+	*a |= mask;
 
 	return retval;
 }
 
-extern __inline__ int test_and_clear_bit(int nr, void *addr)
+/*
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+extern __inline__ int
+test_and_clear_bit(int nr, volatile void *addr)
+{
+	unsigned long *m = ((unsigned long *) addr) + (nr >> 5);
+	unsigned long temp, res;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\t\t# test_and_clear_bit\n"
+		"1:\tll\t%0, %1\n\t"
+		"or\t%2, %0, %3\n\t"
+		"xor\t%2, %3\n\t"
+		"sc\t%2, %1\n\t"
+		"beqz\t%2, 1b\n\t"
+		" and\t%2, %0, %3\n\t"
+		".set\treorder"
+		: "=&r" (temp), "=m" (*m), "=&r" (res)
+		: "r" (1UL << (nr & 0x1f)), "m" (*m)
+		: "memory");
+
+	return res != 0;
+}
+
+/*
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
 {
-	int	mask, retval, mw;
+	int	mask, retval;
+	volatile int	*a = addr;
 
-	addr += ((nr >> 3) & ~3);
+	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	do {
-		mw = load_linked(addr);
-		retval = (mask & mw) != 0;
-		}
-	while (!store_conditional(addr, mw & ~mask));
+	retval = (mask & *a) != 0;
+	*a &= ~mask;
 
 	return retval;
 }
 
-extern __inline__ int test_and_change_bit(int nr, void *addr)
+/*
+ * test_and_change_bit - Change a bit and return its new value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+extern __inline__ int
+test_and_change_bit(int nr, volatile void *addr)
+{
+	unsigned long *m = ((unsigned long *) addr) + (nr >> 5);
+	unsigned long temp, res;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\t\t# test_and_change_bit\n"
+		"1:\tll\t%0, %1\n\t"
+		"xor\t%2, %0, %3\n\t"
+		"sc\t%2, %1\n\t"
+		"beqz\t%2, 1b\n\t"
+		" and\t%2, %0, %3\n\t"
+		".set\treorder"
+		: "=&r" (temp), "=m" (*m), "=&r" (res)
+		: "r" (1UL << (nr & 0x1f)), "m" (*m)
+		: "memory");
+
+	return res != 0;
+}
+
+/*
+ * __test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+extern __inline__ int __test_and_change_bit(int nr, volatile void * addr)
 {
-	int	mask, retval, mw;
+	int	mask, retval;
+	volatile int	*a = addr;
 
-	addr += ((nr >> 3) & ~3);
+	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	do {
-		mw = load_linked(addr);
-		retval = (mask & mw) != 0;
-	} while (!store_conditional(addr, mw ^ mask));
+	retval = (mask & *a) != 0;
+	*a ^= mask;
 
 	return retval;
 }
 
 #else /* MIPS I */
 
-extern __inline__ void set_bit(int nr, void * addr)
+/*
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+extern __inline__ void set_bit(int nr, volatile void * addr)
 {
 	int	mask;
-	int	*a = addr;
+	volatile int	*a = addr;
 	__bi_flags;
 
 	a += nr >> 5;
@@ -159,10 +335,39 @@
 	__bi_restore_flags(flags);
 }
 
-extern __inline__ void clear_bit(int nr, void * addr)
+/*
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_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.
+ */
+extern __inline__ void __set_bit(int nr, volatile void * addr)
 {
 	int	mask;
-	int	*a = addr;
+	volatile int	*a = addr;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	*a |= mask;
+}
+
+/*
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+extern __inline__ void clear_bit(int nr, volatile void * addr)
+{
+	int	mask;
+	volatile int	*a = addr;
 	__bi_flags;
 
 	a += nr >> 5;
@@ -172,10 +377,19 @@
 	__bi_restore_flags(flags);
 }
 
-extern __inline__ void change_bit(int nr, void * addr)
+/*
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+extern __inline__ void change_bit(int nr, volatile void * addr)
 {
 	int	mask;
-	int	*a = addr;
+	volatile int	*a = addr;
 	__bi_flags;
 
 	a += nr >> 5;
@@ -185,10 +399,34 @@
 	__bi_restore_flags(flags);
 }
 
-extern __inline__ int test_and_set_bit(int nr, void * addr)
+/*
+ * __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.
+ */
+extern __inline__ void __change_bit(int nr, volatile void * addr)
+{
+	unsigned long * m = ((unsigned long *) addr) + (nr >> 5);
+
+	*m ^= 1UL << (nr & 31);
+}
+
+/*
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
 {
 	int	mask, retval;
-	int	*a = addr;
+	volatile int	*a = addr;
 	__bi_flags;
 
 	a += nr >> 5;
@@ -201,10 +439,40 @@
 	return retval;
 }
 
-extern __inline__ int test_and_clear_bit(int nr, void * addr)
+/*
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+extern __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+{
+	int	mask, retval;
+	volatile int	*a = addr;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	retval = (mask & *a) != 0;
+	*a |= mask;
+
+	return retval;
+}
+
+/*
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+extern __inline__ int test_and_clear_bit(int nr, volatile void * addr)
 {
 	int	mask, retval;
-	int	*a = addr;
+	volatile int	*a = addr;
 	__bi_flags;
 
 	a += nr >> 5;
@@ -217,10 +485,40 @@
 	return retval;
 }
 
-extern __inline__ int test_and_change_bit(int nr, void * addr)
+/*
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+extern __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
 {
 	int	mask, retval;
-	int	*a = addr;
+	volatile int	*a = addr;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	retval = (mask & *a) != 0;
+	*a &= ~mask;
+
+	return retval;
+}
+
+/*
+ * test_and_change_bit - Change a bit and return its new value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.  
+ * It also implies a memory barrier.
+ */
+extern __inline__ int test_and_change_bit(int nr, volatile void * addr)
+{
+	int	mask, retval;
+	volatile int	*a = addr;
 	__bi_flags;
 
 	a += nr >> 5;
@@ -233,14 +531,41 @@
 	return retval;
 }
 
+/*
+ * __test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.  
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+extern __inline__ int __test_and_change_bit(int nr, volatile void * addr)
+{
+	int	mask, retval;
+	volatile int	*a = addr;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	retval = (mask & *a) != 0;
+	*a ^= mask;
+
+	return retval;
+}
+
 #undef __bi_flags
-#undef __bi_cli()
-#undef __bi_save_flags(x)
-#undef __bi_restore_flags(x)
+#undef __bi_cli
+#undef __bi_save_flags
+#undef __bi_restore_flags
 
 #endif /* MIPS I */
 
-extern __inline__ int test_bit(int nr, const void *addr)
+/*
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+extern __inline__ int test_bit(int nr, volatile void *addr)
 {
 	return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
 }
@@ -249,6 +574,14 @@
 
 /* Little endian versions. */
 
+/*
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
 extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
 {
 	unsigned long dummy;
@@ -285,18 +618,20 @@
 		".set\tat\n\t"
 		".set\treorder\n"
 		"2:"
-		: "=r" (res),
-		  "=r" (dummy),
-		  "=r" (addr)
-		: "0" ((signed int) 0),
-		  "1" ((unsigned int) 0xffffffff),
-		  "2" (addr),
-		  "r" (size)
+		: "=r" (res), "=r" (dummy), "=r" (addr)
+		: "0" ((signed int) 0), "1" ((unsigned int) 0xffffffff),
+		  "2" (addr), "r" (size)
 		: "$1");
 
 	return res;
 }
 
+/*
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
 extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
 {
 	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
@@ -320,11 +655,8 @@
 			".set\tat\n\t"
 			".set\treorder\n"
 			"1:"
-			: "=r" (set),
-			  "=r" (dummy)
-			: "0" (0),
-			  "1" (1 << bit),
-			  "r" (*p)
+			: "=r" (set), "=r" (dummy)
+			: "0" (0), "1" (1 << bit), "r" (*p)
 			: "$1");
 		if (set < (32 - bit))
 			return set + offset;
@@ -341,8 +673,10 @@
 #endif /* !(__MIPSEB__) */
 
 /*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
  */
 extern __inline__ unsigned long ffz(unsigned long word)
 {
@@ -370,8 +704,11 @@
 
 #ifdef __KERNEL__
 
-/*
- * ffs: find first bit set. This is defined the same way as
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
  * differs in spirit from the above ffz (man ffs).
  */
@@ -379,8 +716,10 @@
 #define ffs(x) generic_ffs(x)
 
 /*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
  */
 
 #define hweight32(x) generic_hweight32(x)
@@ -390,14 +729,12 @@
 #endif /* __KERNEL__ */
 
 #ifdef __MIPSEB__
-/* For now I steal the Sparc C versions, no need for speed, just need to
- * get it working.
- */
-/* find_next_zero_bit() finds the first zero bit in a bit string of length
- * 'size' bits, starting the search at bit 'offset'. This is largely based
- * on Linus's ALPHA routines, which are pretty portable BTW.
+/*
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
  */
-
 extern __inline__ int find_next_zero_bit(void *addr, int size, int offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
@@ -438,6 +775,18 @@
  * holds on the Sparc as it does for the ALPHA.
  */
 
+#if 0 /* Fool kernel-doc since it doesn't do macros yet */
+/*
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
+extern int find_first_zero_bit (void *addr, unsigned size);
+#endif
+
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
@@ -451,7 +800,6 @@
 	int		mask, retval, flags;
 	unsigned char	*ADDR = (unsigned char *) addr;
 
-	ADDR += nr >> 3;
 	mask = 1 << (nr & 0x07);
 	save_and_cli(flags);
 	retval = (mask & *ADDR) != 0;
diff -urN linux-2.4.6-pre8/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h
--- linux-2.4.6-pre8/include/asm-mips/bootinfo.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-mips/bootinfo.h	Mon Dec  3 22:50:39 2001
@@ -18,14 +18,23 @@
 #define MACH_GROUP_ARC		3 /* Wreckstation Tyne, rPC44, possibly other */
 #define MACH_GROUP_SNI_RM	4 /* Siemens Nixdorf RM series                */
 #define MACH_GROUP_ACN		5
-#define MACH_GROUP_SGI          6 /* Silicon Graphics workstations and servers */
+#define MACH_GROUP_SGI          6 /* Silicon Graphics                         */
 #define MACH_GROUP_COBALT       7 /* Cobalt servers		 	      */
-#define MACH_GROUP_NEC_DDB	8 /* NEC DDB */
-#define MACH_GROUP_BAGET	9 /* Baget */
-#define MACH_GROUP_ORION       10 /* CoSine Orion */
-
-#define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", \
-                      "SNI", "ACN", "SGI", "Cobalt", "NEC DDB", "Baget", "Orion" }
+#define MACH_GROUP_NEC_DDB	8 /* NEC DDB                                  */
+#define MACH_GROUP_BAGET	9 /* Baget                                    */
+#define MACH_GROUP_COSINE      10 /* CoSine Orion                             */
+#define MACH_GROUP_GALILEO     11 /* Galileo Eval Boards                      */
+#define MACH_GROUP_MOMENCO     12 /* Momentum Boards                          */
+#define MACH_GROUP_ITE         13 /* ITE Semi Eval Boards                     */
+#define MACH_GROUP_PHILIPS     14
+#define MACH_GROUP_GLOBESPAN   15 /* Globespan PVR Referrence Board           */
+#define MACH_GROUP_SIBYTE      16 /* Sibyte Eval Boards                       */
+#define MACH_GROUP_TOSHIBA     17 /* Toshiba Reference Systems TSBREF         */
+#define MACH_GROUP_ALCHEMY     18 /* Alchemy Semi Eval Boards*/
+
+#define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", "SNI", "ACN",      \
+	"SGI", "Cobalt", "NEC DDB", "Baget", "Cosine", "Galileo", "Momentum", \
+	"ITE", "Philips", "Globepspan", "SiByte", "Toshiba", "Alchemy" }
 
 /*
  * Valid machtype values for group unknown (low order halfword of mips_machtype)
@@ -87,9 +96,11 @@
 /*
  * Valid machtype for group SGI
  */
-#define MACH_SGI_INDY		0	/* R4?K and R5K Indy workstaions */
+#define MACH_SGI_INDY		0	/* R4?K and R5K Indy workstations */
+#define MACH_SGI_CHALLENGE_S	1	/* The Challenge S server */
+#define MACH_SGI_INDIGO2	2	/* The Indigo2 system */
 
-#define GROUP_SGI_NAMES { "Indy" }
+#define GROUP_SGI_NAMES { "Indy", "Challenge S", "Indigo2" }
 
 /*
  * Valid machtype for group COBALT
@@ -103,8 +114,9 @@
  */
 #define MACH_NEC_DDB5074	 0	/* NEC DDB Vrc-5074 */
 #define MACH_NEC_DDB5476         1      /* NEC DDB Vrc-5476 */
+#define MACH_NEC_DDB5477         2      /* NEC DDB Vrc-5477 */
 
-#define GROUP_NEC_DDB_NAMES { "Vrc-5074", "Vrc-5476"}
+#define GROUP_NEC_DDB_NAMES { "Vrc-5074", "Vrc-5476", "Vrc-5477"}
 
 /*
  * Valid machtype for group BAGET
@@ -115,6 +127,74 @@
 #define GROUP_BAGET_NAMES { "BT23-201", "BT23-202" }
 
 /*
+ * Cosine boards.
+ */
+#define MACH_COSINE_ORION	0
+
+#define GROUP_COSINE_NAMES { "Orion" }
+
+/*
+ * Valid machtype for group GALILEO
+ */
+#define MACH_EV96100		0	/* EV96100 */
+#define MACH_EV64120A		1	/* EV64120A */
+
+#define GROUP_GALILEO_NAMES { "EV96100" , "EV64120A" }
+
+/*
+ * Valid machtype for group MOMENCO
+ */
+#define MACH_MOMENCO_OCELOT		0
+
+#define GROUP_MOMENCO_NAMES { "Ocelot" }
+
+ 
+/*
+ * Valid machtype for group ITE
+ */
+#define MACH_QED_4N_S01B	0	/* ITE8172 based eval board */
+ 
+#define GROUP_ITE_NAMES { "QED-4N-S01B" } /* the actual board name */
+	
+/*
+ * Valid machtype for group Globespan
+ */
+#define MACH_IVR       0                  /* IVR eval board */
+
+#define GROUP_GLOBESPAN_NAMES { "IVR" }   /* the actual board name */   
+
+/*
+ * Valid machtype for group PHILIPS
+ */
+#define MACH_PHILIPS_NINO	0	/* Nino */
+#define MACH_PHILIPS_VELO	1	/* Velo */
+
+#define GROUP_PHILIPS_NAMES { "Nino" , "Velo" }
+
+/*
+ * Valid machtype for group SIBYTE
+ */
+#define MACH_SWARM              0
+
+#define GROUP_SIBYTE_NAMES {"SWARM" }
+
+/*
+ * Valid machtypes for group Toshiba
+ */
+#define MACH_PALLAS		0
+#define MACH_TOPAS		1
+#define MACH_JMR		2
+
+#define GROUP_TOSHIBA_NAMES { "Pallas", "TopasCE", "JMR" }
+
+/*
+ * Valid machtype for group Alchemy
+ */
+#define MACH_PB1000	0	         /* Au1000-based eval board */
+ 
+#define GROUP_ALCHEMY_NAMES { "PB1000" } /* the actual board name */
+
+/*
  * Valid cputype values
  */
 #define CPU_UNKNOWN		0
@@ -145,17 +225,36 @@
 #define CPU_R5000A		25
 #define CPU_R4640		26
 #define CPU_NEVADA		27	/* RM5230, RM5260 */
-#define CPU_LAST		27
+#define CPU_RM7000		28
+#define CPU_R5432		29
+#define CPU_4KC			30
+#define CPU_5KC			31
+#define CPU_R4310		32
+#define CPU_SB1			33
+#define CPU_TX3912		34
+#define CPU_TX3922		35
+#define CPU_TX3927		36
+#define CPU_AU1000		37
+#define CPU_4KEC		37
+#define CPU_4KSC		38
+#define CPU_LAST		39
 
 #define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \
         "R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC",         \
         "R4200", "R4400PC", "R4400SC", "R4400MC", "R4600", "R6000",          \
         "R6000A", "R8000", "R10000", "R4300", "R4650", "R4700", "R5000",     \
-        "R5000A", "R4640", "Nevada" }
+        "R5000A", "R4640", "Nevada", "RM7000", "R5432", "MIPS 4Kc",          \
+        "MIPS 5Kc", "R4310", "SiByte SB1", "TX3912", "TX3922", "TX3927",     \
+	"Au1000", "MIPS 4KEc", "MIPS 4KSc" }
+
+#define COMMAND_LINE_SIZE	256
+
+#define BOOT_MEM_MAP_MAX	32
+#define BOOT_MEM_RAM		1
+#define BOOT_MEM_ROM_DATA	2
+#define BOOT_MEM_RESERVED	3
 
-#define CL_SIZE      (80)
-
-#ifndef _LANGUAGE_ASSEMBLY
+#ifndef __ASSEMBLY__
 
 /*
  * Some machine parameters passed by the bootloaders. 
@@ -183,12 +282,29 @@
  * values in setup.c (or whereever suitable) so they are in
  * .data section
  */
-extern unsigned long mips_memory_upper;
-extern unsigned long mips_cputype;
+extern struct mips_cpu mips_cpu;
 extern unsigned long mips_machtype;
 extern unsigned long mips_machgroup;
 extern unsigned long mips_tlb_entries;
 
-#endif /* _LANGUAGE_ASSEMBLY */
+/*
+ * A memory map that's built upon what was determined
+ * or specified on the command line.
+ */
+struct boot_mem_map {
+	int nr_map;
+	struct {
+		unsigned long addr;	/* start of memory segment */
+		unsigned long size;	/* size of memory segment */
+		long type;		/* type of memory segment */
+	} map[BOOT_MEM_MAP_MAX];
+};
+
+extern struct boot_mem_map boot_mem_map;
+
+extern void add_memory_region(unsigned long start, unsigned long size,
+			      long type);
+
+#endif /* !__ASSEMBLY__ */
 
-#endif /* __ASM_MIPS_BOOTINFO_H */
+#endif /* _ASM_BOOTINFO_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h
--- linux-2.4.6-pre8/include/asm-mips/bugs.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/bugs.h	Mon Dec  3 22:50:39 2001
@@ -1,9 +1,9 @@
-/* $Id: bugs.h,v 1.4 1999/08/18 23:37:49 ralf Exp $
- *
+/*
  * Copyright (C) 1995  Waldorf Electronics
  * Copyright (C) 1997, 1999  Ralf Baechle
  */
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 
 /*
  * This is included by init/main.c to check for architecture-dependent bugs.
@@ -16,7 +16,7 @@
 static inline void check_wait(void)
 {
 	printk("Checking for 'wait' instruction... ");
-	switch(mips_cputype) {
+	switch(mips_cpu.cputype) {
 	case CPU_R3081:
 	case CPU_R3081E:
 		cpu_wait = r3081_wait;
@@ -30,6 +30,7 @@
 	case CPU_R4700: 
 	case CPU_R5000: 
 	case CPU_NEVADA:
+	case CPU_RM7000:
 		cpu_wait = r4k_wait;
 		printk(" available.\n");
 		break;
diff -urN linux-2.4.6-pre8/include/asm-mips/cache.h linux/include/asm-mips/cache.h
--- linux-2.4.6-pre8/include/asm-mips/cache.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/cache.h	Mon Dec  3 22:50:39 2001
@@ -1,16 +1,32 @@
-/* $Id: cache.h,v 1.4 2000/02/04 07:40:53 ralf Exp $
- *
+/*
  * 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) 1997, 1998, 1999 Ralf Baechle
+ * Copyright (C) 1997, 98, 99, 2000 Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
 #ifndef _ASM_CACHE_H
 #define _ASM_CACHE_H
 
 #include <linux/config.h>
+
+#ifndef _LANGUAGE_ASSEMBLY
+/*
+ * Descriptor for a cache
+ */
+struct cache_desc {
+	int linesz;
+	int sets;
+	int ways;
+	int flags;	/* Details like write thru/back, coherent, etc. */
+};
+#endif
+
+/*
+ * Flag definitions
+ */
+#define MIPS_CACHE_NOT_PRESENT 0x00000001
 
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R6000)
 #define L1_CACHE_BYTES		16
diff -urN linux-2.4.6-pre8/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h
--- linux-2.4.6-pre8/include/asm-mips/checksum.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/checksum.h	Mon Dec  3 22:50:39 2001
@@ -1,10 +1,9 @@
-/* $Id: checksum.h,v 1.8 2000/02/18 00:24:48 ralf Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 1998, 2001 by Ralf Baechle
  */
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
@@ -23,7 +22,7 @@
  *
  * it's best to have buff aligned on a 32-bit boundary
  */
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
 
 /*
  * this is a new version of the above that records errors it finds in *errp,
@@ -42,9 +41,9 @@
  * Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-extern inline unsigned int
-csum_and_copy_to_user (const char *src, char *dst,
-                       int len, int sum, int *err_ptr)
+extern inline unsigned int csum_and_copy_to_user (const char *src, char *dst,
+						  int len, int sum,
+						  int *err_ptr)
 {
 	sum = csum_partial(src, len, sum);
 
@@ -63,22 +62,23 @@
  * this is obsolete and will go away.
  */
 #define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
-  
+unsigned int csum_partial_copy(const char *src, char *dst, int len,
+			       unsigned int sum);
+
 /*
  *	Fold a partial checksum without adding pseudo headers
  */
 static inline unsigned short int csum_fold(unsigned int sum)
 {
-	__asm__("
-	.set	noat            
-	sll	$1,%0,16
-	addu	%0,$1
-	sltu	$1,%0,$1
-	srl	%0,%0,16
-	addu	%0,$1
-	xori	%0,0xffff
-	.set	at"
+	__asm__(
+	".set\tnoat\t\t\t# csum_fold\n\t"
+	"sll\t$1,%0,16\n\t"
+	"addu\t%0,$1\n\t"
+	"sltu\t$1,%0,$1\n\t"
+	"srl\t%0,%0,16\n\t"
+	"addu\t%0,$1\n\t"
+	"xori\t%0,0xffff\n\t"
+	".set\tat"
 	: "=r" (sum)
 	: "0" (sum)
 	: "$1");
@@ -93,7 +93,7 @@
  *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  *	Arnt Gulbrandsen.
  */
-static inline unsigned short ip_fast_csum(unsigned char * iph,
+static inline unsigned short ip_fast_csum(unsigned char *iph,
 					  unsigned int ihl)
 {
 	unsigned int sum;
@@ -102,37 +102,36 @@
 	/*
 	 * This is for 32-bit MIPS processors.
 	 */
-	__asm__ __volatile__("
-	.set	noreorder
-	.set	noat
-	lw	%0,(%1)
-	subu	%2,4
-	#blez	%2,2f
-	sll	%2,2			# delay slot
-
-	lw	%3,4(%1)
-	addu	%2,%1			# delay slot
-	addu	%0,%3
-	sltu	$1,%0,%3
-	lw	%3,8(%1)
-	addu	%0,$1
-	addu	%0,%3
-	sltu	$1,%0,%3
-	lw	%3,12(%1)
-	addu	%0,$1
-	addu	%0,%3
-	sltu	$1,%0,%3
-	addu	%0,$1
-
-1:	lw	%3,16(%1)
-	addiu	%1,4
-	addu	%0,%3
-	sltu	$1,%0,%3
-	bne	%2,%1,1b
-	addu	%0,$1			# delay slot
+	__asm__ __volatile__(
+	".set\tnoreorder\t\t\t# ip_fast_csum\n\t"
+	".set\tnoat\n\t"
+	"lw\t%0, (%1)\n\t"
+	"subu\t%2, 4\n\t"
+	"#blez\t%2, 2f\n\t"
+	" sll\t%2, 2\n\t"
+	"lw\t%3, 4(%1)\n\t"
+	"addu\t%2, %1\n\t"
+	"addu\t%0, %3\n\t"
+	"sltu\t$1, %0, %3\n\t"
+	"lw\t%3, 8(%1)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %3\n\t"
+	"sltu\t$1, %0, %3\n\t"
+	"lw\t%3, 12(%1)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %3\n\t"
+	"sltu\t$1, %0, %3\n\t"
+	"addu\t%0, $1\n"
+
+	"1:\tlw\t%3, 16(%1)\n\t"
+	"addiu\t%1, 4\n\t"
+	"addu\t%0, %3\n\t"
+	"sltu\t$1, %0, %3\n\t"
+	"bne\t%2, %1, 1b\n\t"
+	" addu\t%0, $1\n"
 
-2:	.set	at
-	.set	reorder"
+	"2:\t.set\tat\n\t"
+	".set\treorder"
 	: "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
 	: "1" (iph), "2" (ihl)
 	: "$1");
@@ -150,28 +149,28 @@
                                                unsigned short proto,
                                                unsigned int sum)
 {
-    __asm__("
-	.set	noat
-	addu	%0,%2
-	sltu	$1,%0,%2
-	addu	%0,$1
-
-	addu	%0,%3
-	sltu	$1,%0,%3
-	addu	%0,$1
-
-	addu	%0,%4
-	sltu	$1,%0,%4
-	addu	%0,$1
-	.set	at"
+	__asm__(
+	".set\tnoat\t\t\t# csum_tcpudp_nofold\n\t"
+	"addu\t%0, %2\n\t"
+	"sltu\t$1, %0, %2\n\t"
+	"addu\t%0, $1\n\t"
+
+	"addu\t%0, %3\n\t"
+	"sltu\t$1, %0, %3\n\t"
+	"addu\t%0, $1\n\t"
+
+	"addu\t%0, %4\n\t"
+	"sltu\t$1, %0, %4\n\t"
+	"addu\t%0, $1\n\t"
+	".set\tat"
 	: "=r" (sum)
 	: "0" (daddr), "r"(saddr),
 #ifdef __MIPSEL__
-	    "r" ((ntohs(len)<<16)+proto*256),
+	  "r" ((ntohs(len)<<16)+proto*256),
 #else
-	    "r" (((proto)<<16)+len),
+	  "r" (((proto)<<16)+len),
 #endif
-	    "r"(sum)
+	  "r" (sum)
 	: "$1");
 
 	return sum;
@@ -187,7 +186,7 @@
 						   unsigned short proto,
 						   unsigned int sum)
 {
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 }
 
 /*
@@ -206,64 +205,60 @@
 						     unsigned short proto,
 						     unsigned int sum) 
 {
-	__asm__("
-		.set	noreorder
-		.set	noat
-		addu	%0,%5		# proto (long in network byte order)
-		sltu	$1,%0,%5
-		addu	%0,$1
-
-		addu	%0,%6		# csum
-		sltu	$1,%0,%6
-		lw	%1,0(%2)	# four words source address
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,4(%2)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,8(%2)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,12(%2)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,0(%3)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,4(%3)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,8(%3)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-
-		lw	%1,12(%3)
-		addu	%0,$1
-		addu	%0,%1
-		sltu	$1,%0,$1
-		.set	noat
-		.set	noreorder"
-		: "=r" (sum),
-		  "=r" (proto)
-		: "r" (saddr),
-		  "r" (daddr),
-		  "0" (htonl(len)),
-		  "1" (htonl(proto)),
-		  "r"(sum)
-		: "$1");
+	__asm__(
+	".set\tnoreorder\t\t\t# csum_ipv6_magic\n\t"
+	".set\tnoat\n\t"
+	"addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t"
+	"sltu\t$1, %0, %5\n\t"
+	"addu\t%0, $1\n\t"
+
+	"addu\t%0, %6\t\t\t# csum\n\t"
+	"sltu\t$1, %0, %6\n\t"
+	"lw\t%1, 0(%2)\t\t\t# four words source address\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 4(%2)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 8(%2)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 12(%2)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 0(%3)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 4(%3)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 8(%3)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+
+	"lw\t%1, 12(%3)\n\t"
+	"addu\t%0, $1\n\t"
+	"addu\t%0, %1\n\t"
+	"sltu\t$1, %0, $1\n\t"
+	".set\tnoat\n\t"
+	".set\tnoreorder"
+	: "=r" (sum), "=r" (proto)
+	: "r" (saddr), "r" (daddr),
+	  "0" (htonl(len)), "1" (htonl(proto)), "r" (sum)
+	: "$1");
 
 	return csum_fold(sum);
 }
diff -urN linux-2.4.6-pre8/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h
--- linux-2.4.6-pre8/include/asm-mips/cpu.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/cpu.h	Mon Dec  3 22:50:39 2001
@@ -1,40 +1,132 @@
-/* $Id: cpu.h,v 1.1 1996/06/23 09:38:33 dm Exp $
+/*
  * cpu.h: Values of the PRId register used to match up
  *        various MIPS cpu types.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
-#ifndef _MIPS_CPU_H
-#define _MIPS_CPU_H
+#ifndef _ASM_CPU_H
+#define _ASM_CPU_H
+
+#include <asm/cache.h>
+/* Assigned Company values for bits 23:16 of the PRId Register  
+   (CP0 register 15, select 0).  As of the MIPS32 and MIPS64 specs from 
+   MTI, the PRId register is defined in this (backwards compatible)
+   way:
+
+  +----------------+----------------+----------------+----------------+
+  | Company Options| Company ID     | Processor ID   | Revision       |
+  +----------------+----------------+----------------+----------------+
+   31            24 23            16 15             8 7
+
+   I don't have docs for all the previous processors, but my impression is
+   that bits 16-23 have been 0 for all MIPS processors before the MIPS32/64
+   spec.  
+*/
+
+#define PRID_COMP_LEGACY       0x000000
+#define PRID_COMP_MIPS         0x010000
+#define PRID_COMP_ALCHEMY      0x030000
+/* 
+ * Don't know who should be here...QED and Sandcraft, maybe?
+ */
+#define PRID_COMP_SIBYTE       0x040000
 
 /*
  * Assigned values for the product ID register.  In order to detect a
  * certain CPU type exactly eventually additional registers may need to
- * be examined.
+ * be examined.  These are valid when 23:16 == PRID_COMP_LEGACY
+ */
+#define PRID_IMP_R2000		0x0100
+#define PRID_IMP_AU1000	0x0100
+#define PRID_IMP_R3000		0x0200		/* Same as R2000A  */
+#define PRID_IMP_R6000		0x0300		/* Same as R3000A  */
+#define PRID_IMP_R4000		0x0400
+#define PRID_IMP_R6000A		0x0600
+#define PRID_IMP_R10000		0x0900
+#define PRID_IMP_R4300		0x0b00
+#define PRID_IMP_R12000		0x0e00
+#define PRID_IMP_R8000		0x1000
+#define PRID_IMP_R4600		0x2000
+#define PRID_IMP_R4700		0x2100
+#define PRID_IMP_TX39		0x2200
+#define PRID_IMP_R4640		0x2200
+#define PRID_IMP_R4650		0x2200		/* Same as R4640 */
+#define PRID_IMP_R5000		0x2300
+#define PRID_IMP_R5432		0x5400
+#define PRID_IMP_SONIC		0x2400
+#define PRID_IMP_MAGIC		0x2500
+#define PRID_IMP_RM7000		0x2700
+#define PRID_IMP_NEVADA		0x2800		/* RM5260 ??? */
+#define PRID_IMP_4KC		0x8000
+#define PRID_IMP_5KC		0x8100
+#define PRID_IMP_4KEC		0x8400
+#define PRID_IMP_4KSC		0x8600
+
+
+#define PRID_IMP_UNKNOWN	0xff00
+
+/*
+ * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
+ */
+
+#define PRID_IMP_SB1            0x0100
+
+/*
+ * Definitions for 7:0 on legacy processors
+ */
+
+
+#define PRID_REV_R4400		0x0040
+#define PRID_REV_R3000A		0x0030
+#define PRID_REV_R3000		0x0020
+#define PRID_REV_R2000A		0x0010
+#define PRID_REV_TX3912 	0x0010
+#define PRID_REV_TX3922 	0x0030
+#define PRID_REV_TX3927 	0x0040
+
+#ifndef  _LANGUAGE_ASSEMBLY
+/*
+ * Capability and feature descriptor structure for MIPS CPU
+ */
+struct mips_cpu {
+	unsigned int processor_id;
+	unsigned int cputype;		/* Old "mips_cputype" code */
+	int isa_level;
+	int options;
+	int tlbsize;
+	struct cache_desc icache;	/* Primary I-cache */
+	struct cache_desc dcache;	/* Primary D or combined I/D cache */
+	struct cache_desc scache;	/* Secondary cache */
+	struct cache_desc tcache;	/* Tertiary/split secondary cache */
+};
+
+#endif
+
+/*
+ * ISA Level encodings
+ */
+#define MIPS_CPU_ISA_I		0x00000001
+#define MIPS_CPU_ISA_II		0x00000002
+#define MIPS_CPU_ISA_III	0x00000003
+#define MIPS_CPU_ISA_IV		0x00000004
+#define MIPS_CPU_ISA_V		0x00000005
+#define MIPS_CPU_ISA_M32	0x00000020
+#define MIPS_CPU_ISA_M64	0x00000040
+
+/*
+ * CPU Option encodings
  */
-#define PRID_IMP_R2000    0x0100
-#define PRID_IMP_R3000    0x0200
-#define PRID_IMP_R6000    0x0300
-#define PRID_IMP_R4000    0x0400
-#define PRID_IMP_R6000A   0x0600
-#define PRID_IMP_R10000   0x0900
-#define PRID_IMP_R4300    0x0b00
-#define PRID_IMP_R8000    0x1000
-#define PRID_IMP_R4600    0x2000
-#define PRID_IMP_R4700    0x2100
-#define PRID_IMP_R4640    0x2200
-#define PRID_IMP_R4650    0x2200		/* Same as R4640 */
-#define PRID_IMP_R5000    0x2300
-#define PRID_IMP_SONIC    0x2400
-#define PRID_IMP_MAGIC    0x2500
-#define PRID_IMP_RM7000   0x2700
-#define PRID_IMP_NEVADA   0x2800		/* RM5260 ??? */
-
-#define PRID_IMP_UNKNOWN  0xff00
-
-#define PRID_REV_R4400    0x0040
-#define PRID_REV_R3000A   0x0030
-#define PRID_REV_R3000    0x0020
-#define PRID_REV_R2000A   0x0010
+#define MIPS_CPU_TLB		0x00000001  /* CPU has TLB */
+/* Leave a spare bit for variant MMU types... */
+#define MIPS_CPU_4KEX		0x00000004  /* "R4K" exception model */
+#define MIPS_CPU_4KTLB		0x00000008  /* "R4K" TLB handler */
+#define MIPS_CPU_FPU		0x00000010  /* CPU has FPU */
+#define MIPS_CPU_32FPR		0x00000020  /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER	0x00000040 /* Cycle count/compare */
+#define MIPS_CPU_WATCH		0x00000080  /* watchpoint registers */
+#define MIPS_CPU_MIPS16		0x00000100  /* code compression */
+#define MIPS_CPU_DIVEC		0x00000200  /* dedicated interrupt vector */
+#define MIPS_CPU_VCE		0x00000400  /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX	0x00000800 /* Create_Dirty_Exclusive CACHE op */
 
-#endif /* !(_MIPS_CPU_H) */
+#endif /* _ASM_CPU_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/current.h linux/include/asm-mips/current.h
--- linux-2.4.6-pre8/include/asm-mips/current.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/current.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: current.h,v 1.5 1999/07/26 19:42:43 harald Exp $
- *
+/*
  * 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.
@@ -16,21 +15,5 @@
 register struct task_struct *current asm("$28");
 
 #endif /* _LANGUAGE_C */
-#ifdef _LANGUAGE_ASSEMBLY
-
-/*
- * Special variant for use by exception handlers when the stack pointer
- * is not loaded.
- */
-#define _GET_CURRENT(reg)			\
-	lui	reg, %hi(kernelsp);		\
-	.set	push;				\
-	.set	reorder;			\
-	lw	reg, %lo(kernelsp)(reg);	\
-	.set	pop;				\
-	ori	reg, 8191;			\
-	xori	reg, 8191
-
-#endif
 
 #endif /* _ASM_CURRENT_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/delay.h linux/include/asm-mips/delay.h
--- linux-2.4.6-pre8/include/asm-mips/delay.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/delay.h	Mon Dec  3 22:50:39 2001
@@ -1,17 +1,18 @@
-/* $Id: delay.h,v 1.2 1999/01/04 16:09:20 ralf Exp $
- *
+/*
  * 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 Waldorf Electronics
- * Copyright (C) 1995 - 1998 by Ralf Baechle
+ * Copyright (C) 1995 - 1998, 2001 by Ralf Baechle
  */
 #ifndef _ASM_DELAY_H
 #define _ASM_DELAY_H
 
 #include <linux/config.h>
 
+extern unsigned long loops_per_jiffy;
+
 extern __inline__ void
 __delay(unsigned long loops)
 {
@@ -34,21 +35,21 @@
  * first constant multiplications gets optimized away if the delay is
  * a constant)
  */
-extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
+extern __inline__ void __udelay(unsigned long usecs, unsigned long lpj)
 {
 	unsigned long lo;
 
-	usecs *= 0x000010c6;		/* 2**32 / 1000000 */
+	usecs *= 0x00068db8;		/* 2**32 / (1000000 / HZ) */
 	__asm__("multu\t%2,%3"
 		:"=h" (usecs), "=l" (lo)
-		:"r" (usecs),"r" (lps));
+		:"r" (usecs),"r" (lpj));
 	__delay(usecs);
 }
 
 #ifdef CONFIG_SMP
 #define __udelay_val cpu_data[smp_processor_id()].udelay_val
 #else
-#define __udelay_val loops_per_sec
+#define __udelay_val loops_per_jiffy
 #endif
 
 #define udelay(usecs) __udelay((usecs),__udelay_val)
diff -urN linux-2.4.6-pre8/include/asm-mips/div64.h linux/include/asm-mips/div64.h
--- linux-2.4.6-pre8/include/asm-mips/div64.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/div64.h	Mon Dec  3 22:50:39 2001
@@ -1,4 +1,7 @@
-/* $Id: div64.h,v 1.1 2000/01/28 23:18:43 ralf Exp $
+/*
+ * include/asm-mips/div64.h
+ * 
+ * Copyright (C) 2000  Maciej W. Rozycki
  *
  * 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
@@ -7,14 +10,104 @@
 #ifndef _ASM_DIV64_H
 #define _ASM_DIV64_H
 
+#include <asm/sgidefs.h>
+
 /*
- * Hey, we're already 64-bit, no
- * need to play games..
+ * No traps on overflows for any of these...
  */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
+
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
+
+#define do_div64_32(res, high, low, base) ({ \
+	unsigned long __quot, __mod; \
+	unsigned long __cf, __tmp, __i; \
+	\
+	__asm__(".set	push\n\t" \
+		".set	noat\n\t" \
+		".set	noreorder\n\t" \
+		"b	1f\n\t" \
+		" li	%4,0x21\n" \
+		"0:\n\t" \
+		"sll	$1,%0,0x1\n\t" \
+		"srl	%3,%0,0x1f\n\t" \
+		"or	%0,$1,$2\n\t" \
+		"sll	%1,%1,0x1\n\t" \
+		"sll	%2,%2,0x1\n" \
+		"1:\n\t" \
+		"bnez	%3,2f\n\t" \
+		"sltu	$2,%0,%z5\n\t" \
+		"bnez	$2,3f\n\t" \
+		"2:\n\t" \
+		" addiu	%4,%4,-1\n\t" \
+		"subu	%0,%0,%z5\n\t" \
+		"addiu	%2,%2,1\n" \
+		"3:\n\t" \
+		"bnez	%4,0b\n\t" \
+		" srl	$2,%1,0x1f\n\t" \
+		".set	pop" \
+		: "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+		  "=&r" (__i) \
+		: "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \
+		/* Aarrgh!  Ran out of gcc's limit on constraints... */ \
+		: "$1", "$2"); \
+	\
+	(res) = __quot; \
+	__mod; })
+
+#define do_div(n, base) ({ \
+	unsigned long long __quot; \
+	unsigned long __upper, __low, __high, __mod; \
+	\
+	__quot = (n); \
+	__high = __quot >> 32; \
+	__low = __quot; \
+	__upper = __high; \
+	\
+	if (__high) \
+		__asm__("divu	$0,%z2,%z3" \
+			: "=h" (__upper), "=l" (__high) \
+			: "Jr" (__high), "Jr" (base)); \
+	\
+	__mod = do_div64_32(__low, __upper, __low, base); \
+	\
+	__quot = __high; \
+	__quot = __quot << 32 | __low; \
+	(n) = __quot; \
+	__mod; })
+
+#else
+
+#define do_div64_32(res, high, low, base) ({ \
+	unsigned long __quot, __mod, __r0; \
+	\
+	__asm__("dsll32	%2,%z3,0\n\t" \
+		"or	%2,%2,%z4\n\t" \
+		"ddivu	$0,%2,%z5" \
+		: "=h" (__mod), "=l" (__quot), "=&r" (__r0) \
+		: "Jr" (high), "Jr" (low), "Jr" (base)); \
+	\
+	(res) = __quot; \
+	__mod; })
+
+#define do_div(n, base) ({ \
+	unsigned long long __quot; \
+	unsigned long __mod, __r0; \
+	\
+	__quot = (n); \
+	\
+	__asm__("dsll32	%2,%M3,0\n\t" \
+		"or	%2,%2,%L3\n\t" \
+		"ddivu	$0,%2,%z4\n\t" \
+		"mflo	%L1\n\t" \
+		"dsra32	%M1,%L1,0\n\t" \
+		"dsll32	%L1,%L1,0\n\t" \
+		"dsra32	%L1,%L1,0" \
+		: "=h" (__mod), "=r" (__quot), "=&r" (__r0) \
+		: "r" (n), "Jr" (base)); \
+	\
+	(n) = __quot; \
+	__mod; })
+
+#endif
 
 #endif /* _ASM_DIV64_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/elf.h linux/include/asm-mips/elf.h
--- linux-2.4.6-pre8/include/asm-mips/elf.h	Thu Jul 27 18:36:54 2000
+++ linux/include/asm-mips/elf.h	Mon Dec  3 22:50:39 2001
@@ -25,8 +25,7 @@
 	int __res = 1;							\
 	struct elfhdr *__h = (hdr);					\
 									\
-	if ((__h->e_machine != EM_MIPS) &&				\
-	    (__h->e_machine != EM_MIPS_RS4_BE))				\
+	if (__h->e_machine != EM_MIPS)					\
 		__res = 0;						\
 	if (__h->e_flags & EF_MIPS_ARCH)				\
 		__res = 0;						\
@@ -35,17 +34,7 @@
 })
 
 /* This one accepts IRIX binaries.  */
-#define irix_elf_check_arch(hdr)					\
-({									\
-	int __res = 1;							\
-	struct elfhdr *__h = (hdr);					\
-									\
-	if ((__h->e_machine != EM_MIPS) &&				\
-	    (__h->e_machine != EM_MIPS_RS4_BE))				\
-		__res = 0;						\
-									\
-	__res;								\
-})
+#define irix_elf_check_arch(hdr)	((hdr)->e_machine == EM_MIPS)
 
 /*
  * These are used to set parameters in the core dumps.
diff -urN linux-2.4.6-pre8/include/asm-mips/errno.h linux/include/asm-mips/errno.h
--- linux-2.4.6-pre8/include/asm-mips/errno.h	Thu Feb 24 22:52:30 2000
+++ linux/include/asm-mips/errno.h	Mon Dec  3 22:50:39 2001
@@ -1,11 +1,9 @@
 /*
- * include/asm-mips/errno.h
- *
  * 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) 1995, 1999 by Ralf Baechle
+ * Copyright (C) 1995, 1999, 2001 by Ralf Baechle
  */
 #ifndef _ASM_ERRNO_H
 #define _ASM_ERRNO_H
diff -urN linux-2.4.6-pre8/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h
--- linux-2.4.6-pre8/include/asm-mips/fcntl.h	Fri Sep 22 14:21:20 2000
+++ linux/include/asm-mips/fcntl.h	Mon Dec  3 22:50:39 2001
@@ -1,13 +1,12 @@
-/* $Id: fcntl.h,v 1.4 1998/09/19 19:19:36 ralf Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998 by Ralf Baechle
  */
-#ifndef __ASM_MIPS_FCNTL_H
-#define __ASM_MIPS_FCNTL_H
+#ifndef __ASM_FCNTL_H
+#define __ASM_FCNTL_H
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
@@ -44,6 +43,10 @@
 #define F_SETSIG	10	/*  for sockets. */
 #define F_GETSIG	11	/*  for sockets. */
 
+#define F_GETLK64	33	/*  using 'struct flock64' */
+#define F_SETLK64	34
+#define F_SETLKW64	35
+
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC	1	/* actually anything with low bit set goes */
 
@@ -76,10 +79,19 @@
 	short l_whence;
 	__kernel_off_t l_start;
 	__kernel_off_t l_len;
-	long  l_sysid;			/* XXXXXXXXXXXXXXXXXXXXXXXXX */
+	long  l_sysid;			/* ABI junk, unused on Linux */
 	__kernel_pid_t l_pid;
-	long  pad[4];			/* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */
+	long  pad[4];			/* ABI junk, unused on Linux */
 } flock_t;
 
+typedef struct flock64 {
+	short	l_type;
+	short	l_whence;
+	loff_t	l_start;
+	loff_t	l_len;
+	pid_t	l_pid;
+} flock64_t;
+
 #define F_LINUX_SPECIFIC_BASE	1024
-#endif /* __ASM_MIPS_FCNTL_H */
+
+#endif /* __ASM_FCNTL_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/fpu_emulator.h linux/include/asm-mips/fpu_emulator.h
--- linux-2.4.6-pre8/include/asm-mips/fpu_emulator.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/fpu_emulator.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,44 @@
+/*
+ * Definitiona for the Algorithmics FPU Emulator port into MIPS Linux
+ */
+/**************************************************************************
+ *
+ *  include/asm-mips/fpu_emulator.h
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *************************************************************************/
+/* 
+ * Further private data for which no space exists in mips_fpu_soft_struct.
+ * This should be subsumed into the mips_fpu_soft_struct structure as
+ * defined in processor.h as soon as the absurd wired absolute assembler
+ * offsets become dynamic at compile time.
+ */
+
+struct mips_fpu_emulator_private {
+	unsigned int eir;
+	struct {
+		unsigned int emulated;
+		unsigned int loads;
+		unsigned int stores;
+		unsigned int cp1ops;
+		unsigned int cp1xops;
+		unsigned int errors;
+	} stats;
+};
diff -urN linux-2.4.6-pre8/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h
--- linux-2.4.6-pre8/include/asm-mips/hardirq.h	Fri Aug  4 16:15:37 2000
+++ linux/include/asm-mips/hardirq.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: hardirq.h,v 1.8 2000/03/02 02:37:13 ralf Exp $
- *
+/*
  * 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.
@@ -13,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
+#include <linux/spinlock.h>
 
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
@@ -38,14 +38,60 @@
 #define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
 #define hardirq_endlock(cpu)	do { } while (0)
 
-#define irq_enter(cpu)		(local_irq_count(cpu)++)
-#define irq_exit(cpu)		(local_irq_count(cpu)--)
+#define irq_enter(cpu, irq)	(local_irq_count(cpu)++)
+#define irq_exit(cpu, irq)	(local_irq_count(cpu)--)
 
 #define synchronize_irq()	barrier();
 
 #else
 
-#error No habla MIPS SMP
+#include <asm/atomic.h>
+#include <linux/spinlock.h>
+#include <asm/smp.h>
+
+extern int global_irq_holder;
+extern spinlock_t global_irq_lock;
+
+static inline int irqs_running (void)
+{
+	int i;
+
+	for (i = 0; i < smp_num_cpus; i++)
+		if (local_irq_count(i))
+			return 1;
+	return 0;
+}
+
+static inline void release_irqlock(int cpu)
+{
+	/* if we didn't own the irq lock, just ignore.. */
+	if (global_irq_holder == cpu) {
+		global_irq_holder = NO_PROC_ID;
+		spin_unlock(&global_irq_lock);
+	}
+}
+
+static inline int hardirq_trylock(int cpu)
+{
+	return !local_irq_count(cpu) && !spin_is_locked(&global_irq_lock);
+}
+
+#define hardirq_endlock(cpu)	do { } while (0)
+
+static inline void irq_enter(int cpu, int irq)
+{
+	++local_irq_count(cpu);
+
+	while (spin_is_locked(&global_irq_lock))
+		barrier();
+}
+
+static inline void irq_exit(int cpu, int irq)
+{
+	--local_irq_count(cpu);
+}
+
+extern void synchronize_irq(void);
 
 #endif /* CONFIG_SMP */
 #endif /* _ASM_HARDIRQ_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/hdreg.h linux/include/asm-mips/hdreg.h
--- linux-2.4.6-pre8/include/asm-mips/hdreg.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/hdreg.h	Mon Dec  3 22:50:39 2001
@@ -1,18 +1,15 @@
-/* $Id: hdreg.h,v 1.4 1998/05/08 21:05:26 davem Exp $
- *
- *  linux/include/asm-mips/hdreg.h
- *
+/*
  *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ *  Copyright (C) 2001 Ralf Baechle
  */
 
 /*
  *  This file contains the MIPS architecture specific IDE code.
  */
 
-#ifndef __ASM_MIPS_HDREG_H
-#define __ASM_MIPS_HDREG_H
-
-typedef unsigned short ide_ioreg_t;
+#ifndef _ASM_HDREG_H
+#define _ASM_HDREG_H
 
-#endif /* __ASM_MIPS_HDREG_H */
+typedef unsigned long ide_ioreg_t;
 
+#endif /* _ASM_HDREG_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/hw_irq.h linux/include/asm-mips/hw_irq.h
--- linux-2.4.6-pre8/include/asm-mips/hw_irq.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/hw_irq.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,16 @@
-/* This exists merely to satisfy <linux/irq.h>.  There is
-   nothing that would go here of general interest.
+/*
+ * 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) 2000, 2001 by Ralf Baechle
+ */
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
 
-   Everything of consequence is in arch/alpha/kernel/irq_impl.h,
-   to be used only in arch/alpha/kernel/.  */
+/* This may not be apropriate for all machines, we'll see ...  */
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+{
+}
+
+#endif /* _ASM_HW_IRQ_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/ide.h linux/include/asm-mips/ide.h
--- linux-2.4.6-pre8/include/asm-mips/ide.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/ide.h	Mon Dec  3 22:50:39 2001
@@ -8,16 +8,13 @@
  * Copyright (C) 1994-1996  Linus Torvalds & authors
  */
 
-/*
- *  This file contains the MIPS architecture specific IDE code.
- */
-
 #ifndef __ASM_IDE_H
 #define __ASM_IDE_H
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <asm/io.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
@@ -93,13 +90,21 @@
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
+#ifdef __MIPSEB__
+		unsigned bit7		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* using LBA instead of CHS */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned unit		: 1;	/* drive select number, 0 or 1 */
+		unsigned head		: 4;	/* always zeros here */
+#else
 		unsigned head		: 4;	/* always zeros here */
 		unsigned unit		: 1;	/* drive select number, 0 or 1 */
 		unsigned bit5		: 1;	/* always 1 */
 		unsigned lba		: 1;	/* using LBA instead of CHS */
 		unsigned bit7		: 1;	/* always 1 */
+#endif
 	} b;
-	} select_t;
+} select_t;
 
 static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int,void *, struct pt_regs *),
 			unsigned long flags, const char *device, void *dev_id)
@@ -129,11 +134,96 @@
 	ide_ops->ide_release_region(from, extent);
 }
 
+#undef  SUPPORT_VLB_SYNC
+#define SUPPORT_VLB_SYNC 0
+
+#if defined(__MIPSEB__)
+
+#define T_CHAR          (0x0000)        /* char:  don't touch  */
+#define T_SHORT         (0x4000)        /* short: 12 -> 21     */
+#define T_INT           (0x8000)        /* int:   1234 -> 4321 */
+#define T_TEXT          (0xc000)        /* text:  12 -> 21     */
+
+#define T_MASK_TYPE     (0xc000)
+#define T_MASK_COUNT    (0x3fff)
+
+#define D_CHAR(cnt)     (T_CHAR  | (cnt))
+#define D_SHORT(cnt)    (T_SHORT | (cnt))
+#define D_INT(cnt)      (T_INT   | (cnt))
+#define D_TEXT(cnt)     (T_TEXT  | (cnt))
+
+static u_short driveid_types[] = {
+	D_SHORT(10),	/* config - vendor2 */
+	D_TEXT(20),	/* serial_no */
+	D_SHORT(3),	/* buf_type - ecc_bytes */
+	D_TEXT(48),	/* fw_rev - model */
+	D_CHAR(2),	/* max_multsect - vendor3 */
+	D_SHORT(1),	/* dword_io */
+	D_CHAR(2),	/* vendor4 - capability */
+	D_SHORT(1),	/* reserved50 */
+	D_CHAR(4),	/* vendor5 - tDMA */
+	D_SHORT(4),	/* field_valid - cur_sectors */
+	D_INT(1),	/* cur_capacity */
+	D_CHAR(2),	/* multsect - multsect_valid */
+	D_INT(1),	/* lba_capacity */
+	D_SHORT(194)	/* dma_1word - reservedyy */
+};
+
+#define num_driveid_types       (sizeof(driveid_types)/sizeof(*driveid_types))
+
+static __inline__ void ide_fix_driveid(struct hd_driveid *id)
+{
+	u_char *p = (u_char *)id;
+	int i, j, cnt;
+	u_char t;
+
+	for (i = 0; i < num_driveid_types; i++) {
+		cnt = driveid_types[i] & T_MASK_COUNT;
+		switch (driveid_types[i] & T_MASK_TYPE) {
+		case T_CHAR:
+			p += cnt;
+			break;
+		case T_SHORT:
+			for (j = 0; j < cnt; j++) {
+				t = p[0];
+				p[0] = p[1];
+				p[1] = t;
+				p += 2;
+			}
+			break;
+		case T_INT:
+			for (j = 0; j < cnt; j++) {
+				t = p[0];
+				p[0] = p[3];
+				p[3] = t;
+				t = p[1];
+				p[1] = p[2];
+				p[2] = t;
+				p += 4;
+			}
+			break;
+		case T_TEXT:
+			for (j = 0; j < cnt; j += 2) {
+				t = p[0];
+				p[0] = p[1];
+				p[1] = t;
+				p += 2;
+			}
+			break;
+		};
+	}
+}
+
+#else /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__)  */
+
+#define ide_fix_driveid(id)		do {} while (0)
+
+#endif
+
 /*
  * The following are not needed for the non-m68k ports
  */
 #define ide_ack_intr(hwif)		(1)
-#define ide_fix_driveid(id)		do {} while (0)
 #define ide_release_lock(lock)		do {} while (0)
 #define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
diff -urN linux-2.4.6-pre8/include/asm-mips/inst.h linux/include/asm-mips/inst.h
--- linux-2.4.6-pre8/include/asm-mips/inst.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/inst.h	Mon Dec  3 22:50:39 2001
@@ -5,10 +5,10 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 2000 by Ralf Baechle
  */
-#ifndef __ASM_MIPS_INST_H
-#define __ASM_MIPS_INST_H
+#ifndef _ASM_INST_H
+#define _ASM_INST_H
 
 /*
  * Major opcodes; before MIPS IV cop1x was called cop3.
@@ -21,7 +21,7 @@
 	cop0_op, cop1_op, cop2_op, cop1x_op,
 	beql_op, bnel_op, blezl_op, bgtzl_op,
 	daddi_op, daddiu_op, ldl_op, ldr_op,
-	major_1c_op, major_1d_op, major_1e_op, major_1f_op,
+	major_1c_op, jalx_op, major_1e_op, major_1f_op,
 	lb_op, lh_op, lwl_op, lw_op,
 	lbu_op, lhu_op, lwr_op, lwu_op,
 	sb_op, sh_op, swl_op, sw_op,
@@ -80,6 +80,13 @@
 };
 
 /*
+ * rt field of cop.bc_op opcodes
+ */
+enum bcop_op {
+	bcf_op, bct_op, bcfl_op, bctl_op
+};
+
+/*
  * func field of cop0 coi opcodes.
  */
 enum cop0_coi_func {
@@ -301,4 +308,64 @@
         struct ma_format ma_format;
 };
 
-#endif /* __ASM_MIPS_INST_H */
+/* HACHACHAHCAHC ...  */
+
+/* In case some other massaging is needed, keep MIPSInst as wrapper */
+
+#define MIPSInst(x) x
+
+#define I_OPCODE_SFT	26
+#define MIPSInst_OPCODE(x) (MIPSInst(x) >> I_OPCODE_SFT)
+
+#define I_JTARGET_SFT	0
+#define MIPSInst_JTARGET(x) (MIPSInst(x) & 0x03ffffff)
+
+#define I_RS_SFT	21
+#define MIPSInst_RS(x) ((MIPSInst(x) & 0x03e00000) >> I_RS_SFT)
+
+#define I_RT_SFT	16
+#define MIPSInst_RT(x) ((MIPSInst(x) & 0x001f0000) >> I_RT_SFT)
+
+#define I_IMM_SFT	0
+#define MIPSInst_SIMM(x) ((int)((short)(MIPSInst(x) & 0xffff)))
+#define MIPSInst_UIMM(x) (MIPSInst(x) & 0xffff)
+
+#define I_CACHEOP_SFT	18
+#define MIPSInst_CACHEOP(x) ((MIPSInst(x) & 0x001c0000) >> I_CACHEOP_SFT)
+
+#define I_CACHESEL_SFT	16
+#define MIPSInst_CACHESEL(x) ((MIPSInst(x) & 0x00030000) >> I_CACHESEL_SFT)
+
+#define I_RD_SFT	11
+#define MIPSInst_RD(x) ((MIPSInst(x) & 0x0000f800) >> I_RD_SFT)
+
+#define I_RE_SFT	6
+#define MIPSInst_RE(x) ((MIPSInst(x) & 0x000007c0) >> I_RE_SFT)
+
+#define I_FUNC_SFT	0
+#define MIPSInst_FUNC(x) (MIPSInst(x) & 0x0000003f)
+
+#define I_FFMT_SFT	21
+#define MIPSInst_FFMT(x) ((MIPSInst(x) & 0x01e00000) >> I_FFMT_SFT)
+
+#define I_FT_SFT	16
+#define MIPSInst_FT(x) ((MIPSInst(x) & 0x001f0000) >> I_FT_SFT)
+
+#define I_FS_SFT	11
+#define MIPSInst_FS(x) ((MIPSInst(x) & 0x0000f800) >> I_FS_SFT)
+
+#define I_FD_SFT	6
+#define MIPSInst_FD(x) ((MIPSInst(x) & 0x000007c0) >> I_FD_SFT)
+
+#define I_FR_SFT	21
+#define MIPSInst_FR(x) ((MIPSInst(x) & 0x03e00000) >> I_FR_SFT)
+
+#define I_FMA_FUNC_SFT	2
+#define MIPSInst_FMA_FUNC(x) ((MIPSInst(x) & 0x0000003c) >> I_FMA_FUNC_SFT)
+
+#define I_FMA_FFMT_SFT	0
+#define MIPSInst_FMA_FFMT(x) (MIPSInst(x) & 0x00000003)
+
+typedef unsigned int mips_instruction;
+
+#endif /* _ASM_INST_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/io.h linux/include/asm-mips/io.h
--- linux-2.4.6-pre8/include/asm-mips/io.h	Mon Feb 28 07:18:20 2000
+++ linux/include/asm-mips/io.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: io.h,v 1.13 2000/02/24 00:13:19 ralf Exp $
- *
+/*
  * 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.
@@ -7,16 +6,38 @@
  * Copyright (C) 1994, 1995 Waldorf GmbH
  * Copyright (C) 1994 - 2000 Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2000 FSMLabs, Inc.
  */
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
+#include <linux/config.h>
+#include <linux/pagemap.h>
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+
 /*
  * Slowdown I/O port space accesses for antique hardware.
  */
 #undef CONF_SLOWDOWN_IO
 
-#include <asm/addrspace.h>
+/*
+ * Sane hardware offers swapping of I/O space accesses in hardware; less
+ * sane hardware forces software to fiddle with this ...
+ */
+#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__)
+
+#define __ioswab8(x) (x)
+#define __ioswab16(x) swab16(x)
+#define __ioswab32(x) swab32(x)
+
+#else
+
+#define __ioswab8(x) (x)
+#define __ioswab16(x) (x)
+#define __ioswab32(x) (x)
+
+#endif
 
 /*
  * This file contains the definitions for the MIPS counterpart of the
@@ -91,9 +112,6 @@
 	return (void *)KSEG0ADDR(address);
 }
 
-extern void * ioremap(unsigned long phys_addr, unsigned long size);
-extern void iounmap(void *addr);
-
 /*
  * IO bus memory addresses are also 1:1 with the physical address
  */
@@ -113,54 +131,35 @@
  */
 extern unsigned long isa_slot_offset;
 
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the x86 architecture, we just read/write the
- * memory location directly.
- *
- * On MIPS, we have the whole physical address space mapped at all
- * times, so "ioremap()" and "iounmap()" do not need to do anything.
- * (This isn't true for all machines but we still handle these cases
- * with wired TLB entries anyway ...)
- *
- * We cheat a bit and always return uncachable areas until we've fixed
- * the drivers to handle caching properly.
- */
-extern inline void * ioremap(unsigned long offset, unsigned long size)
-{
-	return (void *) KSEG1ADDR(offset);
-}
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
-/*
- * This one maps high address device memory and turns off caching for that area.
- * it's useful if some control registers are in such an area and write combining
- * or read caching is not desirable:
- */
-extern inline void * ioremap_nocache (unsigned long offset, unsigned long size)
+extern inline void *ioremap(unsigned long offset, unsigned long size)
 {
-	return (void *) KSEG1ADDR(offset);
+	return __ioremap(offset, size, _CACHE_UNCACHED);
 }
 
-extern inline void iounmap(void *addr)
+extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
 {
+	return __ioremap(offset, size, _CACHE_UNCACHED);
 }
 
+extern void iounmap(void *addr);
+
 /*
  * XXX We need system specific versions of these to handle EISA address bits
  * 24-31 on SNI.
  * XXX more SNI hacks.
  */
 #define readb(addr) (*(volatile unsigned char *)(addr))
-#define readw(addr) (*(volatile unsigned short *)(addr))
-#define readl(addr) (*(volatile unsigned int *)(addr))
+#define readw(addr) __ioswab16((*(volatile unsigned short *)(addr)))
+#define readl(addr) __ioswab32((*(volatile unsigned int *)(addr)))
 #define __raw_readb readb
 #define __raw_readw readw
 #define __raw_readl readl
 
 #define writeb(b,addr) (*(volatile unsigned char *)(addr)) = (b)
-#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (b)
-#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (b)
+#define writew(b,addr) (*(volatile unsigned short *)(addr)) = (__ioswab16(b))
+#define writel(b,addr) (*(volatile unsigned int *)(addr)) = (__ioswab32(b))
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
@@ -226,12 +225,12 @@
 #define __OUT2(m) \
 __asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
 
-#define __OUT(m,s) \
-__OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); } \
-__OUT1(s##c) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); } \
-__OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (mips_io_port_base+port)); \
+#define __OUT(m,s,w) \
+__OUT1(s) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); } \
+__OUT1(s##c) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); } \
+__OUT1(s##_p) __OUT2(m) : : "r" (__ioswab##w(value)), "i" (0), "r" (mips_io_port_base+port)); \
 	SLOW_DOWN_IO; } \
-__OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base)); \
+__OUT1(s##c_p) __OUT2(m) : : "r" (__ioswab##w(value)), "ir" (port), "r" (mips_io_port_base)); \
 	SLOW_DOWN_IO; }
 
 #define __IN1(t,s) \
@@ -243,11 +242,11 @@
 #define __IN2(m) \
 __asm__ __volatile__ ("l" #m "\t%0,%1(%2)"
 
-#define __IN(t,m,s) \
-__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return _v; } \
-__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return _v; } \
-__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return _v; } \
-__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return _v; }
+#define __IN(t,m,s,w) \
+__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); return __ioswab##w(_v); } \
+__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); return __ioswab##w(_v); } \
+__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SLOW_DOWN_IO; return __ioswab##w(_v); } \
+__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return __ioswab##w(_v); }
 
 #define __INS1(s) \
 extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
@@ -268,11 +267,13 @@
 #define __INS(m,s,i) \
 __INS1(s) __INS2(m) \
 	: "=r" (addr), "=r" (count) \
-	: "0" (addr), "1" (count), "i" (0), "r" (mips_io_port_base+port), "I" (i) \
+	: "0" (addr), "1" (count), "i" (0), \
+	  "r" (mips_io_port_base+port), "I" (i) \
 	: "$1");} \
 __INS1(s##c) __INS2(m) \
 	: "=r" (addr), "=r" (count) \
-	: "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \
+	: "0" (addr), "1" (count), "ir" (port), \
+	  "r" (mips_io_port_base), "I" (i) \
 	: "$1");}
 
 #define __OUTS1(s) \
@@ -301,13 +302,13 @@
 	: "0" (addr), "1" (count), "ir" (port), "r" (mips_io_port_base), "I" (i) \
 	: "$1");}
 
-__IN(unsigned char,b,b)
-__IN(unsigned short,h,w)
-__IN(unsigned int,w,l)
-
-__OUT(b,b)
-__OUT(h,w)
-__OUT(w,l)
+__IN(unsigned char,b,b,8)
+__IN(unsigned short,h,w,16)
+__IN(unsigned int,w,l,32)
+
+__OUT(b,b,8)
+__OUT(h,w,16)
+__OUT(w,l,32)
 
 __INS(b,b,1)
 __INS(h,w,2)
@@ -316,6 +317,7 @@
 __OUTS(b,b,1)
 __OUTS(h,w,2)
 __OUTS(w,l,4)
+
 
 /*
  * Note that due to the way __builtin_constant_p() works, you
diff -urN linux-2.4.6-pre8/include/asm-mips/ioctl.h linux/include/asm-mips/ioctl.h
--- linux-2.4.6-pre8/include/asm-mips/ioctl.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/ioctl.h	Mon Dec  3 22:50:39 2001
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 2001 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_IOCTL_H
 #define __ASM_MIPS_IOCTL_H
@@ -40,11 +40,6 @@
 #define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
 
 /*
- * We to additionally limit parameters to a maximum 255 bytes.
- */
-#define _IOC_SLMASK	0xff
-
-/*
  * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
  * And this turns out useful to catch old ioctl numbers in header
  * files for us.
@@ -65,7 +60,7 @@
 	(((dir)  << _IOC_DIRSHIFT) | \
 	 ((type) << _IOC_TYPESHIFT) | \
 	 ((nr)   << _IOC_NRSHIFT) | \
-	 (((size) & _IOC_SLMASK) << _IOC_SIZESHIFT))
+	 ((size) << _IOC_SIZESHIFT))
 
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
diff -urN linux-2.4.6-pre8/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- linux-2.4.6-pre8/include/asm-mips/ioctls.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/ioctls.h	Mon Dec  3 22:50:39 2001
@@ -58,6 +58,7 @@
 #define FIONCLEX	0x6602		/* these numbers need to be adjusted. */
 #define FIOASYNC	0x667d
 #define FIONBIO		0x667e
+#define FIOQSIZE	0x667f
 
 #if defined(__USE_MISC) || defined (__KERNEL__)
 #define TIOCGLTC	(tIOC | 116)		/* get special local chars */
diff -urN linux-2.4.6-pre8/include/asm-mips/irq.h linux/include/asm-mips/irq.h
--- linux-2.4.6-pre8/include/asm-mips/irq.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/irq.h	Mon Dec  3 22:50:39 2001
@@ -1,25 +1,39 @@
-/* $Id: irq.h,v 1.6 2000/01/26 00:07:45 ralf Exp $
- *
+/*
  * 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 Waldorf GMBH, written by Ralf Baechle
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 by Ralf Baechle
  */
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
-#define NR_IRQS 64
+#include <linux/config.h>
+
+#define NR_IRQS 64		/* Largest number of ints of all machines.  */
 
 #define TIMER_IRQ 0
 
-extern int (*irq_cannonicalize)(int irq);
+#ifdef CONFIG_I8259
+static inline int irq_cannonicalize(int irq)
+{
+	return ((irq == 2) ? 9 : irq);
+}
+#else
+#define irq_cannonicalize(irq) (irq)	/* Sane hardware, sane code ... */
+#endif
 
 struct irqaction;
 extern int i8259_setup_irq(int irq, struct irqaction * new);
 extern void disable_irq(unsigned int);
+
+#ifdef CONFIG_ROTTEN_IRQ
 #define disable_irq_nosync	disable_irq
+#else
+extern void disable_irq_nosync(unsigned int);
+#endif
+
 extern void enable_irq(unsigned int);
 
 /* Machine specific interrupt initialization  */
diff -urN linux-2.4.6-pre8/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h
--- linux-2.4.6-pre8/include/asm-mips/jazzdma.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/jazzdma.h	Mon Dec  3 22:50:39 2001
@@ -1,29 +1,28 @@
 /*
  * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
- *
- * $Id:$
  */
-#ifndef __ASM_MIPS_JAZZDMA_H
-#define __ASM_MIPS_JAZZDMA_H
+#ifndef _ASM_JAZZDMA_H
+#define _ASM_JAZZDMA_H
 
 /*
  * Prototypes and macros
  */
-unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end);
-unsigned long vdma_alloc(unsigned long paddr, unsigned long size);
-int vdma_free(unsigned long laddr);
-int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size);
-unsigned long vdma_phys2log(unsigned long paddr);
-unsigned long vdma_log2phys(unsigned long laddr);
-void vdma_stats(void);		/* for debugging only */
-
-void vdma_enable(int channel);
-void vdma_disable(int channel);
-void vdma_set_mode(int channel, int mode);
-void vdma_set_addr(int channel, long addr);
-void vdma_set_count(int channel, int count);
-int vdma_get_residue(int channel);
-int vdma_get_enable(int channel);
+extern void vdma_init(void);
+extern unsigned long vdma_alloc(unsigned long paddr, unsigned long size);
+extern int vdma_free(unsigned long laddr);
+extern int vdma_remap(unsigned long laddr, unsigned long paddr,
+                      unsigned long size);
+extern unsigned long vdma_phys2log(unsigned long paddr);
+extern unsigned long vdma_log2phys(unsigned long laddr);
+extern void vdma_stats(void);		/* for debugging only */
+
+extern void vdma_enable(int channel);
+extern void vdma_disable(int channel);
+extern void vdma_set_mode(int channel, int mode);
+extern void vdma_set_addr(int channel, long addr);
+extern void vdma_set_count(int channel, int count);
+extern int vdma_get_residue(int channel);
+extern int vdma_get_enable(int channel);
 
 /*
  * some definitions used by the driver functions
@@ -49,8 +48,7 @@
 /*
  * VDMA pagetable entry description
  */
-typedef volatile struct VDMA_PGTBL_ENTRY
-{
+typedef volatile struct VDMA_PGTBL_ENTRY {
 	unsigned int frame;		/* physical frame no. */
 	unsigned int owner;		/* owner of this entry (0=free) */
 } VDMA_PGTBL_ENTRY;
@@ -95,4 +93,4 @@
 #define R4030_MODE_BURST         (1<<6)	/* Rev. 2 only */
 #define R4030_MODE_FAST_ACK      (1<<7)	/* Rev. 2 only */
 
-#endif /* __ASM_MIPS_JAZZDMA_H */
+#endif /* _ASM_JAZZDMA_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h
--- linux-2.4.6-pre8/include/asm-mips/keyboard.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-mips/keyboard.h	Mon Dec  3 22:50:39 2001
@@ -13,10 +13,13 @@
 
 #include <linux/delay.h>
 #include <linux/ioport.h>
+#include <linux/config.h>
 #include <asm/bootinfo.h>
 
 #define DISABLE_KBD_DURING_INTERRUPTS 0
 
+#ifdef CONFIG_PC_KEYB
+
 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,
@@ -34,6 +37,19 @@
 #define kbd_leds		pckbd_leds
 #define kbd_init_hw		pckbd_init_hw
 #define kbd_sysrq_xlate         pckbd_sysrq_xlate
+
+#else
+
+extern int kbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int kbd_getkeycode(unsigned int scancode);
+extern int kbd_translate(unsigned char scancode, unsigned char *keycode,
+	char raw_mode);
+extern char kbd_unexpected_up(unsigned char keycode);
+extern void kbd_leds(unsigned char leds);
+extern void kbd_init_hw(void);
+extern unsigned char *kbd_sysrq_xlate;
+
+#endif
 
 #define SYSRQ_KEY 0x54
 
diff -urN linux-2.4.6-pre8/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h
--- linux-2.4.6-pre8/include/asm-mips/mc146818rtc.h	Fri Aug  4 18:31:19 2000
+++ linux/include/asm-mips/mc146818rtc.h	Mon Dec  3 22:50:39 2001
@@ -14,8 +14,12 @@
 #include <asm/io.h>
 
 #ifndef RTC_PORT
+#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
+#define RTC_PORT(x)	(0x14014800 + (x))
+#else
 #define RTC_PORT(x)	(0x70 + (x))
 #endif
+#endif
 
 /*
  * The yet supported machines all access the RTC index register via
@@ -45,8 +49,13 @@
 
 #ifdef CONFIG_DECSTATION
 #define RTC_IRQ 0
+#elif defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
+#include <asm/it8172/it8172_int.h>
+#define RTC_IRQ	IT8172_RTC_IRQ
 #else
 #define RTC_IRQ	8
 #endif
+
+#define RTC_DEC_YEAR	0x3f	/* Where we store the real year on DECs.  */
 
 #endif /* _ASM_MC146818RTC_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/mips32_cache.h linux/include/asm-mips/mips32_cache.h
--- linux-2.4.6-pre8/include/asm-mips/mips32_cache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/mips32_cache.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,288 @@
+/*
+ * mips32_cache.h
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Inline assembly cache operations.
+ * 
+ * This file is the original r4cache.c file with modification that makes the
+ * cache handling more generic.
+ *
+ * FIXME: Handle split L2 caches.
+ *
+ */
+#ifndef _MIPS_R4KCACHE_H
+#define _MIPS_R4KCACHE_H
+
+#include <asm/asm.h>
+#include <asm/cacheops.h>
+
+extern inline void flush_icache_line_indexed(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Index_Invalidate_I));
+}
+
+extern inline void flush_dcache_line_indexed(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Index_Writeback_Inv_D));
+}
+
+extern inline void flush_scache_line_indexed(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Index_Writeback_Inv_SD));
+}
+
+extern inline void flush_icache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Invalidate_I));
+}
+
+extern inline void flush_dcache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Writeback_Inv_D));
+}
+
+extern inline void invalidate_dcache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Invalidate_D));
+}
+
+extern inline void invalidate_scache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Invalidate_SD));
+}
+
+extern inline void flush_scache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n\t"
+		"cache %1, (%0)\n\t"
+		".set mips0\n\t"
+		".set reorder"
+		:
+		: "r" (addr),
+		  "i" (Hit_Writeback_Inv_SD));
+}
+
+/*
+ * The next two are for badland addresses like signal trampolines.
+ */
+extern inline void protected_flush_icache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n"
+		"1:\tcache %1,(%0)\n"
+		"2:\t.set mips0\n\t"
+		".set reorder\n\t"
+		".section\t__ex_table,\"a\"\n\t"
+		STR(PTR)"\t1b,2b\n\t"
+		".previous"
+		:
+		: "r" (addr),
+		  "i" (Hit_Invalidate_I));
+}
+
+extern inline void protected_writeback_dcache_line(unsigned long addr)
+{
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		".set mips3\n"
+		"1:\tcache %1,(%0)\n"
+		"2:\t.set mips0\n\t"
+		".set reorder\n\t"
+		".section\t__ex_table,\"a\"\n\t"
+		STR(PTR)"\t1b,2b\n\t"
+		".previous"
+		:
+		: "r" (addr),
+		  "i" (Hit_Writeback_D));
+}
+
+#define cache_unroll(base,op)	        	\
+	__asm__ __volatile__("	         	\
+		.set noreorder;		        \
+		.set mips3;		        \
+                cache %1, (%0);	                \
+		.set mips0;			\
+		.set reorder"			\
+		:				\
+		: "r" (base),			\
+		  "i" (op));
+
+
+extern inline void blast_dcache(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + dcache_size);
+
+	while(start < end) {
+		cache_unroll(start,Index_Writeback_Inv_D);
+		start += dc_lsize;
+	}
+}
+
+extern inline void blast_dcache_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		cache_unroll(start,Hit_Writeback_Inv_D);
+		start += dc_lsize;
+	}
+}
+
+extern inline void blast_dcache_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		cache_unroll(start,Index_Writeback_Inv_D);
+		start += dc_lsize;
+	}
+}
+
+extern inline void blast_icache(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + icache_size);
+
+	while(start < end) {
+		cache_unroll(start,Index_Invalidate_I);
+		start += ic_lsize;
+	}
+}
+
+extern inline void blast_icache_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		cache_unroll(start,Hit_Invalidate_I);
+		start += ic_lsize;
+	}
+}
+
+extern inline void blast_icache_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = (start + PAGE_SIZE);
+
+	while(start < end) {
+		cache_unroll(start,Index_Invalidate_I);
+		start += ic_lsize;
+	}
+}
+
+extern inline void blast_scache(void)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = KSEG0 + scache_size;
+
+	while(start < end) {
+		cache_unroll(start,Index_Writeback_Inv_SD);
+		start += sc_lsize;
+	}
+}
+
+extern inline void blast_scache_page(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		cache_unroll(start,Hit_Writeback_Inv_SD);
+		start += sc_lsize;
+	}
+}
+
+extern inline void blast_scache_page_indexed(unsigned long page)
+{
+	unsigned long start = page;
+	unsigned long end = page + PAGE_SIZE;
+
+	while(start < end) {
+		cache_unroll(start,Index_Writeback_Inv_SD);
+		start += sc_lsize;
+	}
+}
+
+#endif /* !(_MIPS_R4KCACHE_H) */
diff -urN linux-2.4.6-pre8/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- linux-2.4.6-pre8/include/asm-mips/mipsregs.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-mips/mipsregs.h	Mon Dec  3 22:50:39 2001
@@ -1,14 +1,16 @@
-/* $Id: mipsregs.h,v 1.6 1999/07/26 19:42:43 harald Exp $
- *
+/*
  * 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, 1995, 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
+ * Copyright (C) 2000 Silicon Graphics, Inc.
  * Modified for further R[236]000 support by Paul M. Antoine, 1996.
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  */
-#ifndef __ASM_MIPS_MIPSREGS_H
-#define __ASM_MIPS_MIPSREGS_H
+#ifndef _ASM_MIPSREGS_H
+#define _ASM_MIPSREGS_H
 
 #include <linux/linkage.h>
 
@@ -70,6 +72,12 @@
 #define CP0_IWATCH $18
 #define CP0_DWATCH $19
 
+/* 
+ * Coprocessor 0 Set 1 register names
+ */
+#define CP0_S1_DERRADDR0  $26
+#define CP0_S1_DERRADDR1  $27
+#define CP0_S1_INTCONTROL $20
 /*
  * Coprocessor 1 (FPU) register names
  */
@@ -77,6 +85,58 @@
 #define CP1_STATUS     $31
 
 /*
+ * FPU Status Register Values
+ */
+/*
+ * Status Register Values
+ */
+
+#define FPU_CSR_FLUSH   0x01000000      /* flush denormalised results to 0 */
+#define FPU_CSR_COND    0x00800000      /* $fcc0 */
+#define FPU_CSR_COND0   0x00800000      /* $fcc0 */
+#define FPU_CSR_COND1   0x02000000      /* $fcc1 */
+#define FPU_CSR_COND2   0x04000000      /* $fcc2 */
+#define FPU_CSR_COND3   0x08000000      /* $fcc3 */
+#define FPU_CSR_COND4   0x10000000      /* $fcc4 */
+#define FPU_CSR_COND5   0x20000000      /* $fcc5 */
+#define FPU_CSR_COND6   0x40000000      /* $fcc6 */
+#define FPU_CSR_COND7   0x80000000      /* $fcc7 */
+
+/*
+ * X the exception cause indicator
+ * E the exception enable
+ * S the sticky/flag bit
+*/
+#define FPU_CSR_ALL_X 0x0003f000
+#define FPU_CSR_UNI_X   0x00020000
+#define FPU_CSR_INV_X   0x00010000
+#define FPU_CSR_DIV_X   0x00008000
+#define FPU_CSR_OVF_X   0x00004000
+#define FPU_CSR_UDF_X   0x00002000
+#define FPU_CSR_INE_X   0x00001000
+
+#define FPU_CSR_ALL_E   0x00000f80
+#define FPU_CSR_INV_E   0x00000800
+#define FPU_CSR_DIV_E   0x00000400
+#define FPU_CSR_OVF_E   0x00000200
+#define FPU_CSR_UDF_E   0x00000100
+#define FPU_CSR_INE_E   0x00000080
+
+#define FPU_CSR_ALL_S   0x0000007c
+#define FPU_CSR_INV_S   0x00000040
+#define FPU_CSR_DIV_S   0x00000020
+#define FPU_CSR_OVF_S   0x00000010
+#define FPU_CSR_UDF_S   0x00000008
+#define FPU_CSR_INE_S   0x00000004
+
+/* rounding mode */
+#define FPU_CSR_RN      0x0     /* nearest */
+#define FPU_CSR_RZ      0x1     /* towards zero */
+#define FPU_CSR_RU      0x2     /* towards +Infinity */
+#define FPU_CSR_RD      0x3     /* towards -Infinity */
+
+
+/*
  * Values for PageMask register
  */
 #define PM_4K   0x00000000
@@ -111,6 +171,16 @@
         : "=r" (__res));                                        \
         __res;})
 
+#define read_32bit_cp0_set1_register(source)                    \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+	".set\tpush\n\t"					\
+	".set\treorder\n\t"					\
+        "cfc0\t%0,"STR(source)"\n\t"                            \
+	".set\tpop"						\
+        : "=r" (__res));                                        \
+        __res;})
+
 /*
  * For now use this only with interrupts disabled!
  */
@@ -129,12 +199,36 @@
 	"nop"							\
         : : "r" (value));
 
+#define write_32bit_cp0_set1_register(register,value)           \
+        __asm__ __volatile__(                                   \
+        "ctc0\t%0,"STR(register)"\n\t"				\
+	"nop"							\
+        : : "r" (value));
+
 #define write_64bit_cp0_register(register,value)                \
         __asm__ __volatile__(                                   \
         ".set\tmips3\n\t"                                       \
         "dmtc0\t%0,"STR(register)"\n\t"                         \
         ".set\tmips0"                                           \
         : : "r" (value))
+
+#ifdef CONFIG_CPU_MIPS32
+/* 
+ * This should be changed when we get a compiler that support the MIPS32 ISA. 
+ */
+#define read_mips32_cp0_config1()                               \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+	".set\tnoreorder\n\t"                                   \
+	".set\tnoat\n\t"                                        \
+     	".word\t0x40018001\n\t"                                 \
+	"move\t%0,$1\n\t"                                       \
+	".set\tat\n\t"                                          \
+	".set\treorder"                                         \
+	:"=r" (__res));                                         \
+        __res;})
+#endif
+
 /*
  * R4x00 interrupt enable / cause bits
  */
@@ -166,7 +260,31 @@
  */
 #define __BUILD_SET_CP0(name,register)                          \
 extern __inline__ unsigned int                                  \
-set_cp0_##name(unsigned int change, unsigned int new)           \
+set_cp0_##name(unsigned int set)				\
+{                                                               \
+	unsigned int res;                                       \
+                                                                \
+	res = read_32bit_cp0_register(register);                \
+	res |= set;						\
+	write_32bit_cp0_register(register, res);        	\
+                                                                \
+	return res;                                             \
+}								\
+								\
+extern __inline__ unsigned int                                  \
+clear_cp0_##name(unsigned int clear)				\
+{                                                               \
+	unsigned int res;                                       \
+                                                                \
+	res = read_32bit_cp0_register(register);                \
+	res &= ~clear;						\
+	write_32bit_cp0_register(register, res);		\
+                                                                \
+	return res;                                             \
+}								\
+								\
+extern __inline__ unsigned int                                  \
+change_cp0_##name(unsigned int change, unsigned int new)	\
 {                                                               \
 	unsigned int res;                                       \
                                                                 \
@@ -186,42 +304,6 @@
 #endif /* defined (_LANGUAGE_ASSEMBLY) */
 
 /*
- * Inline code for use of the ll and sc instructions
- *
- * FIXME: This instruction is only available on MIPS ISA >=2.
- * Since these operations are only being used for atomic operations
- * the easiest workaround for the R[23]00 is to disable interrupts.
- * This fails for R3000 SMP machines which use that many different
- * technologies as replacement that it is difficult to create even
- * just a hook for for all machines to hook into.  The only good
- * thing is that there is currently no R3000 SMP machine on the
- * Linux/MIPS target list ...
- */
-#define load_linked(addr)                                       \
-({                                                              \
-	unsigned int __res;                                     \
-                                                                \
-	__asm__ __volatile__(                                   \
-	"ll\t%0,(%1)"                                           \
-	: "=r" (__res)                                          \
-	: "r" ((unsigned long) (addr)));                        \
-                                                                \
-	__res;                                                  \
-})
-
-#define store_conditional(addr,value)                           \
-({                                                              \
-	int	__res;                                          \
-                                                                \
-	__asm__ __volatile__(                                   \
-	"sc\t%0,(%2)"                                           \
-	: "=r" (__res)                                          \
-	: "0" (value), "r" (addr));                             \
-                                                                \
-	__res;                                                  \
-})
-
-/*
  * Bitfields in the R4xx0 cp0 status register
  */
 #define ST0_IE			0x00000001
@@ -253,11 +335,44 @@
 /*
  * Bits specific to the R4640/R4650
  */
-#define ST0_UM                 <1   <<  4)
+#define ST0_UM                 (1   <<  4)
 #define ST0_IL                 (1   << 23)
 #define ST0_DL                 (1   << 24)
 
 /*
+ * Bitfields in the TX39 family CP0 Configuration Register 3
+ */
+#define TX39_CONF_ICS_SHIFT	19
+#define TX39_CONF_ICS_MASK	0x00380000
+#define TX39_CONF_ICS_1KB 	0x00000000
+#define TX39_CONF_ICS_2KB 	0x00080000
+#define TX39_CONF_ICS_4KB 	0x00100000
+#define TX39_CONF_ICS_8KB 	0x00180000
+#define TX39_CONF_ICS_16KB 	0x00200000
+
+#define TX39_CONF_DCS_SHIFT	16
+#define TX39_CONF_DCS_MASK	0x00070000
+#define TX39_CONF_DCS_1KB 	0x00000000
+#define TX39_CONF_DCS_2KB 	0x00010000
+#define TX39_CONF_DCS_4KB 	0x00020000
+#define TX39_CONF_DCS_8KB 	0x00030000
+#define TX39_CONF_DCS_16KB 	0x00040000
+
+#define TX39_CONF_CWFON 	0x00004000
+#define TX39_CONF_WBON  	0x00002000
+#define TX39_CONF_RF_SHIFT	10
+#define TX39_CONF_RF_MASK	0x00000c00
+#define TX39_CONF_DOZE		0x00000200
+#define TX39_CONF_HALT		0x00000100
+#define TX39_CONF_LOCK		0x00000080
+#define TX39_CONF_ICE		0x00000020
+#define TX39_CONF_DCE		0x00000010
+#define TX39_CONF_IRSIZE_SHIFT	2
+#define TX39_CONF_IRSIZE_MASK	0x0000000c
+#define TX39_CONF_DRSIZE_SHIFT	0
+#define TX39_CONF_DRSIZE_MASK	0x00000003
+
+/*
  * Status register bits available in all MIPS CPUs.
  */
 #define ST0_IM			0x0000ff00
@@ -277,6 +392,22 @@
 #define  STATUSF_IP6		(1   << 14)
 #define  STATUSB_IP7		15
 #define  STATUSF_IP7		(1   << 15)
+#define  STATUSB_IP8		0
+#define  STATUSF_IP8		(1   << 0)
+#define  STATUSB_IP9		1
+#define  STATUSF_IP9		(1   << 1)
+#define  STATUSB_IP10		2
+#define  STATUSF_IP10		(1   << 2)
+#define  STATUSB_IP11		3
+#define  STATUSF_IP11		(1   << 3)
+#define  STATUSB_IP12		4
+#define  STATUSF_IP12		(1   << 4)
+#define  STATUSB_IP13		5
+#define  STATUSF_IP13		(1   << 5)
+#define  STATUSB_IP14		6
+#define  STATUSF_IP14		(1   << 6)
+#define  STATUSB_IP15		7
+#define  STATUSF_IP15		(1   << 7)
 #define ST0_CH			0x00040000
 #define ST0_SR			0x00100000
 #define ST0_BEV			0x00400000
@@ -405,4 +536,4 @@
 extern asmlinkage void write_perf_cntl(unsigned int counter, unsigned int val);
 #endif
 
-#endif /* __ASM_MIPS_MIPSREGS_H */
+#endif /* _ASM_MIPSREGS_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/mmu_context.h linux/include/asm-mips/mmu_context.h
--- linux-2.4.6-pre8/include/asm-mips/mmu_context.h	Thu Aug 10 13:30:05 2000
+++ linux/include/asm-mips/mmu_context.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: mmu_context.h,v 1.7 2000/02/04 07:40:53 ralf Exp $
- *
+/*
  * Switch a MMU context.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -13,11 +12,12 @@
 #define _ASM_MMU_CONTEXT_H
 
 #include <linux/config.h>
+#include <linux/slab.h>
 #include <asm/pgalloc.h>
 
 /* Fuck.  The f-word is here so you can grep for it :-)  */
 extern unsigned long asid_cache;
-extern pgd_t *current_pgd;
+extern pgd_t *current_pgd[];
 
 #if defined(CONFIG_CPU_R3000)
 
@@ -60,7 +60,19 @@
 extern inline int
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
+#ifndef CONFIG_SMP
 	mm->context = 0;
+#else
+	mm->context = (unsigned long)kmalloc(smp_num_cpus * 
+				sizeof(unsigned long), GFP_KERNEL);
+	/*
+ 	 * Init the "context" values so that a tlbpid allocation 
+	 * happens on the first switch.
+ 	 */
+	if (mm->context == 0)
+		return -ENOMEM;
+	memset((void *)mm->context, 0, smp_num_cpus * sizeof(unsigned long));
+#endif
 	return 0;
 }
 
@@ -73,7 +85,7 @@
 	if ((next->context ^ asid) & ASID_VERSION_MASK)
 		get_new_mmu_context(next, asid);
 
-	current_pgd = next->pgd;
+	current_pgd[cpu] = next->pgd;
 	set_entryhi(next->context);
 }
 
@@ -96,7 +108,7 @@
 	/* Unconditionally get a new ASID.  */
 	get_new_mmu_context(next, asid_cache);
 
-	current_pgd = next->pgd;
+	current_pgd[smp_processor_id()] = next->pgd;
 	set_entryhi(next->context);
 }
 
diff -urN linux-2.4.6-pre8/include/asm-mips/orion.h linux/include/asm-mips/orion.h
--- linux-2.4.6-pre8/include/asm-mips/orion.h	Tue Jul 11 11:15:02 2000
+++ linux/include/asm-mips/orion.h	Wed Dec 31 16:00:00 1969
@@ -1,14 +0,0 @@
-/*
- * Orion/Galileo specific header file.
- *  -- Cort <cort@fsmlabs.com>
- */
-#ifndef __LINUX_MIPS_ORION_H
-#define __LINUX_MIPS_ORION_H
-
-/* base address for the GT-64120 internal registers */
-#define GT64120_BASE (0x14000000)
-/* GT64120 and PCI_0 interrupt cause register */
-#define GT64120_CAUSE_LOW *(unsigned long *)(GT64120_BASE + 0xc18)
-#define GT64120_CAUSE_HIGH *(unsigned long *)(GT64120_BASE + 0xc1c)
-
-#endif /* __LINUX_MIPS_ORION_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/param.h linux/include/asm-mips/param.h
--- linux-2.4.6-pre8/include/asm-mips/param.h	Wed Jul 12 15:15:10 2000
+++ linux/include/asm-mips/param.h	Mon Dec  3 22:50:39 2001
@@ -64,4 +64,8 @@
 
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
 
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC	100	/* frequency at which times() counts */
+#endif
+
 #endif /* _ASM_PARAM_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- linux-2.4.6-pre8/include/asm-mips/pci.h	Wed May 16 10:31:27 2001
+++ linux/include/asm-mips/pci.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: pci.h,v 1.10 2000/03/23 02:26:00 ralf Exp $
- *
+/*
  * 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.
@@ -13,7 +12,8 @@
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
 
-#define pcibios_assign_all_busses()	0
+//#define pcibios_assign_all_busses()	0
+#define pcibios_assign_all_busses()	1
 
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
@@ -201,8 +201,27 @@
 #endif
 }
 
-/* Return the index of the PCI controller for device PDEV. */
-#define pci_controller_num(PDEV)	(0)
+/* Return whether the given PCI device DMA address mask can
+ * be supported properly.  For example, if your device can
+ * only drive the low 24-bits during PCI bus mastering, then
+ * you would pass 0x00ffffff as the mask to this function.
+ */
+extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < 0x00ffffff)
+		return 0;
+
+	return 1;
+}
+
+
+/* Return the index of the PCI controller for device. */
+#define pci_controller_num(pdev)	(0)
 
 /*
  * These macros should be used after a pci_map_sg call has been done
diff -urN linux-2.4.6-pre8/include/asm-mips/pgalloc.h linux/include/asm-mips/pgalloc.h
--- linux-2.4.6-pre8/include/asm-mips/pgalloc.h	Mon Apr 23 15:28:07 2001
+++ linux/include/asm-mips/pgalloc.h	Mon Dec  3 22:50:39 2001
@@ -1,16 +1,16 @@
-/* $Id: pgalloc.h,v 1.3 2000/02/23 00:41:38 ralf Exp $
- *
+/*
  * 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 - 2000 by Ralf Baechle at alii
+ * Copyright (C) 1994 - 2001 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_PGALLOC_H
 #define _ASM_PGALLOC_H
 
 #include <linux/config.h>
+#include <linux/mm.h>
 
 /* TLB flushing:
  *
@@ -33,9 +33,7 @@
 
 
 /*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
+ * Allocate and free page tables.
  */
 
 #define pgd_quicklist (current_cpu_data.pgd_quick)
@@ -43,6 +41,13 @@
 #define pte_quicklist (current_cpu_data.pte_quick)
 #define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
 
+#define pmd_populate(mm, pmd, pte)	pmd_set(pmd, pte)
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+extern void pgd_init(unsigned long page);
+
 extern __inline__ pgd_t *get_pgd_slow(void)
 {
 	pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL), *init;
@@ -82,7 +87,6 @@
 }
 
 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);
 
 extern __inline__ pte_t *get_pte_fast(void)
 {
@@ -123,94 +127,54 @@
 }
 
 extern void __bad_pte(pmd_t *pmd);
-extern void __bad_pte_kernel(pmd_t *pmd);
-
-#define pte_free_kernel(pte)    free_pte_fast(pte)
-#define pte_free(pte)           free_pte_fast(pte)
-#define pgd_free(pgd)           free_pgd_fast(pgd)
-#define pgd_alloc(mm)           get_pgd_fast()
 
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	pte_t *pte;
 
-	if (pmd_none(*pmd)) {
-		pte_t *page = get_pte_fast();
-		if (page) {
-			pmd_val(*pmd) = (unsigned long)page;
-			return page + address;
-		}
-		return get_pte_kernel_slow(pmd, address);
-	}
-	if (pmd_bad(*pmd)) {
-		__bad_pte_kernel(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
+	pte = (pte_t *) __get_free_page(GFP_KERNEL);
+	if (pte)
+		clear_page(pte);
+	return pte;
 }
 
-extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	unsigned long *ret;
 
-	if (pmd_none(*pmd)) {
-		pte_t *page = get_pte_fast();
-		if (page) {
-			pmd_val(*pmd) = (unsigned long)page;
-			return page + address;
-		}
-		return get_pte_slow(pmd, address);
-	}
-	if (pmd_bad(*pmd)) {
-		__bad_pte(pmd);
-		return NULL;
+	if ((ret = (unsigned long *)pte_quicklist) != NULL) {
+		pte_quicklist = (unsigned long *)(*ret);
+		ret[0] = ret[1];
+		pgtable_cache_size--;
 	}
-	return (pte_t *) pmd_page(*pmd) + address;
+	return (pte_t *)ret;
 }
 
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern inline void pmd_free(pmd_t * pmd)
+extern __inline__ void pte_free_fast(pte_t *pte)
 {
+	*(unsigned long *)pte = (unsigned long) pte_quicklist;
+	pte_quicklist = (unsigned long *) pte;
+	pgtable_cache_size++;
 }
 
-extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+extern __inline__ void pte_free_slow(pte_t *pte)
 {
-	return (pmd_t *) pgd;
+	free_page((unsigned long)pte);
 }
 
-#define pmd_free_kernel		pmd_free
-#define pmd_alloc_kernel	pmd_alloc
+#define pte_free(pte)           pte_free_slow(pte)
+#define pgd_free(pgd)           free_pgd_fast(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.
+ */
+#define pmd_alloc_one_fast(mm, addr)	({ BUG(); ((pmd_t *)1); })
+#define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
+#define pmd_free(x)			do { } while (0)
+#define pgd_populate(mm, pmd, pte)	BUG()
 
 extern int do_check_pgt_cache(int, int);
-
-extern inline void set_pgdir(unsigned long address, pgd_t entry)
-{
-	struct task_struct * p;
-	pgd_t *pgd;
-#ifdef CONFIG_SMP
-	int i;
-#endif	
-
-	read_lock(&tasklist_lock);
-	for_each_task(p) {
-		if (!p->mm)
-			continue;
-		*pgd_offset(p->mm,address) = entry;
-	}
-	read_unlock(&tasklist_lock);
-#ifndef CONFIG_SMP
-	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
-		pgd[address >> PGDIR_SHIFT] = entry;
-#else
-	/* To pgd_alloc/pgd_free, one holds master kernel lock and so does our
-	   callee, so we can modify pgd caches of other CPUs as well. -jj */
-	for (i = 0; i < NR_CPUS; i++)
-		for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
-			pgd[address >> PGDIR_SHIFT] = entry;
-#endif
-}
 
 #endif /* _ASM_PGALLOC_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h
--- linux-2.4.6-pre8/include/asm-mips/pgtable.h	Tue Nov  7 10:46:04 2000
+++ linux/include/asm-mips/pgtable.h	Mon Dec  3 22:50:39 2001
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 - 1999 by Ralf Baechle at alii
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle at alii
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
 #ifndef _ASM_PGTABLE_H
@@ -25,32 +25,32 @@
  *  - flush_cache_page(mm, vmaddr) flushes a single page
  *  - flush_cache_range(mm, start, end) flushes a range of pages
  *  - flush_page_to_ram(page) write back kernel page to ram
+ *  - flush_icache_range(start, end) flush a range of instructions
  */
 extern void (*_flush_cache_all)(void);
+extern void (*___flush_cache_all)(void);
 extern void (*_flush_cache_mm)(struct mm_struct *mm);
 extern void (*_flush_cache_range)(struct mm_struct *mm, unsigned long start,
 				 unsigned long end);
 extern void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
 extern void (*_flush_cache_sigtramp)(unsigned long addr);
 extern void (*_flush_page_to_ram)(struct page * page);
+extern void (*_flush_icache_range)(unsigned long start, unsigned long end);
+extern void (*_flush_icache_page)(struct vm_area_struct *vma,
+                                  struct page *page);
 
 #define flush_dcache_page(page)			do { } while (0)
 
 #define flush_cache_all()		_flush_cache_all()
+#define __flush_cache_all()		___flush_cache_all()
 #define flush_cache_mm(mm)		_flush_cache_mm(mm)
 #define flush_cache_range(mm,start,end)	_flush_cache_range(mm,start,end)
 #define flush_cache_page(vma,page)	_flush_cache_page(vma, page)
 #define flush_cache_sigtramp(addr)	_flush_cache_sigtramp(addr)
 #define flush_page_to_ram(page)		_flush_page_to_ram(page)
 
-#define flush_icache_range(start, end)	flush_cache_all()
-
-#define flush_icache_page(vma, page)					\
-do {									\
-	unsigned long addr;						\
-	addr = (unsigned long) page_address(page);			\
-	_flush_cache_page(vma, addr);					\
-} while (0)
+#define flush_icache_range(start, end)	_flush_icache_range(start,end)
+#define flush_icache_page(vma, page) 	_flush_icache_page(vma, page)
 
 
 /*
@@ -59,6 +59,16 @@
 extern void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 			       unsigned long entryhi, unsigned long pagemask);
 
+/*
+ * - add_temporary_entry() add a temporary TLB entry. We use TLB entries
+ *	starting at the top and working down. This is for populating the
+ *	TLB before trap_init() puts the TLB miss handler in place. It 
+ *	should be used only for entries matching the actual page tables,
+ *	to prevent inconsistencies.
+ */
+extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+			       unsigned long entryhi, unsigned long pagemask);
+
 
 /* Basically we have the same two-level (which is the logical three level
  * Linux page table layout folded) page tables as the i386.  Some day
@@ -130,13 +140,25 @@
 #define _CACHE_CACHABLE_NONCOHERENT 0
 
 #else
- 
 #define _PAGE_R4KBUG                (1<<5)  /* workaround for r4k bug  */
 #define _PAGE_GLOBAL                (1<<6)
 #define _PAGE_VALID                 (1<<7)
 #define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
 #define _PAGE_DIRTY                 (1<<8)  /* The MIPS dirty bit      */
 #define _PAGE_SILENT_WRITE          (1<<8)
+#define _CACHE_MASK                 (7<<9)
+
+#if defined(CONFIG_CPU_SB1)
+
+/* No penalty for being coherent on the SB1, so just
+   use it for "noncoherent" spaces, too.  Shouldn't hurt. */
+
+#define _CACHE_UNCACHED             (2<<9)  
+#define _CACHE_CACHABLE_COW         (5<<9)  
+#define _CACHE_CACHABLE_NONCOHERENT (5<<9)  
+
+#else
+
 #define _CACHE_CACHABLE_NO_WA       (0<<9)  /* R4600 only              */
 #define _CACHE_CACHABLE_WA          (1<<9)  /* R4600 only              */
 #define _CACHE_UNCACHED             (2<<9)  /* R4[0246]00              */
@@ -145,26 +167,36 @@
 #define _CACHE_CACHABLE_COW         (5<<9)  /* R4[04]00 only           */
 #define _CACHE_CACHABLE_CUW         (6<<9)  /* R4[04]00 only           */
 #define _CACHE_CACHABLE_ACCELERATED (7<<9)  /* R10000 only             */
-#define _CACHE_MASK                 (7<<9)
 
 #endif
+#endif
 
 #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
 
 #define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
 
+#ifdef CONFIG_MIPS_UNCACHED
+#define PAGE_CACHABLE_DEFAULT	_CACHE_UNCACHED
+#else
+#ifdef CONFIG_CPU_SB1
+#define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
+#else
+#define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_NONCOHERENT
+#endif
+#endif
+
 #define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			PAGE_CACHABLE_DEFAULT)
 #define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_READ | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			PAGE_CACHABLE_DEFAULT)
 #define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_READ | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			PAGE_CACHABLE_DEFAULT)
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			PAGE_CACHABLE_DEFAULT)
 #define PAGE_USERIO     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
-			_CACHE_UNCACHED)
+			PAGE_CACHABLE_DEFAULT)
 #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
 			_CACHE_UNCACHED)
 
@@ -200,21 +232,9 @@
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-/*
- * 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);
-
 extern unsigned long empty_zero_page;
 extern unsigned long zero_page_mask;
 
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
 #define ZERO_PAGE(vaddr) \
 	(virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
 
@@ -269,6 +289,13 @@
 }
 
 /*
+ * (pmds are folded into pgds so this doesnt get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
+
+/*
  * Empty pgd/pmd entries point to the invalid_pte_table.
  */
 extern inline int pmd_none(pmd_t pmd)
@@ -284,7 +311,7 @@
 
 extern inline int pmd_present(pmd_t pmd)
 {
-	return pmd_val(pmd);
+	return (pmd_val(pmd) != (unsigned long) invalid_pte_table);
 }
 
 extern inline void pmd_clear(pmd_t *pmdp)
@@ -303,7 +330,7 @@
 extern inline void pgd_clear(pgd_t *pgdp)	{ }
 
 /*
- * Permanent address of a page.  On MIPS64 we never have highmem, so this
+ * Permanent address of a page.  On MIPS we never have highmem, so this
  * is simple.
  */
 #define page_address(page)	((page)->virtual)
@@ -390,7 +417,7 @@
 
 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 {
-	return __pte(((physpage & PAGE_MASK) - PAGE_OFFSET) | pgprot_val(pgprot));
+	return __pte(physpage | pgprot_val(pgprot));
 }
 
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
@@ -424,19 +451,6 @@
 	       ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
 }
 
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-extern void pgd_init(unsigned long page);
-
-extern void __bad_pte(pmd_t *pmd);
-extern void __bad_pte_kernel(pmd_t *pmd);
-
-#define pte_free_kernel(pte)    free_pte_fast(pte)
-#define pte_free(pte)           free_pte_fast(pte)
-#define pgd_free(pgd)           free_pgd_fast(pgd)
-#define pgd_alloc()             get_pgd_fast()
-
 extern int do_check_pgt_cache(int, int);
 
 extern pgd_t swapper_pg_dir[1024];
@@ -637,6 +651,19 @@
 		"mtc0 %0, $6\n\t"
 		".set pop"
 		: : "r" (val));
+}
+
+extern inline unsigned long get_info(void)
+{
+	unsigned long val;
+
+	__asm__(
+		".set push\n\t"
+		".set reorder\n\t"
+		"mfc0 %0, $7\n\t"
+		".set pop"
+		: "=r" (val));
+	return val;
 }
 
 /* CP0_TAGLO and CP0_TAGHI registers */
diff -urN linux-2.4.6-pre8/include/asm-mips/pmc/ev64120.h linux/include/asm-mips/pmc/ev64120.h
--- linux-2.4.6-pre8/include/asm-mips/pmc/ev64120.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/pmc/ev64120.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,59 @@
+/*
+ * This is a direct copy of the ev96100.h file, with a global search and
+ * replace.  The numbers are the same.
+ *
+ * The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef _ASM_PMC_CP7000_H
+#define _ASM_PMC_CP7000_H
+
+#include <asm/addrspace.h>
+
+/*
+ *   GT64120 config space base address
+ */
+#define GT64120_BASE    (KSEG1ADDR(0x14000000))
+#define MIPS_GT_BASE    GT64120_BASE
+ 
+/*
+ *   PCI Bus allocation
+ */
+#define GT_PCI_MEM_BASE    0x12000000
+#define GT_PCI_MEM_SIZE    0x02000000
+#define GT_PCI_IO_BASE     0x10000000
+#define GT_PCI_IO_SIZE     0x02000000
+#define GT_ISA_IO_BASE     PCI_IO_BASE          
+
+/*
+ *   Duart I/O ports.
+ */
+#define EV64120_COM1_BASE_ADDR  (0x1d000000 + 0x20) 
+#define EV64120_COM2_BASE_ADDR  (0x1d000000 + 0x00)
+
+
+/*
+ *   EV64120 interrupt controller register base.
+ */
+#define EV64120_ICTRL_REGS_BASE   (KSEG1ADDR(0x1f000000))
+
+/*
+ *   EV64120 UART register base.
+ */
+#define EV64120_UART0_REGS_BASE    (KSEG1ADDR(EV64120_COM1_BASE_ADDR))
+#define EV64120_UART1_REGS_BASE    (KSEG1ADDR(EV64120_COM2_BASE_ADDR))
+#define EV64120_BASE_BAUD ( 3686400 / 16 )
+
+
+/*
+ * Because of an error/peculiarity in the Galileo chip, we need to swap the 
+ * bytes when running bigendian.
+ */
+
+#define GT_WRITE(ofs, data)  \
+	*(volatile u32 *)(MIPS_GT_BASE+ofs) = cpu_to_le32(data)
+#define GT_READ(ofs, data)   \
+	*data = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+ofs))
+    
+
+#endif /* _ASM_PMC_CP7000_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/pmc/ev64120int.h linux/include/asm-mips/pmc/ev64120int.h
--- linux-2.4.6-pre8/include/asm-mips/pmc/ev64120int.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/pmc/ev64120int.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,32 @@
+#ifndef _ASM_PMC_CP7000INT_H
+#define _ASM_PMC_CP7000INT_H
+
+#define INT_CAUSE_MAIN 0
+#define INT_CAUSE_HIGH 1
+
+#define MAX_CAUSE_REGS 4
+#define MAX_CAUSE_REG_WIDTH 32
+
+void hook_irq_handler (int int_cause , int bit_num , void *isr_ptr);
+int disable_galileo_irq (int int_cause , int bit_num);
+int enable_galileo_irq (int int_cause , int bit_num);
+
+extern struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
+
+/*
+ * PCI interrupts will come in on either the INTA or INTD interrups lines,
+ * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
+ * boards, they all either come in on IntD or they all come in on IntA, they
+ * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
+ * "requested" interrupt numbers and go through the list whenever we get an
+ * IntA/D.
+ *
+ * All PCI interrupts have numbers >= 20 by arbitrary convention.  Any
+ * interrupt < 8 is an interrupt that is maskable on MIPS.
+ */
+
+#define TIMER	4
+#define INTA	2
+#define INTD	5
+
+#endif /* _ASM_PMC_CP7000INT_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- linux-2.4.6-pre8/include/asm-mips/processor.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-mips/processor.h	Mon Dec  3 22:50:39 2001
@@ -1,11 +1,10 @@
-/* $Id: processor.h,v 1.25 2000/02/05 06:47:37 ralf Exp $
- *
+/*
  * 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 Waldorf GMBH
- * Copyright (C) 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001 Ralf Baechle
  * Copyright (C) 1996 Paul M. Antoine
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
@@ -30,6 +29,7 @@
 #include <asm/system.h>
 
 struct mips_cpuinfo {
+	unsigned long udelay_val;
 	unsigned long *pgd_quick;
 	unsigned long *pte_quick;
 	unsigned long pgtable_cache_sz;
@@ -44,7 +44,6 @@
 extern void r4k_wait(void);
 extern char cyclecounter_available;	/* only available from R4000 upwards. */
 extern char dedicated_iv_available;	/* some embedded MIPS like Nevada */
-extern char vce_available;		/* Supports VCED / VCEI exceptions */
 
 extern struct mips_cpuinfo boot_cpu_data;
 extern unsigned int vced_count, vcei_count;
@@ -83,7 +82,7 @@
  * for a 64 bit kernel expandable to 8192EB, of which the current MIPS
  * implementations will "only" be able to use 1TB ...
  */
-#define TASK_SIZE	(0x80000000UL)
+#define TASK_SIZE	(0x7fff8000UL)
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
diff -urN linux-2.4.6-pre8/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h
--- linux-2.4.6-pre8/include/asm-mips/ptrace.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/ptrace.h	Mon Dec  3 22:50:39 2001
@@ -1,16 +1,15 @@
-/* $Id: ptrace.h,v 1.7 1999/09/28 22:27:17 ralf Exp $
- *
+/*
  * 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, 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
  *
  * Machine dependent structs and defines to help the user use
  * the ptrace system call.
  */
-#ifndef __ASM_MIPS_PTRACE_H
-#define __ASM_MIPS_PTRACE_H
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
 
 #include <asm/isadep.h>
 #include <linux/types.h>
@@ -52,6 +51,19 @@
 
 #endif /* !(_LANGUAGE_ASSEMBLY) */
 
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+/* #define PTRACE_GETREGS		12 */
+/* #define PTRACE_SETREGS		13 */
+/* #define PTRACE_GETFPREGS		14 */
+/* #define PTRACE_SETFPREGS		15 */
+/* #define PTRACE_GETFPXREGS		18 */
+/* #define PTRACE_SETFPXREGS		19 */
+
+#define PTRACE_SETOPTIONS	21
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD	0x00000001
+
 #ifdef _LANGUAGE_ASSEMBLY
 #include <asm/offset.h>
 #endif
@@ -71,4 +83,4 @@
 
 #endif
 
-#endif /* __ASM_MIPS_PTRACE_H */
+#endif /* _ASM_PTRACE_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/resource.h linux/include/asm-mips/resource.h
--- linux-2.4.6-pre8/include/asm-mips/resource.h	Fri Sep 22 14:21:20 2000
+++ linux/include/asm-mips/resource.h	Mon Dec  3 22:50:39 2001
@@ -1,10 +1,9 @@
-/* $Id: resource.h,v 1.4 2000/01/27 23:45:30 ralf Exp $
- *
+/*
  * 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) 1995, 1996, 1998 by Ralf Baechle
+ * Copyright (C) 1995, 96, 98, 2000 by Ralf Baechle
  */
 #ifndef _ASM_RESOURCE_H
 #define _ASM_RESOURCE_H
@@ -26,13 +25,13 @@
 
 #define RLIM_NLIMITS 11			/* Number of limit flavors.  */
 
+#ifdef __KERNEL__
+
 /*
  * SuS says limits have to be unsigned.
  * Which makes a ton more sense anyway.
  */
 #define RLIM_INFINITY	0x7fffffffUL
-
-#ifdef __KERNEL__
 
 #define INIT_RLIMITS					\
 {							\
diff -urN linux-2.4.6-pre8/include/asm-mips/riscos-syscall.h linux/include/asm-mips/riscos-syscall.h
--- linux-2.4.6-pre8/include/asm-mips/riscos-syscall.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/riscos-syscall.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,979 @@
+/*
+ * 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) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle
+ */
+#ifndef _ASM_RISCOS_SYSCALL_H
+#define _ASM_RISCOS_SYSCALL_H
+
+/*
+ * The syscalls 0 - 3999 are reserved for a down to the root syscall
+ * compatibility with RISC/os and IRIX.  We'll see how to deal with the
+ * various "real" BSD variants like Ultrix, NetBSD ...
+ */
+
+/*
+ * SVR4 syscalls are in the range from 1 to 999
+ */
+#define __NR_SVR4			0
+#define __NR_SVR4_syscall		(__NR_SVR4 +   0)
+#define __NR_SVR4_exit			(__NR_SVR4 +   1)
+#define __NR_SVR4_fork			(__NR_SVR4 +   2)
+#define __NR_SVR4_read			(__NR_SVR4 +   3)
+#define __NR_SVR4_write			(__NR_SVR4 +   4)
+#define __NR_SVR4_open			(__NR_SVR4 +   5)
+#define __NR_SVR4_close			(__NR_SVR4 +   6)
+#define __NR_SVR4_wait			(__NR_SVR4 +   7)
+#define __NR_SVR4_creat			(__NR_SVR4 +   8)
+#define __NR_SVR4_link			(__NR_SVR4 +   9)
+#define __NR_SVR4_unlink		(__NR_SVR4 +  10)
+#define __NR_SVR4_exec			(__NR_SVR4 +  11)
+#define __NR_SVR4_chdir			(__NR_SVR4 +  12)
+#define __NR_SVR4_gtime			(__NR_SVR4 +  13)
+#define __NR_SVR4_mknod			(__NR_SVR4 +  14)
+#define __NR_SVR4_chmod			(__NR_SVR4 +  15)
+#define __NR_SVR4_chown			(__NR_SVR4 +  16)
+#define __NR_SVR4_sbreak		(__NR_SVR4 +  17)
+#define __NR_SVR4_stat			(__NR_SVR4 +  18)
+#define __NR_SVR4_lseek			(__NR_SVR4 +  19)
+#define __NR_SVR4_getpid		(__NR_SVR4 +  20)
+#define __NR_SVR4_mount			(__NR_SVR4 +  21)
+#define __NR_SVR4_umount		(__NR_SVR4 +  22)
+#define __NR_SVR4_setuid		(__NR_SVR4 +  23)
+#define __NR_SVR4_getuid		(__NR_SVR4 +  24)
+#define __NR_SVR4_stime			(__NR_SVR4 +  25)
+#define __NR_SVR4_ptrace		(__NR_SVR4 +  26)
+#define __NR_SVR4_alarm			(__NR_SVR4 +  27)
+#define __NR_SVR4_fstat			(__NR_SVR4 +  28)
+#define __NR_SVR4_pause			(__NR_SVR4 +  29)
+#define __NR_SVR4_utime			(__NR_SVR4 +  30)
+#define __NR_SVR4_stty			(__NR_SVR4 +  31)
+#define __NR_SVR4_gtty			(__NR_SVR4 +  32)
+#define __NR_SVR4_access		(__NR_SVR4 +  33)
+#define __NR_SVR4_nice			(__NR_SVR4 +  34)
+#define __NR_SVR4_statfs		(__NR_SVR4 +  35)
+#define __NR_SVR4_sync			(__NR_SVR4 +  36)
+#define __NR_SVR4_kill			(__NR_SVR4 +  37)
+#define __NR_SVR4_fstatfs		(__NR_SVR4 +  38)
+#define __NR_SVR4_setpgrp		(__NR_SVR4 +  39)
+#define __NR_SVR4_cxenix		(__NR_SVR4 +  40)
+#define __NR_SVR4_dup			(__NR_SVR4 +  41)
+#define __NR_SVR4_pipe			(__NR_SVR4 +  42)
+#define __NR_SVR4_times			(__NR_SVR4 +  43)
+#define __NR_SVR4_profil		(__NR_SVR4 +  44)
+#define __NR_SVR4_plock			(__NR_SVR4 +  45)
+#define __NR_SVR4_setgid		(__NR_SVR4 +  46)
+#define __NR_SVR4_getgid		(__NR_SVR4 +  47)
+#define __NR_SVR4_sig			(__NR_SVR4 +  48)
+#define __NR_SVR4_msgsys		(__NR_SVR4 +  49)
+#define __NR_SVR4_sysmips		(__NR_SVR4 +  50)
+#define __NR_SVR4_sysacct		(__NR_SVR4 +  51)
+#define __NR_SVR4_shmsys		(__NR_SVR4 +  52)
+#define __NR_SVR4_semsys		(__NR_SVR4 +  53)
+#define __NR_SVR4_ioctl			(__NR_SVR4 +  54)
+#define __NR_SVR4_uadmin		(__NR_SVR4 +  55)
+#define __NR_SVR4_exch 			(__NR_SVR4 +  56)
+#define __NR_SVR4_utssys		(__NR_SVR4 +  57)
+#define __NR_SVR4_fsync			(__NR_SVR4 +  58)
+#define __NR_SVR4_exece			(__NR_SVR4 +  59)
+#define __NR_SVR4_umask			(__NR_SVR4 +  60)
+#define __NR_SVR4_chroot		(__NR_SVR4 +  61)
+#define __NR_SVR4_fcntl			(__NR_SVR4 +  62)
+#define __NR_SVR4_ulimit		(__NR_SVR4 +  63)
+#define __NR_SVR4_reserved1		(__NR_SVR4 +  64)
+#define __NR_SVR4_reserved2		(__NR_SVR4 +  65)
+#define __NR_SVR4_reserved3		(__NR_SVR4 +  66)
+#define __NR_SVR4_reserved4		(__NR_SVR4 +  67)
+#define __NR_SVR4_reserved5		(__NR_SVR4 +  68)
+#define __NR_SVR4_reserved6		(__NR_SVR4 +  69)
+#define __NR_SVR4_advfs			(__NR_SVR4 +  70)
+#define __NR_SVR4_unadvfs		(__NR_SVR4 +  71)
+#define __NR_SVR4_unused1		(__NR_SVR4 +  72)
+#define __NR_SVR4_unused2		(__NR_SVR4 +  73)
+#define __NR_SVR4_rfstart		(__NR_SVR4 +  74)
+#define __NR_SVR4_unused3		(__NR_SVR4 +  75)
+#define __NR_SVR4_rdebug		(__NR_SVR4 +  76)
+#define __NR_SVR4_rfstop		(__NR_SVR4 +  77)
+#define __NR_SVR4_rfsys			(__NR_SVR4 +  78)
+#define __NR_SVR4_rmdir			(__NR_SVR4 +  79)
+#define __NR_SVR4_mkdir			(__NR_SVR4 +  80)
+#define __NR_SVR4_getdents		(__NR_SVR4 +  81)
+#define __NR_SVR4_libattach		(__NR_SVR4 +  82)
+#define __NR_SVR4_libdetach		(__NR_SVR4 +  83)
+#define __NR_SVR4_sysfs			(__NR_SVR4 +  84)
+#define __NR_SVR4_getmsg		(__NR_SVR4 +  85)
+#define __NR_SVR4_putmsg		(__NR_SVR4 +  86)
+#define __NR_SVR4_poll			(__NR_SVR4 +  87)
+#define __NR_SVR4_lstat			(__NR_SVR4 +  88)
+#define __NR_SVR4_symlink		(__NR_SVR4 +  89)
+#define __NR_SVR4_readlink		(__NR_SVR4 +  90)
+#define __NR_SVR4_setgroups		(__NR_SVR4 +  91)
+#define __NR_SVR4_getgroups		(__NR_SVR4 +  92)
+#define __NR_SVR4_fchmod		(__NR_SVR4 +  93)
+#define __NR_SVR4_fchown		(__NR_SVR4 +  94)
+#define __NR_SVR4_sigprocmask		(__NR_SVR4 +  95)
+#define __NR_SVR4_sigsuspend		(__NR_SVR4 +  96)
+#define __NR_SVR4_sigaltstack		(__NR_SVR4 +  97)
+#define __NR_SVR4_sigaction		(__NR_SVR4 +  98)
+#define __NR_SVR4_sigpending		(__NR_SVR4 +  99)
+#define __NR_SVR4_setcontext		(__NR_SVR4 + 100)
+#define __NR_SVR4_evsys			(__NR_SVR4 + 101)
+#define __NR_SVR4_evtrapret		(__NR_SVR4 + 102)
+#define __NR_SVR4_statvfs		(__NR_SVR4 + 103)
+#define __NR_SVR4_fstatvfs		(__NR_SVR4 + 104)
+#define __NR_SVR4_reserved7		(__NR_SVR4 + 105)
+#define __NR_SVR4_nfssys		(__NR_SVR4 + 106)
+#define __NR_SVR4_waitid		(__NR_SVR4 + 107)
+#define __NR_SVR4_sigsendset		(__NR_SVR4 + 108)
+#define __NR_SVR4_hrtsys		(__NR_SVR4 + 109)
+#define __NR_SVR4_acancel		(__NR_SVR4 + 110)
+#define __NR_SVR4_async			(__NR_SVR4 + 111)
+#define __NR_SVR4_priocntlset		(__NR_SVR4 + 112)
+#define __NR_SVR4_pathconf		(__NR_SVR4 + 113)
+#define __NR_SVR4_mincore		(__NR_SVR4 + 114)
+#define __NR_SVR4_mmap			(__NR_SVR4 + 115)
+#define __NR_SVR4_mprotect		(__NR_SVR4 + 116)
+#define __NR_SVR4_munmap		(__NR_SVR4 + 117)
+#define __NR_SVR4_fpathconf		(__NR_SVR4 + 118)
+#define __NR_SVR4_vfork			(__NR_SVR4 + 119)
+#define __NR_SVR4_fchdir		(__NR_SVR4 + 120)
+#define __NR_SVR4_readv			(__NR_SVR4 + 121)
+#define __NR_SVR4_writev		(__NR_SVR4 + 122)
+#define __NR_SVR4_xstat			(__NR_SVR4 + 123)
+#define __NR_SVR4_lxstat		(__NR_SVR4 + 124)
+#define __NR_SVR4_fxstat		(__NR_SVR4 + 125)
+#define __NR_SVR4_xmknod		(__NR_SVR4 + 126)
+#define __NR_SVR4_clocal		(__NR_SVR4 + 127)
+#define __NR_SVR4_setrlimit		(__NR_SVR4 + 128)
+#define __NR_SVR4_getrlimit		(__NR_SVR4 + 129)
+#define __NR_SVR4_lchown		(__NR_SVR4 + 130)
+#define __NR_SVR4_memcntl		(__NR_SVR4 + 131)
+#define __NR_SVR4_getpmsg		(__NR_SVR4 + 132)
+#define __NR_SVR4_putpmsg		(__NR_SVR4 + 133)
+#define __NR_SVR4_rename		(__NR_SVR4 + 134)
+#define __NR_SVR4_nuname		(__NR_SVR4 + 135)
+#define __NR_SVR4_setegid		(__NR_SVR4 + 136)
+#define __NR_SVR4_sysconf		(__NR_SVR4 + 137)
+#define __NR_SVR4_adjtime		(__NR_SVR4 + 138)
+#define __NR_SVR4_sysinfo		(__NR_SVR4 + 139)
+#define __NR_SVR4_reserved8		(__NR_SVR4 + 140)
+#define __NR_SVR4_seteuid		(__NR_SVR4 + 141)
+#define __NR_SVR4_PYRAMID_statis	(__NR_SVR4 + 142)
+#define __NR_SVR4_PYRAMID_tuning	(__NR_SVR4 + 143)
+#define __NR_SVR4_PYRAMID_forcerr	(__NR_SVR4 + 144)
+#define __NR_SVR4_PYRAMID_mpcntl	(__NR_SVR4 + 145)
+#define __NR_SVR4_reserved9		(__NR_SVR4 + 146)
+#define __NR_SVR4_reserved10		(__NR_SVR4 + 147)
+#define __NR_SVR4_reserved11		(__NR_SVR4 + 148)
+#define __NR_SVR4_reserved12		(__NR_SVR4 + 149)
+#define __NR_SVR4_reserved13		(__NR_SVR4 + 150)
+#define __NR_SVR4_reserved14		(__NR_SVR4 + 151)
+#define __NR_SVR4_reserved15		(__NR_SVR4 + 152)
+#define __NR_SVR4_reserved16		(__NR_SVR4 + 153)
+#define __NR_SVR4_reserved17		(__NR_SVR4 + 154)
+#define __NR_SVR4_reserved18		(__NR_SVR4 + 155)
+#define __NR_SVR4_reserved19		(__NR_SVR4 + 156)
+#define __NR_SVR4_reserved20		(__NR_SVR4 + 157)
+#define __NR_SVR4_reserved21		(__NR_SVR4 + 158)
+#define __NR_SVR4_reserved22		(__NR_SVR4 + 159)
+#define __NR_SVR4_reserved23		(__NR_SVR4 + 160)
+#define __NR_SVR4_reserved24		(__NR_SVR4 + 161)
+#define __NR_SVR4_reserved25		(__NR_SVR4 + 162)
+#define __NR_SVR4_reserved26		(__NR_SVR4 + 163)
+#define __NR_SVR4_reserved27		(__NR_SVR4 + 164)
+#define __NR_SVR4_reserved28		(__NR_SVR4 + 165)
+#define __NR_SVR4_reserved29		(__NR_SVR4 + 166)
+#define __NR_SVR4_reserved30		(__NR_SVR4 + 167)
+#define __NR_SVR4_reserved31		(__NR_SVR4 + 168)
+#define __NR_SVR4_reserved32		(__NR_SVR4 + 169)
+#define __NR_SVR4_reserved33		(__NR_SVR4 + 170)
+#define __NR_SVR4_reserved34		(__NR_SVR4 + 171)
+#define __NR_SVR4_reserved35		(__NR_SVR4 + 172)
+#define __NR_SVR4_reserved36		(__NR_SVR4 + 173)
+#define __NR_SVR4_reserved37		(__NR_SVR4 + 174)
+#define __NR_SVR4_reserved38		(__NR_SVR4 + 175)
+#define __NR_SVR4_reserved39		(__NR_SVR4 + 176)
+#define __NR_SVR4_reserved40		(__NR_SVR4 + 177)
+#define __NR_SVR4_reserved41		(__NR_SVR4 + 178)
+#define __NR_SVR4_reserved42		(__NR_SVR4 + 179)
+#define __NR_SVR4_reserved43		(__NR_SVR4 + 180)
+#define __NR_SVR4_reserved44		(__NR_SVR4 + 181)
+#define __NR_SVR4_reserved45		(__NR_SVR4 + 182)
+#define __NR_SVR4_reserved46		(__NR_SVR4 + 183)
+#define __NR_SVR4_reserved47		(__NR_SVR4 + 184)
+#define __NR_SVR4_reserved48		(__NR_SVR4 + 185)
+#define __NR_SVR4_reserved49		(__NR_SVR4 + 186)
+#define __NR_SVR4_reserved50		(__NR_SVR4 + 187)
+#define __NR_SVR4_reserved51		(__NR_SVR4 + 188)
+#define __NR_SVR4_reserved52		(__NR_SVR4 + 189)
+#define __NR_SVR4_reserved53		(__NR_SVR4 + 190)
+#define __NR_SVR4_reserved54		(__NR_SVR4 + 191)
+#define __NR_SVR4_reserved55		(__NR_SVR4 + 192)
+#define __NR_SVR4_reserved56		(__NR_SVR4 + 193)
+#define __NR_SVR4_reserved57		(__NR_SVR4 + 194)
+#define __NR_SVR4_reserved58		(__NR_SVR4 + 195)
+#define __NR_SVR4_reserved59		(__NR_SVR4 + 196)
+#define __NR_SVR4_reserved60		(__NR_SVR4 + 197)
+#define __NR_SVR4_reserved61		(__NR_SVR4 + 198)
+#define __NR_SVR4_reserved62		(__NR_SVR4 + 199)
+#define __NR_SVR4_reserved63		(__NR_SVR4 + 200)
+#define __NR_SVR4_aread			(__NR_SVR4 + 201)
+#define __NR_SVR4_awrite		(__NR_SVR4 + 202)	
+#define __NR_SVR4_listio		(__NR_SVR4 + 203)
+#define __NR_SVR4_mips_acancel		(__NR_SVR4 + 204)
+#define __NR_SVR4_astatus		(__NR_SVR4 + 205)
+#define __NR_SVR4_await			(__NR_SVR4 + 206)
+#define __NR_SVR4_areadv		(__NR_SVR4 + 207)
+#define __NR_SVR4_awritev		(__NR_SVR4 + 208)
+#define __NR_SVR4_MIPS_reserved1	(__NR_SVR4 + 209)
+#define __NR_SVR4_MIPS_reserved2	(__NR_SVR4 + 210)
+#define __NR_SVR4_MIPS_reserved3	(__NR_SVR4 + 211)
+#define __NR_SVR4_MIPS_reserved4	(__NR_SVR4 + 212)
+#define __NR_SVR4_MIPS_reserved5	(__NR_SVR4 + 213)
+#define __NR_SVR4_MIPS_reserved6	(__NR_SVR4 + 214)
+#define __NR_SVR4_MIPS_reserved7	(__NR_SVR4 + 215)
+#define __NR_SVR4_MIPS_reserved8	(__NR_SVR4 + 216)
+#define __NR_SVR4_MIPS_reserved9	(__NR_SVR4 + 217)
+#define __NR_SVR4_MIPS_reserved10	(__NR_SVR4 + 218)
+#define __NR_SVR4_MIPS_reserved11	(__NR_SVR4 + 219)
+#define __NR_SVR4_MIPS_reserved12	(__NR_SVR4 + 220)
+#define __NR_SVR4_CDC_reserved1		(__NR_SVR4 + 221)
+#define __NR_SVR4_CDC_reserved2		(__NR_SVR4 + 222)
+#define __NR_SVR4_CDC_reserved3		(__NR_SVR4 + 223)
+#define __NR_SVR4_CDC_reserved4		(__NR_SVR4 + 224)
+#define __NR_SVR4_CDC_reserved5		(__NR_SVR4 + 225)
+#define __NR_SVR4_CDC_reserved6		(__NR_SVR4 + 226)
+#define __NR_SVR4_CDC_reserved7		(__NR_SVR4 + 227)
+#define __NR_SVR4_CDC_reserved8		(__NR_SVR4 + 228)
+#define __NR_SVR4_CDC_reserved9		(__NR_SVR4 + 229)
+#define __NR_SVR4_CDC_reserved10	(__NR_SVR4 + 230)
+#define __NR_SVR4_CDC_reserved11	(__NR_SVR4 + 231)
+#define __NR_SVR4_CDC_reserved12	(__NR_SVR4 + 232)
+#define __NR_SVR4_CDC_reserved13	(__NR_SVR4 + 233)
+#define __NR_SVR4_CDC_reserved14	(__NR_SVR4 + 234)
+#define __NR_SVR4_CDC_reserved15	(__NR_SVR4 + 235)
+#define __NR_SVR4_CDC_reserved16	(__NR_SVR4 + 236)
+#define __NR_SVR4_CDC_reserved17	(__NR_SVR4 + 237)
+#define __NR_SVR4_CDC_reserved18	(__NR_SVR4 + 238)
+#define __NR_SVR4_CDC_reserved19	(__NR_SVR4 + 239)
+#define __NR_SVR4_CDC_reserved20	(__NR_SVR4 + 240)
+
+/*
+ * SYS V syscalls are in the range from 1000 to 1999
+ */
+#define __NR_SYSV			1000
+#define __NR_SYSV_syscall		(__NR_SYSV +   0)
+#define __NR_SYSV_exit			(__NR_SYSV +   1)
+#define __NR_SYSV_fork			(__NR_SYSV +   2)
+#define __NR_SYSV_read			(__NR_SYSV +   3)
+#define __NR_SYSV_write			(__NR_SYSV +   4)
+#define __NR_SYSV_open			(__NR_SYSV +   5)
+#define __NR_SYSV_close			(__NR_SYSV +   6)
+#define __NR_SYSV_wait			(__NR_SYSV +   7)
+#define __NR_SYSV_creat			(__NR_SYSV +   8)
+#define __NR_SYSV_link			(__NR_SYSV +   9)
+#define __NR_SYSV_unlink		(__NR_SYSV +  10)
+#define __NR_SYSV_execv			(__NR_SYSV +  11)
+#define __NR_SYSV_chdir			(__NR_SYSV +  12)
+#define __NR_SYSV_time			(__NR_SYSV +  13)
+#define __NR_SYSV_mknod			(__NR_SYSV +  14)
+#define __NR_SYSV_chmod			(__NR_SYSV +  15)
+#define __NR_SYSV_chown			(__NR_SYSV +  16)
+#define __NR_SYSV_brk			(__NR_SYSV +  17)
+#define __NR_SYSV_stat			(__NR_SYSV +  18)
+#define __NR_SYSV_lseek			(__NR_SYSV +  19)
+#define __NR_SYSV_getpid		(__NR_SYSV +  20)
+#define __NR_SYSV_mount			(__NR_SYSV +  21)
+#define __NR_SYSV_umount		(__NR_SYSV +  22)
+#define __NR_SYSV_setuid		(__NR_SYSV +  23)
+#define __NR_SYSV_getuid		(__NR_SYSV +  24)
+#define __NR_SYSV_stime			(__NR_SYSV +  25)
+#define __NR_SYSV_ptrace		(__NR_SYSV +  26)
+#define __NR_SYSV_alarm			(__NR_SYSV +  27)
+#define __NR_SYSV_fstat			(__NR_SYSV +  28)
+#define __NR_SYSV_pause			(__NR_SYSV +  29)
+#define __NR_SYSV_utime			(__NR_SYSV +  30)
+#define __NR_SYSV_stty			(__NR_SYSV +  31)
+#define __NR_SYSV_gtty			(__NR_SYSV +  32)
+#define __NR_SYSV_access		(__NR_SYSV +  33)
+#define __NR_SYSV_nice			(__NR_SYSV +  34)
+#define __NR_SYSV_statfs		(__NR_SYSV +  35)
+#define __NR_SYSV_sync			(__NR_SYSV +  36)
+#define __NR_SYSV_kill			(__NR_SYSV +  37)
+#define __NR_SYSV_fstatfs		(__NR_SYSV +  38)
+#define __NR_SYSV_setpgrp		(__NR_SYSV +  39)
+#define __NR_SYSV_syssgi		(__NR_SYSV +  40)
+#define __NR_SYSV_dup			(__NR_SYSV +  41)
+#define __NR_SYSV_pipe			(__NR_SYSV +  42)
+#define __NR_SYSV_times			(__NR_SYSV +  43)
+#define __NR_SYSV_profil		(__NR_SYSV +  44)
+#define __NR_SYSV_plock			(__NR_SYSV +  45)
+#define __NR_SYSV_setgid		(__NR_SYSV +  46)
+#define __NR_SYSV_getgid		(__NR_SYSV +  47)
+#define __NR_SYSV_sig			(__NR_SYSV +  48)
+#define __NR_SYSV_msgsys		(__NR_SYSV +  49)
+#define __NR_SYSV_sysmips		(__NR_SYSV +  50)
+#define __NR_SYSV_acct			(__NR_SYSV +  51)
+#define __NR_SYSV_shmsys		(__NR_SYSV +  52)
+#define __NR_SYSV_semsys		(__NR_SYSV +  53)
+#define __NR_SYSV_ioctl			(__NR_SYSV +  54)
+#define __NR_SYSV_uadmin		(__NR_SYSV +  55)
+#define __NR_SYSV_sysmp			(__NR_SYSV +  56)
+#define __NR_SYSV_utssys		(__NR_SYSV +  57)
+#define __NR_SYSV_USG_reserved1		(__NR_SYSV +  58)
+#define __NR_SYSV_execve		(__NR_SYSV +  59)
+#define __NR_SYSV_umask			(__NR_SYSV +  60)
+#define __NR_SYSV_chroot		(__NR_SYSV +  61)
+#define __NR_SYSV_fcntl			(__NR_SYSV +  62)
+#define __NR_SYSV_ulimit		(__NR_SYSV +  63)
+#define __NR_SYSV_SAFARI4_reserved1	(__NR_SYSV +  64)
+#define __NR_SYSV_SAFARI4_reserved2	(__NR_SYSV +  65)
+#define __NR_SYSV_SAFARI4_reserved3	(__NR_SYSV +  66)
+#define __NR_SYSV_SAFARI4_reserved4	(__NR_SYSV +  67)
+#define __NR_SYSV_SAFARI4_reserved5	(__NR_SYSV +  68)
+#define __NR_SYSV_SAFARI4_reserved6	(__NR_SYSV +  69)
+#define __NR_SYSV_advfs			(__NR_SYSV +  70)
+#define __NR_SYSV_unadvfs		(__NR_SYSV +  71)
+#define __NR_SYSV_rmount		(__NR_SYSV +  72)
+#define __NR_SYSV_rumount		(__NR_SYSV +  73)
+#define __NR_SYSV_rfstart		(__NR_SYSV +  74)
+#define __NR_SYSV_getrlimit64		(__NR_SYSV +  75)
+#define __NR_SYSV_setrlimit64		(__NR_SYSV +  76)
+#define __NR_SYSV_nanosleep		(__NR_SYSV +  77)
+#define __NR_SYSV_lseek64		(__NR_SYSV +  78)
+#define __NR_SYSV_rmdir			(__NR_SYSV +  79)
+#define __NR_SYSV_mkdir			(__NR_SYSV +  80)
+#define __NR_SYSV_getdents		(__NR_SYSV +  81)
+#define __NR_SYSV_sginap		(__NR_SYSV +  82)
+#define __NR_SYSV_sgikopt		(__NR_SYSV +  83)
+#define __NR_SYSV_sysfs			(__NR_SYSV +  84)
+#define __NR_SYSV_getmsg		(__NR_SYSV +  85)
+#define __NR_SYSV_putmsg		(__NR_SYSV +  86)
+#define __NR_SYSV_poll			(__NR_SYSV +  87)
+#define __NR_SYSV_sigreturn		(__NR_SYSV +  88)
+#define __NR_SYSV_accept		(__NR_SYSV +  89)
+#define __NR_SYSV_bind			(__NR_SYSV +  90)
+#define __NR_SYSV_connect		(__NR_SYSV +  91)
+#define __NR_SYSV_gethostid		(__NR_SYSV +  92)
+#define __NR_SYSV_getpeername		(__NR_SYSV +  93)
+#define __NR_SYSV_getsockname		(__NR_SYSV +  94)
+#define __NR_SYSV_getsockopt		(__NR_SYSV +  95)
+#define __NR_SYSV_listen		(__NR_SYSV +  96)
+#define __NR_SYSV_recv			(__NR_SYSV +  97)
+#define __NR_SYSV_recvfrom		(__NR_SYSV +  98)
+#define __NR_SYSV_recvmsg		(__NR_SYSV +  99)
+#define __NR_SYSV_select		(__NR_SYSV + 100)
+#define __NR_SYSV_send			(__NR_SYSV + 101)
+#define __NR_SYSV_sendmsg		(__NR_SYSV + 102)
+#define __NR_SYSV_sendto		(__NR_SYSV + 103)
+#define __NR_SYSV_sethostid		(__NR_SYSV + 104)
+#define __NR_SYSV_setsockopt		(__NR_SYSV + 105)
+#define __NR_SYSV_shutdown		(__NR_SYSV + 106)
+#define __NR_SYSV_socket		(__NR_SYSV + 107)
+#define __NR_SYSV_gethostname		(__NR_SYSV + 108)
+#define __NR_SYSV_sethostname		(__NR_SYSV + 109)
+#define __NR_SYSV_getdomainname		(__NR_SYSV + 110)
+#define __NR_SYSV_setdomainname		(__NR_SYSV + 111)
+#define __NR_SYSV_truncate		(__NR_SYSV + 112)
+#define __NR_SYSV_ftruncate		(__NR_SYSV + 113)
+#define __NR_SYSV_rename		(__NR_SYSV + 114)
+#define __NR_SYSV_symlink		(__NR_SYSV + 115)
+#define __NR_SYSV_readlink		(__NR_SYSV + 116)
+#define __NR_SYSV_lstat			(__NR_SYSV + 117)
+#define __NR_SYSV_nfsmount		(__NR_SYSV + 118)
+#define __NR_SYSV_nfssvc		(__NR_SYSV + 119)
+#define __NR_SYSV_getfh			(__NR_SYSV + 120)
+#define __NR_SYSV_async_daemon		(__NR_SYSV + 121)
+#define __NR_SYSV_exportfs		(__NR_SYSV + 122)
+#define __NR_SYSV_setregid		(__NR_SYSV + 123)
+#define __NR_SYSV_setreuid		(__NR_SYSV + 124)
+#define __NR_SYSV_getitimer		(__NR_SYSV + 125)
+#define __NR_SYSV_setitimer		(__NR_SYSV + 126)
+#define __NR_SYSV_adjtime		(__NR_SYSV + 127)
+#define __NR_SYSV_BSD_getime		(__NR_SYSV + 128)
+#define __NR_SYSV_sproc			(__NR_SYSV + 129)
+#define __NR_SYSV_prctl			(__NR_SYSV + 130)
+#define __NR_SYSV_procblk		(__NR_SYSV + 131)
+#define __NR_SYSV_sprocsp		(__NR_SYSV + 132)
+#define __NR_SYSV_sgigsc		(__NR_SYSV + 133)
+#define __NR_SYSV_mmap			(__NR_SYSV + 134)
+#define __NR_SYSV_munmap		(__NR_SYSV + 135)
+#define __NR_SYSV_mprotect		(__NR_SYSV + 136)
+#define __NR_SYSV_msync			(__NR_SYSV + 137)
+#define __NR_SYSV_madvise		(__NR_SYSV + 138)
+#define __NR_SYSV_pagelock		(__NR_SYSV + 139)
+#define __NR_SYSV_getpagesize		(__NR_SYSV + 140)
+#define __NR_SYSV_quotactl		(__NR_SYSV + 141)
+#define __NR_SYSV_libdetach		(__NR_SYSV + 142)
+#define __NR_SYSV_BSDgetpgrp		(__NR_SYSV + 143)
+#define __NR_SYSV_BSDsetpgrp		(__NR_SYSV + 144)
+#define __NR_SYSV_vhangup		(__NR_SYSV + 145)
+#define __NR_SYSV_fsync			(__NR_SYSV + 146)
+#define __NR_SYSV_fchdir		(__NR_SYSV + 147)
+#define __NR_SYSV_getrlimit		(__NR_SYSV + 148)
+#define __NR_SYSV_setrlimit		(__NR_SYSV + 149)
+#define __NR_SYSV_cacheflush		(__NR_SYSV + 150)
+#define __NR_SYSV_cachectl		(__NR_SYSV + 151)
+#define __NR_SYSV_fchown		(__NR_SYSV + 152)
+#define __NR_SYSV_fchmod		(__NR_SYSV + 153)
+#define __NR_SYSV_wait3			(__NR_SYSV + 154)
+#define __NR_SYSV_socketpair		(__NR_SYSV + 155)
+#define __NR_SYSV_sysinfo		(__NR_SYSV + 156)
+#define __NR_SYSV_nuname		(__NR_SYSV + 157)
+#define __NR_SYSV_xstat			(__NR_SYSV + 158)
+#define __NR_SYSV_lxstat		(__NR_SYSV + 159)
+#define __NR_SYSV_fxstat		(__NR_SYSV + 160)
+#define __NR_SYSV_xmknod		(__NR_SYSV + 161)
+#define __NR_SYSV_ksigaction		(__NR_SYSV + 162)
+#define __NR_SYSV_sigpending		(__NR_SYSV + 163)
+#define __NR_SYSV_sigprocmask		(__NR_SYSV + 164)
+#define __NR_SYSV_sigsuspend		(__NR_SYSV + 165)
+#define __NR_SYSV_sigpoll		(__NR_SYSV + 166)
+#define __NR_SYSV_swapctl		(__NR_SYSV + 167)
+#define __NR_SYSV_getcontext		(__NR_SYSV + 168)
+#define __NR_SYSV_setcontext		(__NR_SYSV + 169)
+#define __NR_SYSV_waitsys		(__NR_SYSV + 170)
+#define __NR_SYSV_sigstack		(__NR_SYSV + 171)
+#define __NR_SYSV_sigaltstack		(__NR_SYSV + 172)
+#define __NR_SYSV_sigsendset		(__NR_SYSV + 173)
+#define __NR_SYSV_statvfs		(__NR_SYSV + 174)
+#define __NR_SYSV_fstatvfs		(__NR_SYSV + 175)
+#define __NR_SYSV_getpmsg		(__NR_SYSV + 176)
+#define __NR_SYSV_putpmsg		(__NR_SYSV + 177)
+#define __NR_SYSV_lchown		(__NR_SYSV + 178)
+#define __NR_SYSV_priocntl		(__NR_SYSV + 179)
+#define __NR_SYSV_ksigqueue		(__NR_SYSV + 180)
+#define __NR_SYSV_readv			(__NR_SYSV + 181)
+#define __NR_SYSV_writev		(__NR_SYSV + 182)
+#define __NR_SYSV_truncate64		(__NR_SYSV + 183)
+#define __NR_SYSV_ftruncate64		(__NR_SYSV + 184)
+#define __NR_SYSV_mmap64		(__NR_SYSV + 185)
+#define __NR_SYSV_dmi			(__NR_SYSV + 186)
+#define __NR_SYSV_pread			(__NR_SYSV + 187)
+#define __NR_SYSV_pwrite		(__NR_SYSV + 188)
+
+/*
+ * BSD 4.3 syscalls are in the range from 2000 to 2999
+ */
+#define __NR_BSD43			2000
+#define __NR_BSD43_syscall		(__NR_BSD43 +   0)
+#define __NR_BSD43_exit			(__NR_BSD43 +   1)
+#define __NR_BSD43_fork			(__NR_BSD43 +   2)
+#define __NR_BSD43_read			(__NR_BSD43 +   3)
+#define __NR_BSD43_write		(__NR_BSD43 +   4)
+#define __NR_BSD43_open			(__NR_BSD43 +   5)
+#define __NR_BSD43_close		(__NR_BSD43 +   6)
+#define __NR_BSD43_wait			(__NR_BSD43 +   7)
+#define __NR_BSD43_creat		(__NR_BSD43 +   8)
+#define __NR_BSD43_link			(__NR_BSD43 +   9)
+#define __NR_BSD43_unlink		(__NR_BSD43 +  10)
+#define __NR_BSD43_exec			(__NR_BSD43 +  11)
+#define __NR_BSD43_chdir		(__NR_BSD43 +  12)
+#define __NR_BSD43_time			(__NR_BSD43 +  13)
+#define __NR_BSD43_mknod		(__NR_BSD43 +  14)
+#define __NR_BSD43_chmod		(__NR_BSD43 +  15)
+#define __NR_BSD43_chown		(__NR_BSD43 +  16)
+#define __NR_BSD43_sbreak		(__NR_BSD43 +  17)
+#define __NR_BSD43_oldstat		(__NR_BSD43 +  18)
+#define __NR_BSD43_lseek		(__NR_BSD43 +  19)
+#define __NR_BSD43_getpid		(__NR_BSD43 +  20)
+#define __NR_BSD43_oldmount		(__NR_BSD43 +  21)
+#define __NR_BSD43_umount		(__NR_BSD43 +  22)
+#define __NR_BSD43_setuid		(__NR_BSD43 +  23)
+#define __NR_BSD43_getuid		(__NR_BSD43 +  24)
+#define __NR_BSD43_stime		(__NR_BSD43 +  25)
+#define __NR_BSD43_ptrace		(__NR_BSD43 +  26)
+#define __NR_BSD43_alarm		(__NR_BSD43 +  27)
+#define __NR_BSD43_oldfstat		(__NR_BSD43 +  28)
+#define __NR_BSD43_pause		(__NR_BSD43 +  29)
+#define __NR_BSD43_utime		(__NR_BSD43 +  30)
+#define __NR_BSD43_stty			(__NR_BSD43 +  31)
+#define __NR_BSD43_gtty			(__NR_BSD43 +  32)
+#define __NR_BSD43_access		(__NR_BSD43 +  33)
+#define __NR_BSD43_nice			(__NR_BSD43 +  34)
+#define __NR_BSD43_ftime		(__NR_BSD43 +  35)
+#define __NR_BSD43_sync			(__NR_BSD43 +  36)
+#define __NR_BSD43_kill			(__NR_BSD43 +  37)
+#define __NR_BSD43_stat			(__NR_BSD43 +  38)
+#define __NR_BSD43_oldsetpgrp		(__NR_BSD43 +  39)
+#define __NR_BSD43_lstat		(__NR_BSD43 +  40)
+#define __NR_BSD43_dup			(__NR_BSD43 +  41)
+#define __NR_BSD43_pipe			(__NR_BSD43 +  42)
+#define __NR_BSD43_times		(__NR_BSD43 +  43)
+#define __NR_BSD43_profil		(__NR_BSD43 +  44)
+#define __NR_BSD43_msgsys		(__NR_BSD43 +  45)
+#define __NR_BSD43_setgid		(__NR_BSD43 +  46)
+#define __NR_BSD43_getgid		(__NR_BSD43 +  47)
+#define __NR_BSD43_ssig			(__NR_BSD43 +  48)
+#define __NR_BSD43_reserved1		(__NR_BSD43 +  49)
+#define __NR_BSD43_reserved2		(__NR_BSD43 +  50)
+#define __NR_BSD43_sysacct		(__NR_BSD43 +  51)
+#define __NR_BSD43_phys			(__NR_BSD43 +  52)
+#define __NR_BSD43_lock			(__NR_BSD43 +  53)
+#define __NR_BSD43_ioctl		(__NR_BSD43 +  54)
+#define __NR_BSD43_reboot		(__NR_BSD43 +  55)
+#define __NR_BSD43_mpxchan		(__NR_BSD43 +  56)
+#define __NR_BSD43_symlink		(__NR_BSD43 +  57)
+#define __NR_BSD43_readlink		(__NR_BSD43 +  58)
+#define __NR_BSD43_execve		(__NR_BSD43 +  59)
+#define __NR_BSD43_umask		(__NR_BSD43 +  60)
+#define __NR_BSD43_chroot		(__NR_BSD43 +  61)
+#define __NR_BSD43_fstat		(__NR_BSD43 +  62)
+#define __NR_BSD43_reserved3		(__NR_BSD43 +  63)
+#define __NR_BSD43_getpagesize		(__NR_BSD43 +  64)
+#define __NR_BSD43_mremap		(__NR_BSD43 +  65)
+#define __NR_BSD43_vfork		(__NR_BSD43 +  66)
+#define __NR_BSD43_vread		(__NR_BSD43 +  67)
+#define __NR_BSD43_vwrite		(__NR_BSD43 +  68)
+#define __NR_BSD43_sbrk			(__NR_BSD43 +  69)
+#define __NR_BSD43_sstk			(__NR_BSD43 +  70)
+#define __NR_BSD43_mmap			(__NR_BSD43 +  71)
+#define __NR_BSD43_vadvise		(__NR_BSD43 +  72)
+#define __NR_BSD43_munmap		(__NR_BSD43 +  73)
+#define __NR_BSD43_mprotect		(__NR_BSD43 +  74)
+#define __NR_BSD43_madvise		(__NR_BSD43 +  75)
+#define __NR_BSD43_vhangup		(__NR_BSD43 +  76)
+#define __NR_BSD43_vlimit		(__NR_BSD43 +  77)
+#define __NR_BSD43_mincore		(__NR_BSD43 +  78)
+#define __NR_BSD43_getgroups		(__NR_BSD43 +  79)
+#define __NR_BSD43_setgroups		(__NR_BSD43 +  80)
+#define __NR_BSD43_getpgrp		(__NR_BSD43 +  81)
+#define __NR_BSD43_setpgrp		(__NR_BSD43 +  82)
+#define __NR_BSD43_setitimer		(__NR_BSD43 +  83)
+#define __NR_BSD43_wait3		(__NR_BSD43 +  84)
+#define __NR_BSD43_swapon		(__NR_BSD43 +  85)
+#define __NR_BSD43_getitimer		(__NR_BSD43 +  86)
+#define __NR_BSD43_gethostname		(__NR_BSD43 +  87)
+#define __NR_BSD43_sethostname		(__NR_BSD43 +  88)
+#define __NR_BSD43_getdtablesize	(__NR_BSD43 +  89)
+#define __NR_BSD43_dup2			(__NR_BSD43 +  90)
+#define __NR_BSD43_getdopt		(__NR_BSD43 +  91)
+#define __NR_BSD43_fcntl		(__NR_BSD43 +  92)
+#define __NR_BSD43_select		(__NR_BSD43 +  93)
+#define __NR_BSD43_setdopt		(__NR_BSD43 +  94)
+#define __NR_BSD43_fsync		(__NR_BSD43 +  95)
+#define __NR_BSD43_setpriority		(__NR_BSD43 +  96)
+#define __NR_BSD43_socket		(__NR_BSD43 +  97)
+#define __NR_BSD43_connect		(__NR_BSD43 +  98)
+#define __NR_BSD43_oldaccept		(__NR_BSD43 +  99)
+#define __NR_BSD43_getpriority		(__NR_BSD43 + 100)
+#define __NR_BSD43_send			(__NR_BSD43 + 101)
+#define __NR_BSD43_recv			(__NR_BSD43 + 102)
+#define __NR_BSD43_sigreturn		(__NR_BSD43 + 103)
+#define __NR_BSD43_bind			(__NR_BSD43 + 104)
+#define __NR_BSD43_setsockopt		(__NR_BSD43 + 105)
+#define __NR_BSD43_listen		(__NR_BSD43 + 106)
+#define __NR_BSD43_vtimes		(__NR_BSD43 + 107)
+#define __NR_BSD43_sigvec		(__NR_BSD43 + 108)
+#define __NR_BSD43_sigblock		(__NR_BSD43 + 109)
+#define __NR_BSD43_sigsetmask		(__NR_BSD43 + 110)
+#define __NR_BSD43_sigpause		(__NR_BSD43 + 111)
+#define __NR_BSD43_sigstack		(__NR_BSD43 + 112)
+#define __NR_BSD43_oldrecvmsg		(__NR_BSD43 + 113)
+#define __NR_BSD43_oldsendmsg		(__NR_BSD43 + 114)
+#define __NR_BSD43_vtrace		(__NR_BSD43 + 115)
+#define __NR_BSD43_gettimeofday		(__NR_BSD43 + 116)
+#define __NR_BSD43_getrusage		(__NR_BSD43 + 117)
+#define __NR_BSD43_getsockopt		(__NR_BSD43 + 118)
+#define __NR_BSD43_reserved4		(__NR_BSD43 + 119)
+#define __NR_BSD43_readv		(__NR_BSD43 + 120)
+#define __NR_BSD43_writev		(__NR_BSD43 + 121)
+#define __NR_BSD43_settimeofday		(__NR_BSD43 + 122)
+#define __NR_BSD43_fchown		(__NR_BSD43 + 123)
+#define __NR_BSD43_fchmod		(__NR_BSD43 + 124)
+#define __NR_BSD43_oldrecvfrom		(__NR_BSD43 + 125)
+#define __NR_BSD43_setreuid		(__NR_BSD43 + 126)
+#define __NR_BSD43_setregid		(__NR_BSD43 + 127)
+#define __NR_BSD43_rename		(__NR_BSD43 + 128)
+#define __NR_BSD43_truncate		(__NR_BSD43 + 129)
+#define __NR_BSD43_ftruncate		(__NR_BSD43 + 130)
+#define __NR_BSD43_flock		(__NR_BSD43 + 131)
+#define __NR_BSD43_semsys		(__NR_BSD43 + 132)
+#define __NR_BSD43_sendto		(__NR_BSD43 + 133)
+#define __NR_BSD43_shutdown		(__NR_BSD43 + 134)
+#define __NR_BSD43_socketpair		(__NR_BSD43 + 135)
+#define __NR_BSD43_mkdir		(__NR_BSD43 + 136)
+#define __NR_BSD43_rmdir		(__NR_BSD43 + 137)
+#define __NR_BSD43_utimes		(__NR_BSD43 + 138)
+#define __NR_BSD43_sigcleanup		(__NR_BSD43 + 139)
+#define __NR_BSD43_adjtime		(__NR_BSD43 + 140)
+#define __NR_BSD43_oldgetpeername	(__NR_BSD43 + 141)
+#define __NR_BSD43_gethostid		(__NR_BSD43 + 142)
+#define __NR_BSD43_sethostid		(__NR_BSD43 + 143)
+#define __NR_BSD43_getrlimit		(__NR_BSD43 + 144)
+#define __NR_BSD43_setrlimit		(__NR_BSD43 + 145)
+#define __NR_BSD43_killpg		(__NR_BSD43 + 146)
+#define __NR_BSD43_shmsys		(__NR_BSD43 + 147)
+#define __NR_BSD43_quota		(__NR_BSD43 + 148)
+#define __NR_BSD43_qquota		(__NR_BSD43 + 149)
+#define __NR_BSD43_oldgetsockname	(__NR_BSD43 + 150)
+#define __NR_BSD43_sysmips		(__NR_BSD43 + 151)
+#define __NR_BSD43_cacheflush		(__NR_BSD43 + 152)
+#define __NR_BSD43_cachectl		(__NR_BSD43 + 153)
+#define __NR_BSD43_debug		(__NR_BSD43 + 154)
+#define __NR_BSD43_reserved5		(__NR_BSD43 + 155)
+#define __NR_BSD43_reserved6		(__NR_BSD43 + 156)
+#define __NR_BSD43_nfs_mount		(__NR_BSD43 + 157)
+#define __NR_BSD43_nfs_svc		(__NR_BSD43 + 158)
+#define __NR_BSD43_getdirentries	(__NR_BSD43 + 159)
+#define __NR_BSD43_statfs		(__NR_BSD43 + 160)
+#define __NR_BSD43_fstatfs		(__NR_BSD43 + 161)
+#define __NR_BSD43_unmount		(__NR_BSD43 + 162)
+#define __NR_BSD43_async_daemon		(__NR_BSD43 + 163)
+#define __NR_BSD43_nfs_getfh		(__NR_BSD43 + 164)
+#define __NR_BSD43_getdomainname	(__NR_BSD43 + 165)
+#define __NR_BSD43_setdomainname	(__NR_BSD43 + 166)
+#define __NR_BSD43_pcfs_mount		(__NR_BSD43 + 167)
+#define __NR_BSD43_quotactl		(__NR_BSD43 + 168)
+#define __NR_BSD43_oldexportfs		(__NR_BSD43 + 169)
+#define __NR_BSD43_smount		(__NR_BSD43 + 170)
+#define __NR_BSD43_mipshwconf		(__NR_BSD43 + 171)
+#define __NR_BSD43_exportfs		(__NR_BSD43 + 172)
+#define __NR_BSD43_nfsfh_open		(__NR_BSD43 + 173)
+#define __NR_BSD43_libattach		(__NR_BSD43 + 174)
+#define __NR_BSD43_libdetach		(__NR_BSD43 + 175)
+#define __NR_BSD43_accept		(__NR_BSD43 + 176)
+#define __NR_BSD43_reserved7		(__NR_BSD43 + 177)
+#define __NR_BSD43_reserved8		(__NR_BSD43 + 178)
+#define __NR_BSD43_recvmsg		(__NR_BSD43 + 179)
+#define __NR_BSD43_recvfrom		(__NR_BSD43 + 180)
+#define __NR_BSD43_sendmsg		(__NR_BSD43 + 181)
+#define __NR_BSD43_getpeername		(__NR_BSD43 + 182)
+#define __NR_BSD43_getsockname		(__NR_BSD43 + 183)
+#define __NR_BSD43_aread		(__NR_BSD43 + 184)
+#define __NR_BSD43_awrite		(__NR_BSD43 + 185)
+#define __NR_BSD43_listio		(__NR_BSD43 + 186)
+#define __NR_BSD43_acancel		(__NR_BSD43 + 187)
+#define __NR_BSD43_astatus		(__NR_BSD43 + 188)
+#define __NR_BSD43_await		(__NR_BSD43 + 189)
+#define __NR_BSD43_areadv		(__NR_BSD43 + 190)
+#define __NR_BSD43_awritev		(__NR_BSD43 + 191)
+
+/*
+ * POSIX syscalls are in the range from 3000 to 3999
+ */
+#define __NR_POSIX			3000
+#define __NR_POSIX_syscall		(__NR_POSIX +   0)
+#define __NR_POSIX_exit			(__NR_POSIX +   1)
+#define __NR_POSIX_fork			(__NR_POSIX +   2)
+#define __NR_POSIX_read			(__NR_POSIX +   3)
+#define __NR_POSIX_write		(__NR_POSIX +   4)
+#define __NR_POSIX_open			(__NR_POSIX +   5)
+#define __NR_POSIX_close		(__NR_POSIX +   6)
+#define __NR_POSIX_wait			(__NR_POSIX +   7)
+#define __NR_POSIX_creat		(__NR_POSIX +   8)
+#define __NR_POSIX_link			(__NR_POSIX +   9)
+#define __NR_POSIX_unlink		(__NR_POSIX +  10)
+#define __NR_POSIX_exec			(__NR_POSIX +  11)
+#define __NR_POSIX_chdir		(__NR_POSIX +  12)
+#define __NR_POSIX_gtime		(__NR_POSIX +  13)
+#define __NR_POSIX_mknod		(__NR_POSIX +  14)
+#define __NR_POSIX_chmod		(__NR_POSIX +  15)
+#define __NR_POSIX_chown		(__NR_POSIX +  16)
+#define __NR_POSIX_sbreak		(__NR_POSIX +  17)
+#define __NR_POSIX_stat			(__NR_POSIX +  18)
+#define __NR_POSIX_lseek		(__NR_POSIX +  19)
+#define __NR_POSIX_getpid		(__NR_POSIX +  20)
+#define __NR_POSIX_mount		(__NR_POSIX +  21)
+#define __NR_POSIX_umount		(__NR_POSIX +  22)
+#define __NR_POSIX_setuid		(__NR_POSIX +  23)
+#define __NR_POSIX_getuid		(__NR_POSIX +  24)
+#define __NR_POSIX_stime		(__NR_POSIX +  25)
+#define __NR_POSIX_ptrace		(__NR_POSIX +  26)
+#define __NR_POSIX_alarm		(__NR_POSIX +  27)
+#define __NR_POSIX_fstat		(__NR_POSIX +  28)
+#define __NR_POSIX_pause		(__NR_POSIX +  29)
+#define __NR_POSIX_utime		(__NR_POSIX +  30)
+#define __NR_POSIX_stty			(__NR_POSIX +  31)
+#define __NR_POSIX_gtty			(__NR_POSIX +  32)
+#define __NR_POSIX_access		(__NR_POSIX +  33)
+#define __NR_POSIX_nice			(__NR_POSIX +  34)
+#define __NR_POSIX_statfs		(__NR_POSIX +  35)
+#define __NR_POSIX_sync			(__NR_POSIX +  36)
+#define __NR_POSIX_kill			(__NR_POSIX +  37)
+#define __NR_POSIX_fstatfs		(__NR_POSIX +  38)
+#define __NR_POSIX_getpgrp		(__NR_POSIX +  39)
+#define __NR_POSIX_syssgi		(__NR_POSIX +  40)
+#define __NR_POSIX_dup			(__NR_POSIX +  41)
+#define __NR_POSIX_pipe			(__NR_POSIX +  42)
+#define __NR_POSIX_times		(__NR_POSIX +  43)
+#define __NR_POSIX_profil		(__NR_POSIX +  44)
+#define __NR_POSIX_lock			(__NR_POSIX +  45)
+#define __NR_POSIX_setgid		(__NR_POSIX +  46)
+#define __NR_POSIX_getgid		(__NR_POSIX +  47)
+#define __NR_POSIX_sig			(__NR_POSIX +  48)
+#define __NR_POSIX_msgsys		(__NR_POSIX +  49)
+#define __NR_POSIX_sysmips		(__NR_POSIX +  50)
+#define __NR_POSIX_sysacct		(__NR_POSIX +  51)
+#define __NR_POSIX_shmsys		(__NR_POSIX +  52)
+#define __NR_POSIX_semsys		(__NR_POSIX +  53)
+#define __NR_POSIX_ioctl		(__NR_POSIX +  54)
+#define __NR_POSIX_uadmin		(__NR_POSIX +  55)
+#define __NR_POSIX_exch			(__NR_POSIX +  56)
+#define __NR_POSIX_utssys		(__NR_POSIX +  57)
+#define __NR_POSIX_USG_reserved1	(__NR_POSIX +  58)
+#define __NR_POSIX_exece		(__NR_POSIX +  59)
+#define __NR_POSIX_umask		(__NR_POSIX +  60)
+#define __NR_POSIX_chroot		(__NR_POSIX +  61)
+#define __NR_POSIX_fcntl		(__NR_POSIX +  62)
+#define __NR_POSIX_ulimit		(__NR_POSIX +  63)
+#define __NR_POSIX_SAFARI4_reserved1	(__NR_POSIX +  64)
+#define __NR_POSIX_SAFARI4_reserved2	(__NR_POSIX +  65)
+#define __NR_POSIX_SAFARI4_reserved3	(__NR_POSIX +  66)
+#define __NR_POSIX_SAFARI4_reserved4	(__NR_POSIX +  67)
+#define __NR_POSIX_SAFARI4_reserved5	(__NR_POSIX +  68)
+#define __NR_POSIX_SAFARI4_reserved6	(__NR_POSIX +  69)
+#define __NR_POSIX_advfs		(__NR_POSIX +  70)
+#define __NR_POSIX_unadvfs		(__NR_POSIX +  71)
+#define __NR_POSIX_rmount		(__NR_POSIX +  72)
+#define __NR_POSIX_rumount		(__NR_POSIX +  73)
+#define __NR_POSIX_rfstart		(__NR_POSIX +  74)
+#define __NR_POSIX_reserved1		(__NR_POSIX +  75)
+#define __NR_POSIX_rdebug		(__NR_POSIX +  76)
+#define __NR_POSIX_rfstop		(__NR_POSIX +  77)
+#define __NR_POSIX_rfsys		(__NR_POSIX +  78)
+#define __NR_POSIX_rmdir		(__NR_POSIX +  79)
+#define __NR_POSIX_mkdir		(__NR_POSIX +  80)
+#define __NR_POSIX_getdents		(__NR_POSIX +  81)
+#define __NR_POSIX_sginap		(__NR_POSIX +  82)
+#define __NR_POSIX_sgikopt		(__NR_POSIX +  83)
+#define __NR_POSIX_sysfs		(__NR_POSIX +  84)
+#define __NR_POSIX_getmsg		(__NR_POSIX +  85)
+#define __NR_POSIX_putmsg		(__NR_POSIX +  86)
+#define __NR_POSIX_poll			(__NR_POSIX +  87)
+#define __NR_POSIX_sigreturn		(__NR_POSIX +  88)
+#define __NR_POSIX_accept		(__NR_POSIX +  89)
+#define __NR_POSIX_bind			(__NR_POSIX +  90)
+#define __NR_POSIX_connect		(__NR_POSIX +  91)
+#define __NR_POSIX_gethostid		(__NR_POSIX +  92)
+#define __NR_POSIX_getpeername		(__NR_POSIX +  93)
+#define __NR_POSIX_getsockname		(__NR_POSIX +  94)
+#define __NR_POSIX_getsockopt		(__NR_POSIX +  95)
+#define __NR_POSIX_listen		(__NR_POSIX +  96)
+#define __NR_POSIX_recv			(__NR_POSIX +  97)
+#define __NR_POSIX_recvfrom		(__NR_POSIX +  98)
+#define __NR_POSIX_recvmsg		(__NR_POSIX +  99)
+#define __NR_POSIX_select		(__NR_POSIX + 100)
+#define __NR_POSIX_send			(__NR_POSIX + 101)
+#define __NR_POSIX_sendmsg		(__NR_POSIX + 102)
+#define __NR_POSIX_sendto		(__NR_POSIX + 103)
+#define __NR_POSIX_sethostid		(__NR_POSIX + 104)
+#define __NR_POSIX_setsockopt		(__NR_POSIX + 105)
+#define __NR_POSIX_shutdown		(__NR_POSIX + 106)
+#define __NR_POSIX_socket		(__NR_POSIX + 107)
+#define __NR_POSIX_gethostname		(__NR_POSIX + 108)
+#define __NR_POSIX_sethostname		(__NR_POSIX + 109)
+#define __NR_POSIX_getdomainname	(__NR_POSIX + 110)
+#define __NR_POSIX_setdomainname	(__NR_POSIX + 111)
+#define __NR_POSIX_truncate		(__NR_POSIX + 112)
+#define __NR_POSIX_ftruncate		(__NR_POSIX + 113)
+#define __NR_POSIX_rename		(__NR_POSIX + 114)
+#define __NR_POSIX_symlink		(__NR_POSIX + 115)
+#define __NR_POSIX_readlink		(__NR_POSIX + 116)
+#define __NR_POSIX_lstat		(__NR_POSIX + 117)
+#define __NR_POSIX_nfs_mount		(__NR_POSIX + 118)
+#define __NR_POSIX_nfs_svc		(__NR_POSIX + 119)
+#define __NR_POSIX_nfs_getfh		(__NR_POSIX + 120)
+#define __NR_POSIX_async_daemon		(__NR_POSIX + 121)
+#define __NR_POSIX_exportfs		(__NR_POSIX + 122)
+#define __NR_POSIX_SGI_setregid		(__NR_POSIX + 123)
+#define __NR_POSIX_SGI_setreuid		(__NR_POSIX + 124)
+#define __NR_POSIX_getitimer		(__NR_POSIX + 125)
+#define __NR_POSIX_setitimer		(__NR_POSIX + 126)
+#define __NR_POSIX_adjtime		(__NR_POSIX + 127)
+#define __NR_POSIX_SGI_bsdgettime	(__NR_POSIX + 128)
+#define __NR_POSIX_SGI_sproc		(__NR_POSIX + 129)
+#define __NR_POSIX_SGI_prctl		(__NR_POSIX + 130)
+#define __NR_POSIX_SGI_blkproc		(__NR_POSIX + 131)
+#define __NR_POSIX_SGI_reserved1	(__NR_POSIX + 132)
+#define __NR_POSIX_SGI_sgigsc		(__NR_POSIX + 133)
+#define __NR_POSIX_SGI_mmap		(__NR_POSIX + 134)
+#define __NR_POSIX_SGI_munmap		(__NR_POSIX + 135)
+#define __NR_POSIX_SGI_mprotect		(__NR_POSIX + 136)
+#define __NR_POSIX_SGI_msync		(__NR_POSIX + 137)
+#define __NR_POSIX_SGI_madvise		(__NR_POSIX + 138)
+#define __NR_POSIX_SGI_mpin		(__NR_POSIX + 139)
+#define __NR_POSIX_SGI_getpagesize	(__NR_POSIX + 140)
+#define __NR_POSIX_SGI_libattach	(__NR_POSIX + 141)
+#define __NR_POSIX_SGI_libdetach	(__NR_POSIX + 142)
+#define __NR_POSIX_SGI_getpgrp		(__NR_POSIX + 143)
+#define __NR_POSIX_SGI_setpgrp		(__NR_POSIX + 144)
+#define __NR_POSIX_SGI_reserved2	(__NR_POSIX + 145)
+#define __NR_POSIX_SGI_reserved3	(__NR_POSIX + 146)
+#define __NR_POSIX_SGI_reserved4	(__NR_POSIX + 147)
+#define __NR_POSIX_SGI_reserved5	(__NR_POSIX + 148)
+#define __NR_POSIX_SGI_reserved6	(__NR_POSIX + 149)
+#define __NR_POSIX_cacheflush		(__NR_POSIX + 150)
+#define __NR_POSIX_cachectl		(__NR_POSIX + 151)
+#define __NR_POSIX_fchown		(__NR_POSIX + 152)
+#define __NR_POSIX_fchmod		(__NR_POSIX + 153)
+#define __NR_POSIX_wait3		(__NR_POSIX + 154)
+#define __NR_POSIX_mmap			(__NR_POSIX + 155)
+#define __NR_POSIX_munmap		(__NR_POSIX + 156)
+#define __NR_POSIX_madvise		(__NR_POSIX + 157)
+#define __NR_POSIX_BSD_getpagesize	(__NR_POSIX + 158)
+#define __NR_POSIX_setreuid		(__NR_POSIX + 159)
+#define __NR_POSIX_setregid		(__NR_POSIX + 160)
+#define __NR_POSIX_setpgid		(__NR_POSIX + 161)
+#define __NR_POSIX_getgroups		(__NR_POSIX + 162)
+#define __NR_POSIX_setgroups		(__NR_POSIX + 163)
+#define __NR_POSIX_gettimeofday		(__NR_POSIX + 164)
+#define __NR_POSIX_getrusage		(__NR_POSIX + 165)
+#define __NR_POSIX_getrlimit		(__NR_POSIX + 166)
+#define __NR_POSIX_setrlimit		(__NR_POSIX + 167)
+#define __NR_POSIX_waitpid		(__NR_POSIX + 168)
+#define __NR_POSIX_dup2			(__NR_POSIX + 169)
+#define __NR_POSIX_reserved2		(__NR_POSIX + 170)
+#define __NR_POSIX_reserved3		(__NR_POSIX + 171)
+#define __NR_POSIX_reserved4		(__NR_POSIX + 172)
+#define __NR_POSIX_reserved5		(__NR_POSIX + 173)
+#define __NR_POSIX_reserved6		(__NR_POSIX + 174)
+#define __NR_POSIX_reserved7		(__NR_POSIX + 175)
+#define __NR_POSIX_reserved8		(__NR_POSIX + 176)
+#define __NR_POSIX_reserved9		(__NR_POSIX + 177)
+#define __NR_POSIX_reserved10		(__NR_POSIX + 178)
+#define __NR_POSIX_reserved11		(__NR_POSIX + 179)
+#define __NR_POSIX_reserved12		(__NR_POSIX + 180)
+#define __NR_POSIX_reserved13		(__NR_POSIX + 181)
+#define __NR_POSIX_reserved14		(__NR_POSIX + 182)
+#define __NR_POSIX_reserved15		(__NR_POSIX + 183)
+#define __NR_POSIX_reserved16		(__NR_POSIX + 184)
+#define __NR_POSIX_reserved17		(__NR_POSIX + 185)
+#define __NR_POSIX_reserved18		(__NR_POSIX + 186)
+#define __NR_POSIX_reserved19		(__NR_POSIX + 187)
+#define __NR_POSIX_reserved20		(__NR_POSIX + 188)
+#define __NR_POSIX_reserved21		(__NR_POSIX + 189)
+#define __NR_POSIX_reserved22		(__NR_POSIX + 190)
+#define __NR_POSIX_reserved23		(__NR_POSIX + 191)
+#define __NR_POSIX_reserved24		(__NR_POSIX + 192)
+#define __NR_POSIX_reserved25		(__NR_POSIX + 193)
+#define __NR_POSIX_reserved26		(__NR_POSIX + 194)
+#define __NR_POSIX_reserved27		(__NR_POSIX + 195)
+#define __NR_POSIX_reserved28		(__NR_POSIX + 196)
+#define __NR_POSIX_reserved29		(__NR_POSIX + 197)
+#define __NR_POSIX_reserved30		(__NR_POSIX + 198)
+#define __NR_POSIX_reserved31		(__NR_POSIX + 199)
+#define __NR_POSIX_reserved32		(__NR_POSIX + 200)
+#define __NR_POSIX_reserved33		(__NR_POSIX + 201)
+#define __NR_POSIX_reserved34		(__NR_POSIX + 202)
+#define __NR_POSIX_reserved35		(__NR_POSIX + 203)
+#define __NR_POSIX_reserved36		(__NR_POSIX + 204)
+#define __NR_POSIX_reserved37		(__NR_POSIX + 205)
+#define __NR_POSIX_reserved38		(__NR_POSIX + 206)
+#define __NR_POSIX_reserved39		(__NR_POSIX + 207)
+#define __NR_POSIX_reserved40		(__NR_POSIX + 208)
+#define __NR_POSIX_reserved41		(__NR_POSIX + 209)
+#define __NR_POSIX_reserved42		(__NR_POSIX + 210)
+#define __NR_POSIX_reserved43		(__NR_POSIX + 211)
+#define __NR_POSIX_reserved44		(__NR_POSIX + 212)
+#define __NR_POSIX_reserved45		(__NR_POSIX + 213)
+#define __NR_POSIX_reserved46		(__NR_POSIX + 214)
+#define __NR_POSIX_reserved47		(__NR_POSIX + 215)
+#define __NR_POSIX_reserved48		(__NR_POSIX + 216)
+#define __NR_POSIX_reserved49		(__NR_POSIX + 217)
+#define __NR_POSIX_reserved50		(__NR_POSIX + 218)
+#define __NR_POSIX_reserved51		(__NR_POSIX + 219)
+#define __NR_POSIX_reserved52		(__NR_POSIX + 220)
+#define __NR_POSIX_reserved53		(__NR_POSIX + 221)
+#define __NR_POSIX_reserved54		(__NR_POSIX + 222)
+#define __NR_POSIX_reserved55		(__NR_POSIX + 223)
+#define __NR_POSIX_reserved56		(__NR_POSIX + 224)
+#define __NR_POSIX_reserved57		(__NR_POSIX + 225)
+#define __NR_POSIX_reserved58		(__NR_POSIX + 226)
+#define __NR_POSIX_reserved59		(__NR_POSIX + 227)
+#define __NR_POSIX_reserved60		(__NR_POSIX + 228)
+#define __NR_POSIX_reserved61		(__NR_POSIX + 229)
+#define __NR_POSIX_reserved62		(__NR_POSIX + 230)
+#define __NR_POSIX_reserved63		(__NR_POSIX + 231)
+#define __NR_POSIX_reserved64		(__NR_POSIX + 232)
+#define __NR_POSIX_reserved65		(__NR_POSIX + 233)
+#define __NR_POSIX_reserved66		(__NR_POSIX + 234)
+#define __NR_POSIX_reserved67		(__NR_POSIX + 235)
+#define __NR_POSIX_reserved68		(__NR_POSIX + 236)
+#define __NR_POSIX_reserved69		(__NR_POSIX + 237)
+#define __NR_POSIX_reserved70		(__NR_POSIX + 238)
+#define __NR_POSIX_reserved71		(__NR_POSIX + 239)
+#define __NR_POSIX_reserved72		(__NR_POSIX + 240)
+#define __NR_POSIX_reserved73		(__NR_POSIX + 241)
+#define __NR_POSIX_reserved74		(__NR_POSIX + 242)
+#define __NR_POSIX_reserved75		(__NR_POSIX + 243)
+#define __NR_POSIX_reserved76		(__NR_POSIX + 244)
+#define __NR_POSIX_reserved77		(__NR_POSIX + 245)
+#define __NR_POSIX_reserved78		(__NR_POSIX + 246)
+#define __NR_POSIX_reserved79		(__NR_POSIX + 247)
+#define __NR_POSIX_reserved80		(__NR_POSIX + 248)
+#define __NR_POSIX_reserved81		(__NR_POSIX + 249)
+#define __NR_POSIX_reserved82		(__NR_POSIX + 250)
+#define __NR_POSIX_reserved83		(__NR_POSIX + 251)
+#define __NR_POSIX_reserved84		(__NR_POSIX + 252)
+#define __NR_POSIX_reserved85		(__NR_POSIX + 253)
+#define __NR_POSIX_reserved86		(__NR_POSIX + 254)
+#define __NR_POSIX_reserved87		(__NR_POSIX + 255)
+#define __NR_POSIX_reserved88		(__NR_POSIX + 256)
+#define __NR_POSIX_reserved89		(__NR_POSIX + 257)
+#define __NR_POSIX_reserved90		(__NR_POSIX + 258)
+#define __NR_POSIX_reserved91		(__NR_POSIX + 259)
+#define __NR_POSIX_netboot		(__NR_POSIX + 260)
+#define __NR_POSIX_netunboot		(__NR_POSIX + 261)
+#define __NR_POSIX_rdump		(__NR_POSIX + 262)
+#define __NR_POSIX_setsid		(__NR_POSIX + 263)
+#define __NR_POSIX_getmaxsig		(__NR_POSIX + 264)
+#define __NR_POSIX_sigpending		(__NR_POSIX + 265)
+#define __NR_POSIX_sigprocmask		(__NR_POSIX + 266)
+#define __NR_POSIX_sigsuspend		(__NR_POSIX + 267)
+#define __NR_POSIX_sigaction		(__NR_POSIX + 268)
+#define __NR_POSIX_MIPS_reserved1	(__NR_POSIX + 269)
+#define __NR_POSIX_MIPS_reserved2	(__NR_POSIX + 270)
+#define __NR_POSIX_MIPS_reserved3	(__NR_POSIX + 271)
+#define __NR_POSIX_MIPS_reserved4	(__NR_POSIX + 272)
+#define __NR_POSIX_MIPS_reserved5	(__NR_POSIX + 273)
+#define __NR_POSIX_MIPS_reserved6	(__NR_POSIX + 274)
+#define __NR_POSIX_MIPS_reserved7	(__NR_POSIX + 275)
+#define __NR_POSIX_MIPS_reserved8	(__NR_POSIX + 276)
+#define __NR_POSIX_MIPS_reserved9	(__NR_POSIX + 277)
+#define __NR_POSIX_MIPS_reserved10	(__NR_POSIX + 278)
+#define __NR_POSIX_MIPS_reserved11	(__NR_POSIX + 279)
+#define __NR_POSIX_TANDEM_reserved1	(__NR_POSIX + 280)
+#define __NR_POSIX_TANDEM_reserved2	(__NR_POSIX + 281)
+#define __NR_POSIX_TANDEM_reserved3	(__NR_POSIX + 282)
+#define __NR_POSIX_TANDEM_reserved4	(__NR_POSIX + 283)
+#define __NR_POSIX_TANDEM_reserved5	(__NR_POSIX + 284)
+#define __NR_POSIX_TANDEM_reserved6	(__NR_POSIX + 285)
+#define __NR_POSIX_TANDEM_reserved7	(__NR_POSIX + 286)
+#define __NR_POSIX_TANDEM_reserved8	(__NR_POSIX + 287)
+#define __NR_POSIX_TANDEM_reserved9	(__NR_POSIX + 288)
+#define __NR_POSIX_TANDEM_reserved10	(__NR_POSIX + 289)
+#define __NR_POSIX_TANDEM_reserved11	(__NR_POSIX + 290)
+#define __NR_POSIX_TANDEM_reserved12	(__NR_POSIX + 291)
+#define __NR_POSIX_TANDEM_reserved13	(__NR_POSIX + 292)
+#define __NR_POSIX_TANDEM_reserved14	(__NR_POSIX + 293)
+#define __NR_POSIX_TANDEM_reserved15	(__NR_POSIX + 294)
+#define __NR_POSIX_TANDEM_reserved16	(__NR_POSIX + 295)
+#define __NR_POSIX_TANDEM_reserved17	(__NR_POSIX + 296)
+#define __NR_POSIX_TANDEM_reserved18	(__NR_POSIX + 297)
+#define __NR_POSIX_TANDEM_reserved19	(__NR_POSIX + 298)
+#define __NR_POSIX_TANDEM_reserved20	(__NR_POSIX + 299)
+#define __NR_POSIX_SGI_reserved7	(__NR_POSIX + 300)
+#define __NR_POSIX_SGI_reserved8	(__NR_POSIX + 301)
+#define __NR_POSIX_SGI_reserved9	(__NR_POSIX + 302)
+#define __NR_POSIX_SGI_reserved10	(__NR_POSIX + 303)
+#define __NR_POSIX_SGI_reserved11	(__NR_POSIX + 304)
+#define __NR_POSIX_SGI_reserved12	(__NR_POSIX + 305)
+#define __NR_POSIX_SGI_reserved13	(__NR_POSIX + 306)
+#define __NR_POSIX_SGI_reserved14	(__NR_POSIX + 307)
+#define __NR_POSIX_SGI_reserved15	(__NR_POSIX + 308)
+#define __NR_POSIX_SGI_reserved16	(__NR_POSIX + 309)
+#define __NR_POSIX_SGI_reserved17	(__NR_POSIX + 310)
+#define __NR_POSIX_SGI_reserved18	(__NR_POSIX + 311)
+#define __NR_POSIX_SGI_reserved19	(__NR_POSIX + 312)
+#define __NR_POSIX_SGI_reserved20	(__NR_POSIX + 313)
+#define __NR_POSIX_SGI_reserved21	(__NR_POSIX + 314)
+#define __NR_POSIX_SGI_reserved22	(__NR_POSIX + 315)
+#define __NR_POSIX_SGI_reserved23	(__NR_POSIX + 316)
+#define __NR_POSIX_SGI_reserved24	(__NR_POSIX + 317)
+#define __NR_POSIX_SGI_reserved25	(__NR_POSIX + 318)
+#define __NR_POSIX_SGI_reserved26	(__NR_POSIX + 319)
+
+#endif /* _ASM_RISCOS_SYSCALL_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/semaphore-helper.h linux/include/asm-mips/semaphore-helper.h
--- linux-2.4.6-pre8/include/asm-mips/semaphore-helper.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/semaphore-helper.h	Mon Dec  3 22:50:39 2001
@@ -1,11 +1,11 @@
-/* $Id: semaphore-helper.h,v 1.6 1999/10/20 21:10:58 ralf Exp $
- *
+/*
  * SMP- and interrupt-safe semaphores helper functions.
  *
- * (C) Copyright 1996 Linus Torvalds
- * (C) Copyright 1999 Andrea Arcangeli
- * (C) Copyright 1999 Ralf Baechle
- * (C) Copyright 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996 Linus Torvalds
+ * Copyright (C) 1999 Andrea Arcangeli
+ * Copyright (C) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2000 MIPS Technologies, Inc.
  */
 #ifndef _ASM_SEMAPHORE_HELPER_H
 #define _ASM_SEMAPHORE_HELPER_H
@@ -20,7 +20,7 @@
 	atomic_inc(&sem->waking);
 }
 
-#if !defined(CONFIG_CPU_HAS_LLSC)
+#if !defined(CONFIG_CPU_HAS_LLSC) || defined(CONFIG_CPU_MIPS32)
 
 /*
  * It doesn't make sense, IMHO, to endlessly turn interrupts off and on again.
@@ -75,6 +75,7 @@
 		ret = 0;
 	}
 	restore_flags(flags);
+
 	return ret;
 }
 
@@ -92,7 +93,7 @@
 	"sc\t%0, %2\n\t"
 	"beqz\t%0, 1b\n\t"
 	"2:"
-	: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
+	: "=r" (ret), "=r" (tmp), "=m" (sem->waking)
 	: "0"(0));
 
 	return ret;
@@ -133,29 +134,26 @@
 {
 	long ret, tmp;
 
-        __asm__ __volatile__("
-	.set	push
-	.set	mips3
-	.set	noat
-0:	lld	%1, %2
-	li	%0, 0
-	sll	$1, %1, 0
-	blez	$1, 1f
-	daddiu	%1, %1, -1
-	li	%0, 1
-	b 	2f
-1:
-	beqz	%3, 2f
-	li	%0, %4
-	dli	$1, 0x0000000100000000
-	daddu	%1, %1, $1
-2:
-	scd	%1, %2
-	beqz	%1, 0b
-
-	.set	pop"
-	: "=&r"(ret), "=&r"(tmp), "=m"(*sem)
-	: "r"(signal_pending(tsk)), "i"(-EINTR));
+	__asm__ __volatile__(
+	".set\tpush\n\t"
+	".set\tmips3\n\t"
+	".set\tnoat\n"
+	"0:\tlld\t%1, %2\n\t"
+	"li\t%0, 0\n\t"
+	"sll\t$1, %1, 0\n\t"
+	"blez\t$1, 1f\n\t"
+	"daddiu\t%1, %1, -1\n\t"
+	"li\t%0, 1\n\t"
+	"b\t2f\n"
+	"1:\tbeqz\t%3, 2f\n\t"
+	"li\t%0, %4\n\t"
+	"dli\t$1, 0x0000000100000000\n\t"
+	"daddu\t%1, %1, $1\n"
+	"2:\tscd\t%1, %2\n\t"
+	"beqz\t%1, 0b\n\t"
+	".set\tpop"
+	: "=&r" (ret), "=&r" (tmp), "=m" (*sem)
+	: "r" (signal_pending(tsk)), "i" (-EINTR));
 
 	return ret;
 }
diff -urN linux-2.4.6-pre8/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- linux-2.4.6-pre8/include/asm-mips/semaphore.h	Tue Apr 17 17:19:31 2001
+++ linux/include/asm-mips/semaphore.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: semaphore.h,v 1.12 1999/12/08 22:05:10 harald Exp $
- *
+/*
  * SMP- and interrupt-safe semaphores..
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,6 +8,7 @@
  * (C) Copyright 1996  Linus Torvalds
  * (C) Copyright 1998, 1999, 2000  Ralf Baechle
  * (C) Copyright 1999, 2000  Silicon Graphics, Inc.
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  */
 #ifndef _ASM_SEMAPHORE_H
 #define _ASM_SEMAPHORE_H
@@ -60,7 +60,7 @@
 #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);
@@ -85,7 +85,7 @@
 asmlinkage int __down_trylock(struct semaphore * sem);
 asmlinkage 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);
@@ -94,7 +94,7 @@
 		__down(sem);
 }
 
-extern inline int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
@@ -106,9 +106,9 @@
 	return ret;
 }
 
-#if !defined(CONFIG_CPU_HAS_LLSC)
+#if !defined(CONFIG_CPU_HAS_LLSC) || defined(CONFIG_CPU_MIPS32)
 
-extern inline int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
 	if (atomic_dec_return(&sem->count) < 0)
@@ -140,7 +140,7 @@
  *	}
  *   }
  */
-extern inline int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
 {
 	long ret, tmp, tmp2, sub;
 
@@ -148,29 +148,25 @@
 	CHECK_MAGIC(sem->__magic);
 #endif
 
-	__asm__ __volatile__("
-			.set	mips3
-
-		0:	lld	%1, %4
-			dli	%3, 0x0000000100000000
-			dsubu	%1, %3
-			li	%0, 0
-			bgez	%1, 2f
-			sll	%2, %1, 0
-			blez	%2, 1f
-			daddiu	%1, %1, -1
-			b	2f
-		1:
-			daddu	%1, %1, %3
-			li	%0, 1
-		2:
-			scd	%1, %4
-			beqz	%1, 0b
-
-			.set	mips0"
-		: "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub)
-		: "m"(*sem)
-		: "memory");
+	__asm__ __volatile__(
+	".set\tmips3\t\t\t# down_trylock\n"
+	"0:\tlld\t%1, %4\n\t"
+	"dli\t%3, 0x0000000100000000\n\t"
+	"dsubu\t%1, %3\n\t"
+	"li\t%0, 0\n\t"
+	"bgez\t%1, 2f\n\t"
+	"sll\t%2, %1, 0\n\t"
+	"blez\t%2, 1f\n\t"
+	"daddiu\t%1, %1, -1\n\t"
+	"b\t2f\n\t"
+	"1:\tdaddu\t%1, %1, %3\n"
+	"li\t%0, 1\n"
+	"2:\tscd\t%1, %4\n\t"
+	"beqz\t%1, 0b\n\t"
+	".set	mips0"
+	: "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub)
+	: "m"(*sem)
+	: "memory");
 
 	return ret;
 }
@@ -181,183 +177,13 @@
  * Note! This is subtle. We jump to wake people up only if
  * the semaphore was negative (== somebody was waiting on it).
  */
-extern inline void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
 {
 #if WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/*
- * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
- * semaphores together, and this is what we end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer subtracts BIAS ands
- * gets 0 for the case of an uncontended lock.  Readers decrement by 1 and
- * see a positive value when uncontended, negative if there are writers
- * waiting (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and lots of processes.
- * BIAS must be chosen such that subtracting BIAS once per CPU will result
- * in the int remaining negative.  In terms of fairness, this should result
- * in the lock flopping back and forth between readers and writers under
- * heavy use.
- *
- * Once we start supporting machines with more than 128 CPUs, we should go
- * for using a 64bit atomic type instead of 32bit as counter. We shall
- * probably go for bias 0x80000000 then, so that single sethi can set it.
- * */
-
-#define RW_LOCK_BIAS		0x01000000
-
-struct rw_semaphore {
-	atomic_t		count;
-	/* bit 0 means read bias granted;
-	   bit 1 means write bias granted.  */
-	unsigned long		granted; /* pedant: long req'd for set_bit */
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)					\
-	{ ATOMIC_INIT(count), 0,					\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),			\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)		\
-	  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) \
-	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) \
-	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) \
-	__DECLARE_RWSEM_GENERIC(name, 0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-/* The expensive part is outlined.  */
-extern void __down_read(struct rw_semaphore *sem, int count);
-extern void __down_write(struct rw_semaphore *sem, int count);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	count = atomic_dec_return(&sem->count);
-	if (count < 0) {
-		__down_read(sem, count);
-	}
-	mb();
-
-#if WAITQUEUE_DEBUG
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-	if (count) {
-		__down_write(sem, count);
-	}
-	mb();
-
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (sem->granted & 3)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant case is when
-   there was a writer waiting, and we've bumped the count to 0: we must
-   wake the writer up.  */
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-
-	mb();
-	if (atomic_inc_return(&sem->count) == 0)
-		__rwsem_wake(sem, 0);
-}
-
-/*
- * Releasing the writer is easy -- just release it and wake up any sleepers.
- */
-extern inline void up_write(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 3)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-
-	mb();
-	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-	if (count - RW_LOCK_BIAS < 0 && count >= 0) {
-		/* Only do the wake if we're no longer negative.  */
-		__rwsem_wake(sem, count);
-	}
 }
 
 #endif /* _ASM_SEMAPHORE_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/serial.h linux/include/asm-mips/serial.h
--- linux-2.4.6-pre8/include/asm-mips/serial.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/serial.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: serial.h,v 1.9 2000/02/16 01:45:55 ralf Exp $
- *
+/*
  * 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.
@@ -76,6 +75,81 @@
 #define JAZZ_SERIAL_PORT_DEFNS
 #endif
 
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#define ATLAS_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, ATLAS_BASE_BAUD, ATLAS_UART_REGS_BASE, ATLASINT_UART, STD_COM_FLAGS },     /* ttyS0 */
+#else
+#define ATLAS_SERIAL_PORT_DEFNS
+#endif
+
+/*
+ * Both Galileo boards have the same UART mappings.
+ */
+#if defined (CONFIG_MIPS_EV96100) || defined (CONFIG_MIPS_EV64120)
+#include <asm/galileo-boards/ev96100.h>
+#include <asm/galileo-boards/ev96100int.h>
+#define EV96100_SERIAL_PORT_DEFNS                                  \
+    { baud_base: EV96100_BASE_BAUD, port: EV96100_UART0_REGS_BASE, \
+      irq: EV96100INT_UART_0, flags: STD_COM_FLAGS, type: 0x3,   \
+      iomem_base: EV96100_UART0_REGS_BASE },                       \
+    { baud_base: EV96100_BASE_BAUD, port: EV96100_UART1_REGS_BASE, \
+      irq: EV96100INT_UART_0, flags: STD_COM_FLAGS, type: 0x3,   \
+      iomem_base: EV96100_UART1_REGS_BASE },
+#else
+#define EV96100_SERIAL_PORT_DEFNS
+#endif
+
+#ifdef CONFIG_MIPS_ITE8172
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/it8712.h>
+#define ITE_SERIAL_PORT_DEFNS                                  \
+    { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_UART_BASE), \
+      irq: IT8172_UART_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, \
+    { baud_base: (24000000/(16*13)), port: (IT8172_PCI_IO_BASE + IT8712_UART1_PORT), \
+      irq: IT8172_SERIRQ_4, flags: STD_COM_FLAGS, type: 0x3 }, \
+    /* Smart Card Reader 0 */ \
+    { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_SCR0_BASE), \
+      irq: IT8172_SCR0_IRQ, flags: STD_COM_FLAGS, type: 0x3 }, \
+    /* Smart Card Reader 1 */ \
+    { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
+      irq: IT8172_SCR1_IRQ, flags: STD_COM_FLAGS, type: 0x3 },
+#else
+#define ITE_SERIAL_PORT_DEFNS
+#endif
+
+#ifdef CONFIG_MIPS_IVR
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#define IVR_SERIAL_PORT_DEFNS                                  \
+    { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_UART_BASE), \
+      irq: IT8172_UART_IRQ, flags: STD_COM_FLAGS, type: 0x3 },         \
+    /* Smart Card Reader 1 */ \
+    { baud_base: BASE_BAUD, port: (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
+      irq: IT8172_SCR1_IRQ, flags: STD_COM_FLAGS, type: 0x3 },
+#else
+#define IVR_SERIAL_PORT_DEFNS
+#endif
+
+#ifdef CONFIG_AU1000_UART
+#include <asm/au1000.h>
+#define AU1000_SERIAL_PORT_DEFNS                              \
+    { baud_base: 0, port: UART0_ADDR, irq: AU1000_UART0_INT,  \
+      flags: STD_COM_FLAGS, type: 1 },                        \
+    { baud_base: 0, port: UART1_ADDR, irq: AU1000_UART1_INT,  \
+      flags: STD_COM_FLAGS, type: 1 },     \
+    { baud_base: 0, port: UART2_ADDR, irq: AU1000_UART2_INT,  \
+      flags: STD_COM_FLAGS, type: 1 },    \
+    { baud_base: 0, port: UART3_ADDR, irq: AU1000_UART3_INT,  \
+      flags: STD_COM_FLAGS, type: 1 },
+#else
+#define AU1000_SERIAL_PORT_DEFNS
+#endif
+
+#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
 #define STD_SERIAL_PORT_DEFNS			\
 	/* UART CLK   PORT IRQ     FLAGS        */			\
 	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
@@ -83,7 +157,6 @@
 	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
 	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
 
-
 #ifdef CONFIG_SERIAL_MANY_PORTS
 #define EXTRA_SERIAL_PORT_DEFNS			\
 	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
@@ -96,8 +169,8 @@
 	{ 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS },	/* ttyS11 */	\
 	{ 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS },	/* ttyS12 */	\
 	{ 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS },	/* ttyS13 */	\
-	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS14 (spare) */		\
-	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS15 (spare) */		\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },			/* ttyS14 (spare) */ \
+	{ 0, BASE_BAUD, 0x000, 0, 0 },			/* ttyS15 (spare) */ \
 	{ 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS },	/* ttyS16 */	\
 	{ 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS },	/* ttyS17 */	\
 	{ 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS },	/* ttyS18 */	\
@@ -114,9 +187,14 @@
 	{ 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS },	/* ttyS29 */	\
 	{ 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS },	/* ttyS30 */	\
 	{ 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS },	/* ttyS31 */
-#else
+#else /* CONFIG_SERIAL_MANY_PORTS */
 #define EXTRA_SERIAL_PORT_DEFNS
-#endif
+#endif /* CONFIG_SERIAL_MANY_PORTS */
+
+#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
+#define STD_SERIAL_PORT_DEFNS
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
 
 /* You can have up to four HUB6's in the system, but I've only
  * included two cards here for a total of twelve ports.
@@ -151,8 +229,44 @@
 #define MCA_SERIAL_PORT_DFNS
 #endif
 
+#ifdef CONFIG_MOMENCO_OCELOT
+/* Ordinary NS16552 duart with a 20MHz crystal.  */
+#define OCELOT_BASE_BAUD ( 20000000 / 16 )
+
+#define OCELOT_SERIAL1_IRQ	4
+#define OCELOT_SERIAL1_BASE	0xe0001020
+
+#define _OCELOT_SERIAL_INIT(int, base)					\
+	{ baud_base: OCELOT_BASE_BAUD, irq: int, flags: STD_COM_FLAGS,	\
+	  iomem_base: (u8 *) base, iomem_reg_shift: 2,			\
+	  io_type: SERIAL_IO_MEM }
+#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS				\
+	_OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE)
+#else
+#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
+#endif
+
+#ifdef CONFIG_DDB5477
+#define DDB5477_SERIAL_PORT_DEFNS                                       \
+        { baud_base: BASE_BAUD, irq: 12, flags: STD_COM_FLAGS,          \
+          iomem_base: (u8*)0xbfa04200, iomem_reg_shift: 3,              \
+          io_type: SERIAL_IO_MEM},\
+        { baud_base: BASE_BAUD, irq: 28, flags: STD_COM_FLAGS,          \
+          iomem_base: (u8*)0xbfa04240, iomem_reg_shift: 3,              \
+          io_type: SERIAL_IO_MEM},
+#else
+#define DDB5477_SERIAL_PORT_DEFNS
+#endif
+
 #define SERIAL_PORT_DFNS		\
+	IVR_SERIAL_PORT_DEFNS           \
+	ITE_SERIAL_PORT_DEFNS           \
+	ATLAS_SERIAL_PORT_DEFNS		\
+	EV96100_SERIAL_PORT_DEFNS	\
 	JAZZ_SERIAL_PORT_DEFNS		\
 	STD_SERIAL_PORT_DEFNS		\
 	EXTRA_SERIAL_PORT_DEFNS		\
-	HUB6_SERIAL_PORT_DFNS
+	HUB6_SERIAL_PORT_DFNS		\
+	MOMENCO_OCELOT_SERIAL_PORT_DEFNS\
+	AU1000_SERIAL_PORT_DEFNS	\
+	DDB5477_SERIAL_PORT_DEFNS
diff -urN linux-2.4.6-pre8/include/asm-mips/sgi/sgint23.h linux/include/asm-mips/sgi/sgint23.h
--- linux-2.4.6-pre8/include/asm-mips/sgi/sgint23.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/sgi/sgint23.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: sgint23.h,v 1.4 1999/09/28 21:02:12 ralf Exp $
- *
+/*
  * 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.
@@ -7,6 +6,7 @@
  * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 98, 1999, 2000 Ralf Baechle
  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - INT2 corrections
  */
 #ifndef _ASM_SGI_SGINT23_H
@@ -25,20 +25,8 @@
 #define SGINT_HPCDMA   41  /* INDY has 11 HPCDMA irq _sources_ */
 #define SGINT_END      52  /* End of 'spaces' */
 
-/* Individual interrupt definitions for the INDY and Indigo2
- */
-
-#define SGI_WD93_0_IRQ	SGINT_LOCAL0 + 1	/* 1st onboard WD93 */
-#define SGI_WD93_1_IRQ	SGINT_LOCAL0 + 2	/* 2nd onboard WD93 */
-#define SGI_ENET_IRQ	SGINT_LOCAL0 + 3	/* onboard ethernet */
-
-#define SGI_PANEL_IRQ	SGINT_LOCAL1 + 1	/* front panel */
-
-#define SGI_EISA_IRQ	SGINT_LOCAL2 + 3	/* EISA interrupts */
-#define SGI_KEYBOARD_IRQ	SGINT_LOCAL2 + 4	/* keyboard */
-#define SGI_SERIAL_IRQ	SGINT_LOCAL2 + 5	/* onboard serial */
-
-/* Individual interrupt definitions for the INDY and Indigo2
+/*
+ * Individual interrupt definitions for the INDY and Indigo2
  */
 
 #define SGI_WD93_0_IRQ	SGINT_LOCAL0 + 1	/* 1st onboard WD93 */
@@ -215,4 +203,4 @@
 extern void sgint_init(void);
 extern void indy_timer_init(void);
 
-#endif /* !(_ASM_SGINT23_H) */
+#endif /* _ASM_SGI_SGINT23_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h
--- linux-2.4.6-pre8/include/asm-mips/sgialib.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/sgialib.h	Mon Dec  3 22:50:39 2001
@@ -1,9 +1,8 @@
-/* $Id: sgialib.h,v 1.5 2000/03/19 01:28:58 ralf Exp $
+/*
  * sgialib.h: SGI ARCS firmware interface library for the Linux kernel.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
-
 #ifndef _ASM_SGIALIB_H
 #define _ASM_SGIALIB_H
 
@@ -21,7 +20,7 @@
  * Init the PROM library and it's internal data structures.  Called
  * at boot time from head.S before start_kernel is invoked.
  */
-extern int prom_init(int argc, char **argv, char **envp, int *prom_vec);
+extern void prom_init(int argc, char **argv, char **envp, int *prom_vec);
 
 /* Simple char-by-char console I/O. */
 extern void prom_putchar(char c);
@@ -30,28 +29,12 @@
 /* Generic printf() using ARCS console I/O. */
 extern void prom_printf(char *fmt, ...);
 
-/* Memory descriptor management. */
-#define PROM_MAX_PMEMBLOCKS    32
-struct prom_pmemblock {
-	unsigned long base; /* Within KSEG0. */
-	unsigned int size;  /* In bytes. */
-        unsigned int type;  /* free or prom memory */
-};
-
-/* Get next memory descriptor after CURR, returns first descriptor
- * in chain is CURR is NULL.
- */
-extern struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr);
 #define PROM_NULL_MDESC   ((struct linux_mdesc *) 0)
 
 /* Called by prom_init to setup the physical memory pmemblock
  * array.
  */
 extern void prom_meminit(void);
-extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
-
-/* Returns pointer to PROM physical memory block array. */
-extern struct prom_pmemblock *prom_getpblock_array(void);
 
 /* PROM device tree library routines. */
 #define PROM_NULL_COMPONENT ((pcomponent *) 0)
@@ -81,9 +64,9 @@
  */
 extern void prom_identify_arch(void);
 
-/* Environemt variable routines. */
+/* Environment variable routines. */
 extern PCHAR ArcGetEnvironmentVariable(CHAR *name);
-extern LONG SetEnvironmentVariable(PCHAR name, PCHAR value);
+extern LONG ArcSetEnvironmentVariable(PCHAR name, PCHAR value);
 
 /* ARCS command line acquisition and parsing. */
 extern char *prom_getcmdline(void);
@@ -115,7 +98,7 @@
 extern void prom_powerdown(void) __attribute__((noreturn));
 extern void prom_restart(void) __attribute__((noreturn));
 extern void prom_reboot(void) __attribute__((noreturn));
-extern void prom_imode(void) __attribute__((noreturn));
+extern void ArcEnterInteractiveMode(void) __attribute__((noreturn));
 extern long prom_cfgsave(void);
 extern struct linux_sysid *prom_getsysid(void);
 extern void prom_cacheflush(void);
diff -urN linux-2.4.6-pre8/include/asm-mips/shmbuf.h linux/include/asm-mips/shmbuf.h
--- linux-2.4.6-pre8/include/asm-mips/shmbuf.h	Thu Feb 24 22:52:30 2000
+++ linux/include/asm-mips/shmbuf.h	Mon Dec  3 22:50:39 2001
@@ -7,7 +7,7 @@
  * between kernel and user space.
  *
  * Pad space is left for:
- * - 2 miscellaneous 64-bit values
+ * - 2 miscellaneous 32-bit values
  */
 
 struct shmid64_ds {
diff -urN linux-2.4.6-pre8/include/asm-mips/smp.h linux/include/asm-mips/smp.h
--- linux-2.4.6-pre8/include/asm-mips/smp.h	Tue Oct 20 13:52:54 1998
+++ linux/include/asm-mips/smp.h	Mon Dec  3 22:50:39 2001
@@ -1,6 +1,37 @@
 #ifndef __ASM_MIPS_SMP_H
 #define __ASM_MIPS_SMP_H
 
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+
+#include <asm/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/current.h>
+
+
+/* Mappings are straight across.  If we want
+   to add support for disabling cpus and such,
+   we'll have to do what the mips64 port does here */
 #define cpu_logical_map(cpu)	(cpu)
+#define cpu_number_map(cpu)     (cpu)
+
+#define smp_processor_id()  (current->processor)
+
+
+/* I've no idea what the real meaning of this is */
+#define PROC_CHANGE_PENALTY	20
+
+#define NO_PROC_ID	(-1)
+
+struct smp_fn_call_struct {
+	spinlock_t lock;
+	atomic_t   finished;
+	void (*fn)(void *);
+	void *data;
+};
+
+extern struct smp_fn_call_struct smp_fn_call;
 
+#endif /* CONFIG_SMP */
 #endif /* __ASM_MIPS_SMP_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/sni.h linux/include/asm-mips/sni.h
--- linux-2.4.6-pre8/include/asm-mips/sni.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/sni.h	Mon Dec  3 22:50:39 2001
@@ -30,6 +30,14 @@
 #define PCIMT_ERRADDR		0xbfff0040
 #define PCIMT_SYNDROME		0xbfff0048
 #define PCIMT_ITPEND		0xbfff0050
+#define  IT_INT2		0x01
+#define  IT_INTD		0x02
+#define  IT_INTC		0x04
+#define  IT_INTB		0x08
+#define  IT_INTA		0x10
+#define  IT_EISA		0x20
+#define  IT_SCSI		0x40
+#define  IT_ETH			0x80
 #define PCIMT_IRQSEL		0xbfff0058
 #define PCIMT_TESTMEM		0xbfff0060
 #define PCIMT_ECCREG		0xbfff0068
@@ -73,16 +81,18 @@
  * to the other interrupts generated by ASIC PCI.
  */
 #define PCIMT_KEYBOARD_IRQ	 1
-#define PCIMT_IRQ_ETHERNET	16
-#define PCIMT_IRQ_TEMPERATURE	17
-#define PCIMT_IRQ_EISA_NMI	18
-#define PCIMT_IRQ_POWER_OFF	19
-#define PCIMT_IRQ_BUTTON	20
-#define PCIMT_IRQ_INTA		21
-#define PCIMT_IRQ_INTB		22
-#define PCIMT_IRQ_INTC		23
-#define PCIMT_IRQ_INTD		24
-#define PCIMT_IRQ_SCSI		25
+#define PCIMT_IRQ_INT2		16		/* What is that?  */
+#define PCIMT_IRQ_INTD		17
+#define PCIMT_IRQ_INTC		18
+#define PCIMT_IRQ_INTB		19
+#define PCIMT_IRQ_INTA		20
+#define PCIMT_IRQ_EISA		21
+#define PCIMT_IRQ_SCSI		22
+#define PCIMT_IRQ_ETHERNET	23
+#define PCIMT_IRQ_TEMPERATURE	24
+#define PCIMT_IRQ_EISA_NMI	25
+#define PCIMT_IRQ_POWER_OFF	26
+#define PCIMT_IRQ_BUTTON	27
 
 /*
  * Base address for the mapped 16mb EISA bus segment.
diff -urN linux-2.4.6-pre8/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- linux-2.4.6-pre8/include/asm-mips/socket.h	Mon Dec  3 22:50:28 2001
+++ linux/include/asm-mips/socket.h	Mon Dec  3 22:50:39 2001
@@ -33,7 +33,7 @@
 #define SO_RCVLOWAT	0x1004	/* receive low-water mark */
 #define SO_SNDTIMEO	0x1005	/* send timeout */
 #define SO_RCVTIMEO 	0x1006	/* receive timeout */
-#define SO_ACCEPTCONN	0x1007
+#define SO_ACCEPTCONN	0x1009
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -urN linux-2.4.6-pre8/include/asm-mips/spinlock.h linux/include/asm-mips/spinlock.h
--- linux-2.4.6-pre8/include/asm-mips/spinlock.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/spinlock.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: spinlock.h,v 1.8 2000/01/23 21:15:52 ralf Exp $
- *
+/*
  * 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.
@@ -22,6 +21,9 @@
 
 #define spin_lock_init(x)	do { (x)->lock = 0; } while(0);
 
+#define spin_is_locked(x)	((x)->lock != 0)
+#define spin_unlock_wait(x)	({ do { barrier(); } while ((x)->lock); })
+
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
@@ -29,9 +31,6 @@
  * We make no fairness assumptions.  They have a cost.
  */
 
-typedef struct { unsigned long a[100]; } __dummy_lock_t;
-#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
-
 static inline void spin_lock(spinlock_t *lock)
 {
 	unsigned int tmp;
@@ -45,8 +44,8 @@
 	"beqz\t%1, 1b\n\t"
 	" sync\n\t"
 	".set\treorder"
-	: "=o" (__dummy_lock(lock)), "=&r" (tmp)
-	: "o" (__dummy_lock(lock))
+	: "=o" (lock->lock), "=&r" (tmp)
+	: "o" (lock->lock)
 	: "memory");
 }
 
@@ -57,8 +56,8 @@
 	"sync\n\t"
 	"sw\t$0, %0\n\t"
 	".set\treorder"	
-	: "=o" (__dummy_lock(lock))
-	: "o" (__dummy_lock(lock))
+	: "=o" (lock->lock)
+	: "o" (lock->lock)
 	: "memory");
 }
 
@@ -92,8 +91,8 @@
 	"beqz\t%1, 1b\n\t"
 	" sync\n\t"
 	".set\treorder"	
-	: "=o" (__dummy_lock(rw)), "=&r" (tmp)
-	: "o" (__dummy_lock(rw))
+	: "=o" (rw->lock), "=&r" (tmp)
+	: "o" (rw->lock)
 	: "memory");
 }
 
@@ -111,8 +110,8 @@
 	"sc\t%1, %0\n\t"
 	"beqz\t%1, 1b\n\t"
 	".set\treorder"	
-	: "=o" (__dummy_lock(rw)), "=&r" (tmp)
-	: "o" (__dummy_lock(rw))
+	: "=o" (rw->lock), "=&r" (tmp)
+	: "o" (rw->lock)
 	: "memory");
 }
 
@@ -129,8 +128,8 @@
 	"beqz\t%1, 1b\n\t"
 	" sync\n\t"
 	".set\treorder"	
-	: "=o" (__dummy_lock(rw)), "=&r" (tmp)
-	: "o" (__dummy_lock(rw))
+	: "=o" (rw->lock), "=&r" (tmp)
+	: "o" (rw->lock)
 	: "memory");
 }
 
@@ -141,8 +140,8 @@
 	"sync\n\t"
 	"sw\t$0, %0\n\t"
 	".set\treorder"	
-	: "=o" (__dummy_lock(rw))
-	: "o" (__dummy_lock(rw))
+	: "=o" (rw->lock)
+	: "o" (rw->lock)
 	: "memory");
 }
 
diff -urN linux-2.4.6-pre8/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h
--- linux-2.4.6-pre8/include/asm-mips/stackframe.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/stackframe.h	Mon Dec  3 22:50:39 2001
@@ -1,13 +1,17 @@
 /*
- *  include/asm-mips/stackframe.h
+ * 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, 1995, 1996 by Ralf Baechle and Paul M. Antoine.
- *
- * $Id: stackframe.h,v 1.10 1999/08/13 17:07:27 harald Exp $
+ *  Copyright (C) 1994, 1995, 1996, 2001 Ralf Baechle
+ *  Copyright (C) 1994, 1995, 1996 Paul M. Antoine.
  */
-#ifndef __ASM_MIPS_STACKFRAME_H
-#define __ASM_MIPS_STACKFRAME_H
+#ifndef __ASM_STACKFRAME_H
+#define __ASM_STACKFRAME_H
 
+#include <asm/addrspace.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
 #include <asm/asm.h>
 #include <asm/offset.h>
 #include <linux/config.h>
@@ -47,20 +51,45 @@
 #define __str2(x) #x
 #define __str(x) __str2(x)
 
-#define save_static(frame)                               \
-	__asm__ __volatile__(                            \
-		"sw\t$16,"__str(PT_R16)"(%0)\n\t"        \
-		"sw\t$17,"__str(PT_R17)"(%0)\n\t"        \
-		"sw\t$18,"__str(PT_R18)"(%0)\n\t"        \
-		"sw\t$19,"__str(PT_R19)"(%0)\n\t"        \
-		"sw\t$20,"__str(PT_R20)"(%0)\n\t"        \
-		"sw\t$21,"__str(PT_R21)"(%0)\n\t"        \
-		"sw\t$22,"__str(PT_R22)"(%0)\n\t"        \
-		"sw\t$23,"__str(PT_R23)"(%0)\n\t"        \
-		"sw\t$30,"__str(PT_R30)"(%0)\n\t"        \
-		: /* No outputs */                       \
-		: "r" (frame))
+#define save_static_function(symbol)                                    \
+__asm__ (                                                               \
+        ".globl\t" #symbol "\n\t"                                       \
+        ".align\t2\n\t"                                                 \
+        ".type\t" #symbol ", @function\n\t"                             \
+        ".ent\t" #symbol ", 0\n"                                        \
+        #symbol":\n\t"                                                  \
+        ".frame\t$29, 0, $31\n\t"                                       \
+        "sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t"  \
+        "sw\t$17,"__str(PT_R17)"($29)\n\t"                              \
+        "sw\t$18,"__str(PT_R18)"($29)\n\t"                              \
+        "sw\t$19,"__str(PT_R19)"($29)\n\t"                              \
+        "sw\t$20,"__str(PT_R20)"($29)\n\t"                              \
+        "sw\t$21,"__str(PT_R21)"($29)\n\t"                              \
+        "sw\t$22,"__str(PT_R22)"($29)\n\t"                              \
+        "sw\t$23,"__str(PT_R23)"($29)\n\t"                              \
+        "sw\t$30,"__str(PT_R30)"($29)\n\t"                              \
+        ".end\t" #symbol "\n\t"                                         \
+        ".size\t" #symbol",. - " #symbol)
+
+/* Used in declaration of save_static functions.  */
+#define static_unused static __attribute__((unused))
+
+
+#ifdef CONFIG_SMP
+#  define GET_SAVED_SP                                   \
+                mfc0    k0, CP0_CONTEXT;                 \
+                lui     k1, %hi(kernelsp);               \
+                srl     k0, k0, 23;                      \
+		sll     k0, k0, 2;                       \
+                addu    k1, k0;                          \
+                lw      k1, %lo(kernelsp)(k1);        
 
+#else
+#  define GET_SAVED_SP                                   \
+		lui	k1, %hi(kernelsp);               \
+		lw	k1, %lo(kernelsp)(k1);           
+#endif
+ 
 #define SAVE_SOME                                        \
 		.set	push;                            \
 		.set	reorder;                         \
@@ -71,13 +100,12 @@
 		 move	k1, sp;                          \
 		.set	reorder;                         \
 		/* Called from user mode, new stack. */  \
-		lui	k1, %hi(kernelsp);               \
-		lw	k1, %lo(kernelsp)(k1);           \
+                GET_SAVED_SP                             \
 8:                                                       \
 		move	k0, sp;                          \
 		subu	sp, k1, PT_SIZE;                 \
 		sw	k0, PT_R29(sp);                  \
-		sw	$3, PT_R3(sp);                   \
+                sw	$3, PT_R3(sp);                   \
 		sw	$0, PT_R0(sp);			 \
 		mfc0	v1, CP0_STATUS;                  \
 		sw	$2, PT_R2(sp);                   \
@@ -208,6 +236,16 @@
 
 #endif
 
+#define RESTORE_SP                                       \
+		lw	sp,  PT_R29(sp);                 \
+
+#define RESTORE_ALL                                      \
+		RESTORE_SOME;                            \
+		RESTORE_AT;                              \
+		RESTORE_TEMP;                            \
+		RESTORE_STATIC;                          \
+		RESTORE_SP
+
 #define RESTORE_ALL_AND_RET                              \
 		RESTORE_SOME;                            \
 		RESTORE_AT;                              \
@@ -215,6 +253,7 @@
 		RESTORE_STATIC;                          \
 		RESTORE_SP_AND_RET
 
+
 /*
  * Move to kernel mode and disable interrupts.
  * Set cp0 enable bit as sign that we're running on the kernel stack
@@ -248,4 +287,4 @@
 		xori	t0,0x1e;                        \
 		mtc0	t0,CP0_STATUS
 
-#endif /* __ASM_MIPS_STACKFRAME_H */
+#endif /* __ASM_STACKFRAME_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/stat.h linux/include/asm-mips/stat.h
--- linux-2.4.6-pre8/include/asm-mips/stat.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/stat.h	Mon Dec  3 22:50:39 2001
@@ -17,8 +17,7 @@
 	unsigned int	st_ctime, st_res3;
 	unsigned int	st_blksize;
 	int		st_blocks;
-	unsigned int	st_flags;
-	unsigned int	st_gen;
+	unsigned int	st_unused0[2];
 };
 
 struct stat {
@@ -45,11 +44,7 @@
 	long		reserved2;
 	long		st_blksize;
 	long		st_blocks;
-	char		st_fstype[16];	/* Filesystem type name */
-	long		st_pad4[8];
-	/* Linux specific fields */
-	unsigned int	st_flags;
-	unsigned int	st_gen;
+	long		st_pad4[14];
 };
 
 /*
@@ -61,25 +56,36 @@
 struct stat64 {
 	unsigned long	st_dev;
 	unsigned long	st_pad0[3];	/* Reserved for st_dev expansion  */
-	ino_t		st_ino;
+
+	unsigned long long	st_ino;
+
 	mode_t		st_mode;
 	nlink_t		st_nlink;
+
 	uid_t		st_uid;
 	gid_t		st_gid;
+
 	unsigned long	st_rdev;
 	unsigned long	st_pad1[3];	/* Reserved for st_rdev expansion  */
+
 	long long	st_size;
+
 	/*
 	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
 	 * but we don't have it under Linux.
 	 */
 	time_t		st_atime;
 	unsigned long	reserved0;	/* Reserved for st_atime expansion  */
+
 	time_t		st_mtime;
-	unsigned long	reserved1;	/* Reserved for st_atime expansion  */
+	unsigned long	reserved1;	/* Reserved for st_mtime expansion  */
+
 	time_t		st_ctime;
-	unsigned long	reserved2;	/* Reserved for st_atime expansion  */
+	unsigned long	reserved2;	/* Reserved for st_ctime expansion  */
+
 	unsigned long	st_blksize;
+	unsigned long	st_pad2;
+
 	long long	st_blocks;
 };
 
diff -urN linux-2.4.6-pre8/include/asm-mips/system.h linux/include/asm-mips/system.h
--- linux-2.4.6-pre8/include/asm-mips/system.h	Thu Aug  3 15:38:11 2000
+++ linux/include/asm-mips/system.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,4 @@
-/* $Id: system.h,v 1.20 1999/12/06 23:13:21 ralf Exp $
- *
+/*
  * 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.
@@ -7,6 +6,12 @@
  * Copyright (C) 1994 - 1999 by Ralf Baechle
  * Copyright (C) 1996 by Paul M. Antoine
  * Copyright (C) 1994 - 1999 by Ralf Baechle
+ *
+ * Changed set_except_vector declaration to allow return of previous
+ * vector address value - necessary for "borrowing" vectors. 
+ *
+ * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
  */
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
@@ -61,65 +66,76 @@
 		: "$1", "memory");
 }
 
-#define __save_flags(x)                  \
-__asm__ __volatile__(                    \
-	".set\tpush\n\t"		 \
-	".set\treorder\n\t"              \
-	"mfc0\t%0,$12\n\t"               \
-	".set\tpop\n\t"                      \
-	: "=r" (x)                       \
-	: /* no inputs */                \
-	: "memory")
-
-#define __save_and_cli(x)                \
-__asm__ __volatile__(                    \
-	".set\tpush\n\t"		 \
-	".set\treorder\n\t"              \
-	".set\tnoat\n\t"                 \
-	"mfc0\t%0,$12\n\t"               \
-	"ori\t$1,%0,1\n\t"               \
-	"xori\t$1,1\n\t"                 \
-	".set\tnoreorder\n\t"		 \
-	"mtc0\t$1,$12\n\t"               \
-	"nop\n\t"                        \
-	"nop\n\t"                        \
-	"nop\n\t"                        \
-	".set\tpop\n\t"                  \
-	: "=r" (x)                       \
-	: /* no inputs */                \
+#define __save_flags(x)							\
+__asm__ __volatile__(							\
+	".set\tpush\n\t"						\
+	".set\treorder\n\t"						\
+	"mfc0\t%0,$12\n\t"						\
+	".set\tpop\n\t"							\
+	: "=r" (x))
+
+#define __save_and_cli(x)						\
+__asm__ __volatile__(							\
+	".set\tpush\n\t"						\
+	".set\treorder\n\t"						\
+	".set\tnoat\n\t"						\
+	"mfc0\t%0,$12\n\t"						\
+	"ori\t$1,%0,1\n\t"						\
+	"xori\t$1,1\n\t"						\
+	".set\tnoreorder\n\t"						\
+	"mtc0\t$1,$12\n\t"						\
+	"nop\n\t"							\
+	"nop\n\t"							\
+	"nop\n\t"							\
+	".set\tpop\n\t"							\
+	: "=r" (x)							\
+	: /* no inputs */						\
 	: "$1", "memory")
 
-extern void __inline__
-__restore_flags(int flags)
-{
-	__asm__ __volatile__(
-		".set\tpush\n\t"
-		".set\treorder\n\t"
-		"mfc0\t$8,$12\n\t"
-		"li\t$9,0xff00\n\t"
-		"and\t$8,$9\n\t"
-		"nor\t$9,$0,$9\n\t"
-		"and\t%0,$9\n\t"
-		"or\t%0,$8\n\t"
-		".set\tnoreorder\n\t"
-		"mtc0\t%0,$12\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		".set\tpop\n\t"
-		:
-		: "r" (flags)
-		: "$8", "$9", "memory");
-}
+#define __restore_flags(flags)						\
+do {									\
+	unsigned long __tmp1;						\
+									\
+	__asm__ __volatile__(						\
+		".set\tnoreorder\t\t\t# __restore_flags\n\t"		\
+		".set\tnoat\n\t"					\
+		"mfc0\t$1, $12\n\t"					\
+		"andi\t%0, 1\n\t"					\
+		"ori\t$1, 1\n\t"					\
+		"xori\t$1, 1\n\t"					\
+		"or\t%0, $1\n\t"					\
+		"mtc0\t%0, $12\n\t"					\
+		"nop\n\t"						\
+		"nop\n\t"						\
+		"nop\n\t"						\
+		".set\tat\n\t"						\
+		".set\treorder"						\
+		: "=r" (__tmp1)						\
+		: "0" (flags)						\
+		: "$1", "memory");					\
+} while(0)
 
-/*
- * Non-SMP versions ...
- */
-#define sti() __sti()
-#define cli() __cli()
-#define save_flags(x) __save_flags(x)
-#define save_and_cli(x) __save_and_cli(x)
-#define restore_flags(x) __restore_flags(x)
+#ifdef CONFIG_SMP
+
+extern void __global_sti(void);
+extern void __global_cli(void);
+extern unsigned long __global_save_flags(void);
+extern void __global_restore_flags(unsigned long);
+#  define sti() __global_sti()
+#  define cli() __global_cli() 
+#  define save_flags(x) do { x = __global_save_flags(); } while (0)
+#  define restore_flags(x) __global_restore_flags(x)
+#  define save_and_cli(x) do { save_flags(x); cli(); } while(0)
+
+#else /* Single processor */
+
+#  define sti() __sti()
+#  define cli() __cli()
+#  define save_flags(x) __save_flags(x)
+#  define save_and_cli(x) __save_and_cli(x)
+#  define restore_flags(x) __restore_flags(x)
+
+#endif /* SMP */
 
 /* For spinlocks etc */
 #define local_irq_save(x)	__save_and_cli(x);
@@ -131,11 +147,14 @@
  * These are probably defined overly paranoid ...
  */
 #ifdef CONFIG_CPU_HAS_WB
+
 #include <asm/wbflush.h>
-#define rmb()
-#define wmb() wbflush()
-#define mb() wbflush()
-#else
+#define rmb()	do { } while(0)
+#define wmb()	wbflush()
+#define mb()	wbflush()
+
+#else /* CONFIG_CPU_HAS_WB  */
+
 #define mb()						\
 __asm__ __volatile__(					\
 	"# prevent instructions being moved around\n\t"	\
@@ -148,6 +167,17 @@
 	: "memory")
 #define rmb() mb()
 #define wmb() mb()
+
+#endif /* CONFIG_CPU_HAS_WB  */
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#define smp_rmb()	rmb()
+#define smp_wmb()	wmb()
+#else
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
 #endif
 
 #define set_mb(var, value) \
@@ -180,17 +210,17 @@
 	unsigned long dummy;
 
 	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
+		".set\tnoreorder\t\t\t# xchg_u32\n\t"
 		".set\tnoat\n\t"
-		"ll\t%0,(%1)\n"
-		"1:\tmove\t$1,%2\n\t"
-		"sc\t$1,(%1)\n\t"
-		"beqzl\t$1,1b\n\t"
-		"ll\t%0,(%1)\n\t"
+		"ll\t%0, %3\n"
+		"1:\tmove\t$1, %2\n\t"
+		"sc\t$1, %1\n\t"
+		"beqzl\t$1, 1b\n\t"
+		" ll\t%0, %3\n\t"
 		".set\tat\n\t"
 		".set\treorder"
-		: "=r" (val), "=r" (m), "=r" (dummy)
-		: "1" (m), "2" (val)
+		: "=r" (val), "=o" (*m), "=r" (dummy)
+		: "o" (*m), "2" (val)
 		: "memory");
 
 	return val;
@@ -207,64 +237,25 @@
 #endif /* Processor-dependent optimization */
 }
 
-/*
- * Only used for 64 bit kernel.
- */
-extern __inline__ unsigned long xchg_u64(volatile long * m, unsigned long val)
-{
-	unsigned long dummy;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		".set\tnoat\n\t"
-		"lld\t%0,(%1)\n"
-		"1:\tmove\t$1,%2\n\t"
-		"scd\t$1,(%1)\n\t"
-		"beqzl\t$1,1b\n\t"
-		"lld\t%0,(%1)\n\t"
-		".set\tat\n\t"
-		".set\treorder"
-		: "=r" (val), "=r" (m), "=r" (dummy)
-		: "1" (m), "2" (val)
-		: "memory");
-
-	return val;
-}
-
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 #define tas(ptr) (xchg((ptr),1))
 
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid xchg().
- *
- * This only works if the compiler isn't horribly bad at optimizing.
- * gcc-2.5.8 reportedly can't handle this, but I define that one to
- * be dead anyway.
- */
-extern void __xchg_called_with_bad_pointer(void);
-
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+static __inline__ unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
 {
 	switch (size) {
 		case 4:
 			return xchg_u32(ptr, x);
-#if defined(__mips64)
-		case 8:
-			return xchg_u64(ptr, x);
-#endif
 	}
-	__xchg_called_with_bad_pointer();
 	return x;
 }
 
-extern void set_except_vector(int n, void *addr);
+extern void *set_except_vector(int n, void *addr);
 
 extern void __die(const char *, struct pt_regs *, const char *where,
 	unsigned long line) __attribute__((noreturn));
 extern void __die_if_kernel(const char *, struct pt_regs *, const char *where,
 	unsigned long line);
-extern int abs(int);
 
 #define die(msg, regs)							\
 	__die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__)
diff -urN linux-2.4.6-pre8/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- linux-2.4.6-pre8/include/asm-mips/termios.h	Mon Dec  3 22:50:28 2001
+++ linux/include/asm-mips/termios.h	Mon Dec  3 22:50:39 2001
@@ -1,10 +1,9 @@
-/* $Id: termios.h,v 1.8 2000/01/27 23:45:30 ralf Exp $
- *
+/*
  * 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) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 2001 by Ralf Baechle
  */
 #ifndef _ASM_TERMIOS_H
 #define _ASM_TERMIOS_H
diff -urN linux-2.4.6-pre8/include/asm-mips/time.h linux/include/asm-mips/time.h
--- linux-2.4.6-pre8/include/asm-mips/time.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/time.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,66 @@
+/***********************************************************************
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * include/asm-mips/time.h
+ *     header file for the new style time.c file and time services.
+ *
+ * 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.
+ ***********************************************************************
+ */
+
+#ifndef _ASM_TIME_H
+#define _ASM_TIME_H
+
+#include <linux/ptrace.h>               /* for struct pt_regs */
+#include <linux/linkage.h>              /* for asmlinkage */
+
+/* 
+ * RTC ops.  By default, they point a no-RTC functions.
+ *	rtc_get_time - mktime(year, mon, day, hour, min, sec) in seconds.
+ *	rtc_set_time - reverse the above translation
+ */
+extern unsigned long (*rtc_get_time)(void);
+extern int (*rtc_set_time)(unsigned long);
+
+/*
+ * do_gettimeoffset(). By default, this func pointer points to 
+ * do_null_gettimeoffset(), which leads to the same resolution as HZ.
+ * Higher resolution versions are vailable.
+ */
+extern unsigned long (*do_gettimeoffset)(void);
+
+extern unsigned long null_gettimeoffset(void);
+extern unsigned long fixed_rate_gettimeoffset(void);
+extern unsigned long calibrate_div32_gettimeoffset(void);
+extern unsigned long calibrate_div64_gettimeoffset(void);
+
+/*
+ * high-level timer interrupt routines.
+ */
+extern void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+/*
+ * the corresponding low-level timer interrupt routine.
+ */
+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs);
+
+/*
+ * board specific routines required by time_init().
+ * board_time_init is defaulted to NULL and can remains so.
+ * board_timer_setup must be setup properly in machine setup routine.
+ */
+struct irqaction;
+extern void (*board_time_init)(void);
+extern void (*board_timer_setup)(struct irqaction *irq);
+
+/*
+ * mips_counter_frequency - must be set if you intend to use
+ * counter as timer interrupt source or use fixed_rate_gettimeoffset.
+ */
+extern unsigned int mips_counter_frequency;
+
+#endif /* _ASM_TIME_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/tlb.h linux/include/asm-mips/tlb.h
--- linux-2.4.6-pre8/include/asm-mips/tlb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/tlb.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1 @@
+#include <asm-generic/tlb.h>
diff -urN linux-2.4.6-pre8/include/asm-mips/tx3912.h linux/include/asm-mips/tx3912.h
--- linux-2.4.6-pre8/include/asm-mips/tx3912.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/tx3912.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,576 @@
+/*
+ *  linux/include/asm-mips/tx3912.h
+ *
+ *  Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
+ *
+ * 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.
+ *
+ *  Register includes for TMPR3912/05 and PR31700 processors
+ */
+#ifndef __TX3912_H__
+#define __TX3912_H__
+
+#include <asm/addrspace.h>
+
+#define inb(addr)	(*(volatile unsigned char *)(addr))
+#define inw(addr)	(*(volatile unsigned short *)(addr))
+#define inl(addr)	(*(volatile unsigned int *)(addr))
+#define outb(b,addr)	(*(volatile unsigned char *)(addr)) = (b)
+#define outw(b,addr)	(*(volatile unsigned short *)(addr)) = (b)
+#define outl(b,addr)	(*(volatile unsigned int *)(addr)) = (b)
+
+ 
+/******************************************************************************
+*
+* 	01  General macro definitions
+*
+******************************************************************************/
+
+#define REGISTER_BASE   0xb0c00000
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+	#define REG_AT(x)	(*((volatile unsigned long *)(REGISTER_BASE + x)))
+
+#else
+
+	#define REG_AT(x)   (REGISTER_BASE + x)
+
+#endif
+
+#define BIT(x)	(1 << x)
+
+/******************************************************************************
+*
+* 	02  Bus Interface Unit
+*
+******************************************************************************/
+
+#define MemConfig0    REG_AT(0x000)
+#define MemConfig1    REG_AT(0x004)
+#define MemConfig2    REG_AT(0x008)
+#define MemConfig3    REG_AT(0x00c)
+#define MemConfig4    REG_AT(0x010)
+#define MemConfig5    REG_AT(0x014)
+#define MemConfig6    REG_AT(0x018)
+#define MemConfig7    REG_AT(0x01c)
+#define MemConfig8    REG_AT(0x020)
+
+/* Memory config register 1 */
+#define MEM1_ENCS1USER	BIT(21)
+
+/* Memory config register 3 */
+#define MEM3_CARD1ACCVAL_MASK	(BIT(24) | BIT(25) | BIT(26) | BIT(27))
+#define MEM3_CARD1IOEN		BIT(4)
+
+/* Memory config register 4 */
+#define MEM4_ARBITRATIONEN	BIT(29)
+#define MEM4_MEMPOWERDOWN	BIT(16)
+#define MEM4_ENREFRESH1		BIT(15)
+#define MEM4_ENREFRESH0		BIT(14)
+#define MEM4_ENWATCH            BIT(24)
+#define MEM4_WATCHTIMEVAL_MASK  (0xf)
+#define MEM4_WATCHTIMEVAL_SHIFT (20)
+#define MEM4_WATCHTIME_VALUE    (0xf)
+
+/*
+ ***********************************************************************
+ *								       *
+ * 06  Clock Module						       *
+ *								       *
+ ***********************************************************************
+ */
+#define TX3912_CLK_CTRL_BASE			(REGISTER_BASE + 0x1c0)
+
+#define TX3912_CLK_CTRL_CHICLKDIV_MASK		0xff000000
+#define TX3912_CLK_CTRL_CHICLKDIV_SHIFT		24
+#define TX3912_CLK_CTRL_ENCLKTEST		0x00800000
+#define TX3912_CLK_CTRL_CLKTESTSELSIB		0x00400000
+#define TX3912_CLK_CTRL_CHIMCLKSEL		0x00200000
+#define TX3912_CLK_CTRL_CHICLKDIR		0x00100000
+#define TX3912_CLK_CTRL_ENCHIMCLK		0x00080000
+#define TX3912_CLK_CTRL_ENVIDCLK		0x00040000
+#define TX3912_CLK_CTRL_ENMBUSCLK		0x00020000
+#define TX3912_CLK_CTRL_ENSPICLK		0x00010000
+#define TX3912_CLK_CTRL_ENTIMERCLK		0x00008000
+#define TX3912_CLK_CTRL_ENFASTTIMERCLK		0x00004000
+#define TX3912_CLK_CTRL_SIBMCLKDIR		0x00002000
+#define TX3912_CLK_CTRL_RESERVED		0x00001000
+#define TX3912_CLK_CTRL_ENSIBMCLK		0x00000800
+#define TX3912_CLK_CTRL_SIBMCLKDIV_MASK		0x00000700
+#define TX3912_CLK_CTRL_SIBMCLKDIV_SHIFT	8
+#define TX3912_CLK_CTRL_CSERSEL			0x00000080
+#define TX3912_CLK_CTRL_CSERDIV_MASK		0x00000070
+#define TX3912_CLK_CTRL_CSERDIV_SHIFT		4
+#define TX3912_CLK_CTRL_ENCSERCLK		0x00000008
+#define TX3912_CLK_CTRL_ENIRCLK			0x00000004
+#define TX3912_CLK_CTRL_ENUARTACLK		0x00000002
+#define TX3912_CLK_CTRL_ENUARTBCLK		0x00000001
+
+
+
+
+/******************************************************************************
+*
+* 	07  CHI module
+*
+******************************************************************************/
+
+#define CHIControl		REG_AT(0x1D8)
+#define CHIPointerEnable	REG_AT(0x1DC)
+#define CHIReceivePtrA		REG_AT(0x1E0)
+#define CHIReceivePtrB		REG_AT(0x1E4)
+#define CHITransmitPtrA		REG_AT(0x1E8)
+#define CHITransmitPtrB		REG_AT(0x1EC)
+#define CHISize			REG_AT(0x1F0)
+#define CHIReceiveStart		REG_AT(0x1F4)
+#define CHITransmitStart	REG_AT(0x1F8)
+#define CHIHoldingReg		REG_AT(0x1FC)
+
+/* CHI Control Register */
+/* <incomplete!> */
+#define	CHI_RXEN		BIT(2)
+#define	CHI_TXEN		BIT(1)
+#define	CHI_ENCHI		BIT(0)
+
+/******************************************************************************
+*
+*	08  Interrupt module
+*
+******************************************************************************/
+
+/* Register locations */
+
+#define IntStatus1    REG_AT(0x100)
+#define IntStatus2    REG_AT(0x104)
+#define IntStatus3    REG_AT(0x108)
+#define IntStatus4    REG_AT(0x10c)
+#define IntStatus5    REG_AT(0x110)
+#define IntStatus6    REG_AT(0x114)
+
+#define IntClear1     REG_AT(0x100)
+#define IntClear2     REG_AT(0x104)
+#define IntClear3     REG_AT(0x108)
+#define IntClear4     REG_AT(0x10c)
+#define IntClear5     REG_AT(0x110)
+#define IntClear6     REG_AT(0x114)
+
+#define IntEnable1    REG_AT(0x118)
+#define IntEnable2    REG_AT(0x11c)
+#define IntEnable3    REG_AT(0x120)
+#define IntEnable4    REG_AT(0x124)
+#define IntEnable5    REG_AT(0x128)
+#define IntEnable6    REG_AT(0x12c)
+
+/* Interrupt Status Register 1 at offset 100 */
+#define INT1_LCDINT		BIT(31)
+#define INT1_DFINT              BIT(30)
+#define INT1_CHIDMAHALF		BIT(29)
+#define INT1_CHIDMAFULL		BIT(28)
+#define INT1_CHIDMACNTINT       BIT(27)
+#define INT1_CHIRXAINT		BIT(26)
+#define INT1_CHIRXBINT		BIT(25)
+#define INT1_CHIACTINT          BIT(24)
+#define INT1_CHIERRINT          BIT(23)
+#define INT1_SND0_5INT          BIT(22)
+#define INT1_SND1_0INT		BIT(21)
+#define INT1_TEL0_5INT          BIT(20)
+#define INT1_TEL1_0INT          BIT(19)
+#define INT1_SNDDMACNTINT       BIT(18)
+#define INT1_TELDMACNTINT       BIT(17)
+#define INT1_LSNDCLIPINT        BIT(16)
+#define INT1_RSNDCLIPINT        BIT(15)
+#define INT1_VALSNDPOSINT       BIT(14)
+#define INT1_VALSNDNEGINT       BIT(13)
+#define INT1_VALTELPOSINT       BIT(12)
+#define INT1_VALTELNEGINT       BIT(11)
+#define INT1_SNDININT           BIT(10)
+#define INT1_TELININT           BIT(9)
+#define INT1_SIBSF0INT          BIT(8)
+#define INT1_SIBSF1INT          BIT(7)
+#define INT1_SIBIRQPOSINT       BIT(6)
+#define INT1_SIBIRQNEGINT       BIT(5)
+
+/* Interrupt Status Register 2 at offset 104 */
+#define INT2_UARTARXINT		BIT(31)
+#define INT2_UARTARXOVERRUN	BIT(30)
+#define INT2_UARTAFRAMEINT	BIT(29)
+#define INT2_UARTABREAKINT	BIT(28)
+#define INT2_UARTATXINT		BIT(26)
+#define INT2_UARTATXOVERRUN	BIT(25)
+#define INT2_UARTAEMPTY		BIT(24)
+
+#define INT2_UARTBRXINT		BIT(21)
+#define INT2_UARTBRXOVERRUN	BIT(20)
+#define INT2_UARTBFRAMEINT	BIT(29)
+#define INT2_UARTBBREAKINT	BIT(18)
+#define INT2_UARTBTXINT		BIT(16)
+#define INT2_UARTBTXOVERRUN	BIT(15)
+#define INT2_UARTBEMPTY		BIT(14)
+
+#define INT2_UARTA_RX		(BIT(31) | BIT(30) | BIT(29) | BIT(28) | BIT(27))
+#define INT2_UARTA_TX		(BIT(26) | BIT(25) | BIT(24))
+#define INT2_UARTA_DMA		(BIT(23) | BIT(22))
+
+#define INT2_UARTB_RX		(BIT(21) | BIT(20) | BIT(19) | BIT(18) | BIT(17))
+#define INT2_UARTB_TX		(BIT(16) | BIT(15) | BIT(14))
+#define INT2_UARTB_DMA		(BIT(13) | BIT(12))
+
+/* Interrupt Status Register 5 */
+#define INT5_RTCINT	 BIT(31)
+#define INT5_ALARMINT	 BIT(30)
+#define INT5_PERIODICINT BIT(29)
+#define INT5_POSPWRINT 	 BIT(27)
+#define INT5_NEGPWRINT	 BIT(26)
+#define INT5_POSPWROKINT BIT(25)
+#define INT5_NEGPWROKINT BIT(24)
+#define INT5_POSONBUTINT BIT(23)
+#define INT5_NEGONBUTINT BIT(22)
+#define INT5_SPIAVAILINT BIT(21)        /* 0x0020 0000 */
+#define INT5_SPIERRINT   BIT(20)        /* 0x0010 0000 */
+#define INT5_SPIRCVINT	 BIT(19)	/* 0x0008 0000 */
+#define INT5_SPIEMPTYINT BIT(18)	/* 0x0004 0000 */
+#define INT5_IOPOSINT6	 BIT(13)
+#define INT5_IOPOSINT5	 BIT(12)
+#define INT5_IOPOSINT4	 BIT(11)
+#define INT5_IOPOSINT3	 BIT(10)
+#define INT5_IOPOSINT2	 BIT(9)
+#define INT5_IOPOSINT1	 BIT(8)
+#define INT5_IOPOSINT0	 BIT(7)
+#define INT5_IONEGINT6	 BIT(6)
+#define INT5_IONEGINT5	 BIT(5)
+#define INT5_IONEGINT4	 BIT(4)
+#define INT5_IONEGINT3	 BIT(3)
+#define INT5_IONEGINT2	 BIT(2)
+#define INT5_IONEGINT1	 BIT(1)
+#define INT5_IONEGINT0	 BIT(0)
+
+#define INT5_IONEGINT_SHIFT 0
+#define	INT5_IONEGINT_MASK  (0x7F<<INT5_IONEGINT_SHIFT)
+#define INT5_IOPOSINT_SHIFT 7
+#define	INT5_IOPOSINT_MASK  (0x7F<<INT5_IOPOSINT_SHIFT)
+
+/* Interrupt Status Register 6 */
+#define INT6_IRQHIGH	BIT(31)
+#define INT6_IRQLOW	BIT(30)
+#define INT6_INTVECT	(BIT(5) | BIT(4) | BIT(3) | BIT(2))
+
+
+/* Interrupt Enable Register 6 */
+#define INT6_GLOBALEN		BIT(18)
+#define INT6_PWROKINT		BIT(15)
+#define	INT6_ALARMINT		BIT(14)
+#define INT6_PERIODICINT 	BIT(13)
+#define	INT6_MBUSINT		BIT(12)
+#define INT6_UARTARXINT		BIT(11)
+#define INT6_UARTBRXINT		BIT(10)
+#define	INT6_MFIOPOSINT1619	BIT(9)
+#define INT6_IOPOSINT56         BIT(8)
+#define	INT6_MFIONEGINT1619	BIT(7)
+#define INT6_IONEGINT56         BIT(6)
+#define	INT6_MBUSDMAFULLINT	BIT(5)
+#define	INT6_SNDDMACNTINT	BIT(4)
+#define	INT6_TELDMACNTINT	BIT(3)
+#define	INT6_CHIDMACNTINT	BIT(2)
+#define INT6_IOPOSNEGINT0       BIT(1)
+
+/******************************************************************************
+*
+*	09  GPIO and MFIO modules
+*
+******************************************************************************/
+
+#define IOControl   	REG_AT(0x180)
+#define MFIOOutput   	REG_AT(0x184)
+#define MFIODirection  	REG_AT(0x188)
+#define MFIOInput  	REG_AT(0x18c)
+#define MFIOSelect   	REG_AT(0x190)
+#define IOPowerDown   	REG_AT(0x194)
+#define MFIOPowerDown  	REG_AT(0x198)
+
+#define IODIN_MASK      0x0000007f
+#define IODIN_SHIFT     0
+#define IODOUT_MASK     0x00007f00
+#define IODOUT_SHIFT    8
+#define IODIREC_MASK    0x007f0000
+#define IODIREC_SHIFT   16
+#define IODEBSEL_MASK   0x7f000000
+#define IODEBSEL_SHIFT  24
+
+/******************************************************************************
+*
+*	10  IR module
+*
+******************************************************************************/
+
+#define IRControl1                  REG_AT(0x0a0)
+#define IRControl2                  REG_AT(0x0a4)
+
+/* IR Control 1 Register */
+#define IR_CARDRET                  BIT(24)
+#define IR_BAUDVAL_MASK             0x00ff0000
+#define IR_BAUDVAL_SHIFT            16
+#define IR_TESTIR                   BIT(4)
+#define IR_DTINVERT                 BIT(3)
+#define IR_RXPWR                    BIT(2)
+#define IR_ENSTATE                  BIT(1)
+#define IR_ENCONSM                  BIT(0)
+
+/* IR Control 2 Register */
+#define IR_PER_MASK                 0xff000000
+#define IR_PER_SHIFT                24
+#define IR_ONTIME_MASK              0x00ff0000
+#define IR_ONTIME_SHIFT             16
+#define IR_DELAYVAL_MASK            0x0000ff00
+#define IR_DELAYVAL_SHIFT           8
+#define IR_WAITVAL_MASK             0x000000ff
+#define IR_WAITVAL_SHIFT            0
+
+/******************************************************************************
+*
+*	11  Magicbus Module
+*
+******************************************************************************/
+
+#define MbusCntrl1		REG_AT(0x0e0)
+#define MbusCntrl2		REG_AT(0x0e4)
+#define MbusDMACntrl1		REG_AT(0x0e8)
+#define MbusDMACntrl2		REG_AT(0x0ec)
+#define MbusDMACount		REG_AT(0x0f0)
+#define MbusTxReg		REG_AT(0x0f4)
+#define MbusRxReg		REG_AT(0x0f8)
+
+#define	MBUS_CLKPOL		BIT(4)
+#define	MBUS_SLAVE		BIT(3)
+#define	MBUS_FSLAVE		BIT(2)
+#define	MBUS_LONG		BIT(1)
+#define	MBUS_ENMBUS		BIT(0)
+
+/******************************************************************************
+*
+*	12  Power module
+*
+******************************************************************************/
+
+#define PowerControl   	            REG_AT(0x1C4)
+
+#define PWR_ONBUTN                  BIT(31)
+#define PWR_PWRINT                  BIT(30)
+#define PWR_PWROK                   BIT(29)
+#define PWR_VIDRF_MASK              (BIT(28) | BIT(27))
+#define PWR_VIDRF_SHIFT             27
+#define PWR_SLOWBUS                 BIT(26)
+#define PWR_DIVMOD                  BIT(25)
+#define PWR_STPTIMERVAL_MASK        (BIT(15) | BIT(14) | BIT(13) | BIT(12))
+#define PWR_STPTIMERVAL_SHIFT       12
+#define PWR_ENSTPTIMER              BIT(11)
+#define PWR_ENFORCESHUTDWN          BIT(10)
+#define PWR_FORCESHUTDWN            BIT(9)
+#define PWR_FORCESHUTDWNOCC         BIT(8)
+#define PWR_SELC2MS                 BIT(7)
+#define PWR_BPDBVCC3                BIT(5)
+#define PWR_STOPCPU                 BIT(4)
+#define PWR_DBNCONBUTN              BIT(3)
+#define PWR_COLDSTART               BIT(2)
+#define PWR_PWRCS                   BIT(1)
+#define PWR_VCCON                   BIT(0)
+
+/******************************************************************************
+*
+*	13  SIB (Serial Interconnect Bus) Module
+*
+******************************************************************************/
+
+/* Register locations */
+#define SIBSize	      	        REG_AT(0x060)
+#define SIBSoundRXStart	      	REG_AT(0x064)
+#define SIBSoundTXStart         REG_AT(0x068)
+#define SIBTelecomRXStart       REG_AT(0x06C)
+#define SIBTelecomTXStart       REG_AT(0x070)
+#define SIBControl              REG_AT(0x074)
+#define SIBSoundTXRXHolding     REG_AT(0x078)
+#define SIBTelecomTXRXHolding   REG_AT(0x07C)
+#define SIBSubFrame0Control     REG_AT(0x080)
+#define SIBSubFrame1Control     REG_AT(0x084)
+#define SIBSubFrame0Status      REG_AT(0x088)
+#define SIBSubFrame1Status      REG_AT(0x08C)
+#define SIBDMAControl           REG_AT(0x090)
+
+/* SIB Size Register */
+#define SIB_SNDSIZE_MASK        0x3ffc0000
+#define SIB_SNDSIZE_SHIFT       18
+#define SIB_TELSIZE_MASK        0x00003ffc
+#define SIB_TELSIZE_SHIFT       2
+
+/* SIB Control Register */
+#define SIB_SIBIRQ              BIT(31)
+#define SIB_ENCNTTEST           BIT(30)
+#define SIB_ENDMATEST           BIT(29)
+#define SIB_SNDMONO             BIT(28)
+#define SIB_RMONOSNDIN          BIT(27)
+#define SIB_SIBSCLKDIV_MASK     (BIT(26) | BIT(25) | BIT(24))
+#define SIB_SIBSCLKDIV_SHIFT    24
+#define SIB_TEL16               BIT(23)
+#define SIB_TELFSDIV_MASK       0x007f0000
+#define SIB_TELFSDIV_SHIFT      16
+#define SIB_SND16               BIT(15)
+#define SIB_SNDFSDIV_MASK       0x00007f00
+#define SIB_SNDFSDIV_SHIFT      8
+#define SIB_SELTELSF1           BIT(7)
+#define SIB_SELSNDSF1           BIT(6)
+#define SIB_ENTEL               BIT(5)
+#define SIB_ENSND               BIT(4)
+#define SIB_SIBLOOP             BIT(3)
+#define SIB_ENSF1               BIT(2)
+#define SIB_ENSF0               BIT(1)
+#define SIB_ENSIB               BIT(0)
+
+/* SIB Frame Format (SIBSubFrame0Status and SIBSubFrame1Status) */
+#define SIB_REGISTER_EXT        BIT(31)  /* Must be zero */
+#define SIB_ADDRESS_MASK        0x78000000
+#define SIB_ADDRESS_SHIFT       27
+#define SIB_WRITE               BIT(26)
+#define SIB_AUD_VALID           BIT(17)
+#define SIB_TEL_VALID           BIT(16)
+#define SIB_DATA_MASK           0x00ff
+#define SIB_DATA_SHIFT          0
+
+/* SIB DMA Control Register */
+#define SIB_SNDBUFF1TIME        BIT(31)
+#define SIB_SNDDMALOOP          BIT(30)
+#define SIB_SNDDMAPTR_MASK      0x3ffc0000
+#define SIB_SNDDMAPTR_SHIFT     18
+#define SIB_ENDMARXSND          BIT(17)
+#define SIB_ENDMATXSND          BIT(16)
+#define SIB_TELBUFF1TIME        BIT(15)
+#define SIB_TELDMALOOP          BIT(14)
+#define SIB_TELDMAPTR_MASK      0x00003ffc
+#define SIB_TELDMAPTR_SHIFT     2
+#define SIB_ENDMARXTEL          BIT(1)
+#define SIB_ENDMATXTEL          BIT(0)
+
+/******************************************************************************
+*
+* 	14  SPI module
+*
+******************************************************************************/
+
+#define SPIControl		REG_AT(0x160)
+#define SPITransmit		REG_AT(0x164)
+#define SPIReceive		REG_AT(0x164)
+
+#define SPI_SPION		BIT(17)
+#define SPI_EMPTY		BIT(16)
+#define SPI_DELAYVAL_MASK	(BIT(12) | BIT(13) | BIT(14) | BIT(15))
+#define SPI_DELAYVAL_SHIFT	12
+#define	SPI_BAUDRATE_MASK	(BIT(8) | BIT(9) | BIT(10) | BIT(11))
+#define	SPI_BAUDRATE_SHIFT	8
+#define	SPI_PHAPOL		BIT(5)
+#define	SPI_CLKPOL		BIT(4)
+#define	SPI_WORD		BIT(2)
+#define	SPI_LSB			BIT(1)
+#define	SPI_ENSPI		BIT(0)
+
+/******************************************************************************
+*
+*	15  Timer module
+*
+******************************************************************************/
+
+#define RTChigh	      	REG_AT(0x140)
+#define RTClow	        REG_AT(0x144)
+#define RTCalarmHigh    REG_AT(0x148)
+#define RTCalarmLow     REG_AT(0x14c)
+#define RTCtimerControl REG_AT(0x150)
+#define RTCperiodTimer  REG_AT(0x154)
+
+/* RTC Timer Control */
+#define TIM_FREEZEPRE	BIT(7)
+#define TIM_FREEZERTC	BIT(6)
+#define TIM_FREEZETIMER	BIT(5)
+#define TIM_ENPERTIMER	BIT(4)
+#define TIM_RTCCLEAR	BIT(3)
+
+#define	RTC_HIGHMASK	(0xFF)
+
+/* RTC Periodic Timer */
+#define	TIM_PERCNT	0xFFFF0000
+#define	TIM_PERVAL	0x0000FFFF
+
+/* For a system clock frequency of 36.864MHz, the timer counts at one tick
+   every 868nS (ie CLK/32). Therefore 11520 counts gives a 10mS interval
+ */
+#define PER_TIMER_COUNT (1152000/HZ)
+
+/*
+ ***********************************************************************
+ *								       *
+ * 15  UART Module						       *
+ *								       *
+ ***********************************************************************
+ */
+#define TX3912_UARTA_BASE       (REGISTER_BASE + 0x0b0)
+#define TX3912_UARTB_BASE       (REGISTER_BASE + 0x0c8)
+
+/*
+ * TX3912 UART register offsets
+ */
+#define TX3912_UART_CTRL1       0x00
+#define TX3912_UART_CTRL2       0x04
+#define TX3912_UART_DMA_CTRL1   0x08
+#define TX3912_UART_DMA_CTRL2   0x0c
+#define TX3912_UART_DMA_CNT     0x10
+#define TX3912_UART_DATA        0x14
+
+#define UartA_Ctrl1   REG_AT(0x0b0)
+#define UartA_Data    REG_AT(0x0c4)
+
+/*
+ * Defines for UART Control Register 1
+ */
+#define TX3912_UART_CTRL1_UARTON	0x80000000
+#define UART_TX_EMPTY		BIT(30)
+#define UART_PRX_HOLD_FULL	BIT(29)
+#define UART_RX_HOLD_FULL	BIT(28)
+#define UART_EN_DMA_RX 		BIT(15)
+#define UART_EN_DMA_TX 		BIT(14)
+#define UART_BREAK_HALT 	BIT(12)
+#define UART_DMA_LOOP		BIT(10)
+#define UART_PULSE_THREE	BIT(9)
+#define UART_PULSE_SIX		BIT(8)
+#define UART_DT_INVERT		BIT(7)
+#define UART_DIS_TXD		BIT(6)
+#define UART_LOOPBACK		BIT(4)
+#define TX3912_UART_CTRL1_ENUART	0x00000001
+		 
+#define SER_SEVEN_BIT		BIT(3)
+#define SER_EIGHT_BIT		    0
+#define SER_EVEN_PARITY 	(BIT(2) | BIT(1))
+#define SER_ODD_PARITY  	BIT(1)
+#define SER_NO_PARITY		    0
+#define SER_TWO_STOP		BIT(5)
+#define SER_ONE_STOP		    0
+
+/*
+ * Defines for UART Control Register 2
+ *
+ *              3.6864MHz
+ * divisors =  ----------- - 1
+ *             (baud * 16)
+ */
+#define TX3912_UART_CTRL2_B230400	0x000	/*   0 */
+#define TX3912_UART_CTRL2_B115200	0x001	/*   1 */
+#define TX3912_UART_CTRL2_B76800	0x002	/*   2 */
+#define TX3912_UART_CTRL2_B57600	0x003	/*   3 */
+#define TX3912_UART_CTRL2_B38400	0x005	/*   5 */
+#define TX3912_UART_CTRL2_B19200	0x00b	/*  11 */
+#define TX3912_UART_CTRL2_B9600		0x016	/*  22 */
+#define TX3912_UART_CTRL2_B4800		0x02f	/*  47 */
+#define TX3912_UART_CTRL2_B2400		0x05f	/*  95 */
+#define TX3912_UART_CTRL2_B1200		0x0bf	/* 191 */
+#define TX3912_UART_CTRL2_B600		0x17f	/* 383 */
+#define TX3912_UART_CTRL2_B300		0x2ff	/* 767 */
+
+#endif	/* __TX3912_H__ */
diff -urN linux-2.4.6-pre8/include/asm-mips/unaligned.h linux/include/asm-mips/unaligned.h
--- linux-2.4.6-pre8/include/asm-mips/unaligned.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/unaligned.h	Mon Dec  3 22:50:39 2001
@@ -1,10 +1,10 @@
-/* $Id$
- *
+/*
  * 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) 1996, 1999 by Ralf Baechle
+ * Copyright (C) 1996, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_UNALIGNED_H
 #define _ASM_UNALIGNED_H
@@ -13,133 +13,147 @@
 extern void __put_unaligned_bad_length(void);
 
 /*
- * Load quad unaligned.
+ * Load double unaligned.
+ *
+ * This could have been implemented in plain C like IA64 but egcs 1.0.3a
+ * inflates this to 23 instructions ...
  */
-extern __inline__ unsigned long ldq_u(const unsigned long long * __addr)
+extern inline unsigned long long __ldq_u(const unsigned long long * __addr)
 {
 	unsigned long long __res;
 
-	__asm__("uld\t%0,(%1)"
-		:"=&r" (__res)
-		:"r" (__addr));
+	__asm__("ulw\t%0, %1\n\t"
+		"ulw\t%D0, 4+%1"
+		: "=&r" (__res)
+		: "m" (*__addr));
 
 	return __res;
 }
 
 /*
- * Load long unaligned.
+ * Load word unaligned.
  */
-extern __inline__ unsigned long ldl_u(const unsigned int * __addr)
+extern inline unsigned long __ldl_u(const unsigned int * __addr)
 {
 	unsigned long __res;
 
-	__asm__("ulw\t%0,(%1)"
-		:"=&r" (__res)
-		:"r" (__addr));
+	__asm__("ulw\t%0,%1"
+		: "=&r" (__res)
+		: "m" (*__addr));
 
 	return __res;
 }
 
 /*
- * Load word unaligned.
+ * Load halfword unaligned.
  */
-extern __inline__ unsigned long ldw_u(const unsigned short * __addr)
+extern inline unsigned long __ldw_u(const unsigned short * __addr)
 {
 	unsigned long __res;
 
-	__asm__("ulh\t%0,(%1)"
-		:"=&r" (__res)
-		:"r" (__addr));
+	__asm__("ulh\t%0,%1"
+		: "=&r" (__res)
+		: "m" (*__addr));
 
 	return __res;
 }
 
 /*
- * Store quad ununaligned.
+ * Store doubleword ununaligned.
  */
-extern __inline__ void stq_u(unsigned long __val, unsigned long long * __addr)
+extern inline void __stq_u(unsigned long __val, unsigned long long * __addr)
 {
-	__asm__ __volatile__(
-		"usd\t%0,(%1)"
-		: /* No results */
-		:"r" (__val),
-		 "r" (__addr));
+	__asm__("usw\t%1, %0\n\t"
+		"usw\t%D1, 4+%0"
+		: "=m" (*__addr)
+		: "r" (__val));
 }
 
 /*
  * Store long ununaligned.
  */
-extern __inline__ void stl_u(unsigned long __val, unsigned int * __addr)
+extern inline void __stl_u(unsigned long __val, unsigned int * __addr)
 {
-	__asm__ __volatile__(
-		"usw\t%0,(%1)"
-		: /* No results */
-		:"r" (__val),
-		 "r" (__addr));
+	__asm__("usw\t%1, %0"
+		: "=m" (*__addr)
+		: "r" (__val));
 }
 
 /*
  * Store word ununaligned.
  */
-extern __inline__ void stw_u(unsigned long __val, unsigned short * __addr)
+extern inline void __stw_u(unsigned long __val, unsigned short * __addr)
 {
-	__asm__ __volatile__(
-		"ush\t%0,(%1)"
-		: /* No results */
-		:"r" (__val),
-		 "r" (__addr));
-}
-
-extern inline unsigned long __get_unaligned(const void *ptr, size_t size)
-{
-	unsigned long val;
-	switch (size) {
-	case 1:
-		val = *(const unsigned char *)ptr;
-		break;
-	case 2:
-		val = ldw_u((const unsigned short *)ptr);
-		break;
-	case 4:
-		val = ldl_u((const unsigned int *)ptr);
-		break;
-	case 8:
-		val = ldq_u((const unsigned long long *)ptr);
-		break;
-	default:
-		__get_unaligned_bad_length();
-		break;
-	}
-	return val;
-}
-
-extern inline void __put_unaligned(unsigned long val, void *ptr, size_t size)
-{
-	switch (size) {
-	case 1:
-		*(unsigned char *)ptr = (val);
-		break;
-	case 2:
-		stw_u(val, (unsigned short *)ptr);
-		break;
-	case 4:
-		stl_u(val, (unsigned int *)ptr);
-		break;
-	case 8:
-		stq_u(val, (unsigned long long *)ptr);
-		break;
-	default:
-		__put_unaligned_bad_length();
-		break;
-	}
-}
-
-/* 
- * The main single-value unaligned transfer routines.
- */
-#define get_unaligned(ptr) \
-	((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
-#define put_unaligned(x,ptr) \
-	__put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+	__asm__("ush\t%1, %0"
+		: "=m" (*__addr)
+		: "r" (__val));
+}
+
+/*
+ * 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)						\
+({									\
+	__typeof__(*(ptr)) __val;					\
+									\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		__val = *(const unsigned char *)ptr;			\
+		break;							\
+	case 2:								\
+		__val = __ldw_u((const unsigned short *)ptr);		\
+		break;							\
+	case 4:								\
+		__val = __ldl_u((const unsigned int *)ptr);		\
+		break;							\
+	case 8:								\
+		__val = __ldq_u((const unsigned long long *)ptr);	\
+		break;							\
+	default:							\
+		__get_unaligned_bad_length();				\
+		break;							\
+	}								\
+									\
+	__val;								\
+})
+
+/*
+ * 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)						\
+do {									\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		*(unsigned char *)(ptr) = (val);			\
+		break;							\
+	case 2:								\
+		__stw_u(val, (unsigned short *)(ptr));			\
+		break;							\
+	case 4:								\
+		__stl_u(val, (unsigned int *)(ptr));			\
+		break;							\
+	case 8:								\
+		__stq_u(val, (unsigned long long *)(ptr));		\
+		break;							\
+	default:							\
+		__put_unaligned_bad_length();				\
+		break;							\
+	}								\
+} while(0)
 
 #endif /* _ASM_UNALIGNED_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- linux-2.4.6-pre8/include/asm-mips/unistd.h	Fri Aug 11 14:29:03 2000
+++ linux/include/asm-mips/unistd.h	Mon Dec  3 22:50:39 2001
@@ -1,990 +1,16 @@
-/* $Id: unistd.h,v 1.20 2000/02/18 00:24:48 ralf Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle
  *
  * Changed system calls macros _syscall5 - _syscall7 to push args 5 to 7 onto
  * the stack. Robin Farine for ACN S.A, Copyright (C) 1996 by ACN S.A
  */
-#ifndef __ASM_MIPS_UNISTD_H
-#define __ASM_MIPS_UNISTD_H
-
-/*
- * The syscalls 0 - 3999 are reserved for a down to the root syscall
- * compatibility with RISC/os and IRIX.  We'll see how to deal with the
- * various "real" BSD variants like Ultrix, NetBSD ...
- */
-
-/*
- * SVR4 syscalls are in the range from 1 to 999
- */
-#define __NR_SVR4			0
-#define __NR_SVR4_syscall		(__NR_SVR4 +   0)
-#define __NR_SVR4_exit			(__NR_SVR4 +   1)
-#define __NR_SVR4_fork			(__NR_SVR4 +   2)
-#define __NR_SVR4_read			(__NR_SVR4 +   3)
-#define __NR_SVR4_write			(__NR_SVR4 +   4)
-#define __NR_SVR4_open			(__NR_SVR4 +   5)
-#define __NR_SVR4_close			(__NR_SVR4 +   6)
-#define __NR_SVR4_wait			(__NR_SVR4 +   7)
-#define __NR_SVR4_creat			(__NR_SVR4 +   8)
-#define __NR_SVR4_link			(__NR_SVR4 +   9)
-#define __NR_SVR4_unlink		(__NR_SVR4 +  10)
-#define __NR_SVR4_exec			(__NR_SVR4 +  11)
-#define __NR_SVR4_chdir			(__NR_SVR4 +  12)
-#define __NR_SVR4_gtime			(__NR_SVR4 +  13)
-#define __NR_SVR4_mknod			(__NR_SVR4 +  14)
-#define __NR_SVR4_chmod			(__NR_SVR4 +  15)
-#define __NR_SVR4_chown			(__NR_SVR4 +  16)
-#define __NR_SVR4_sbreak		(__NR_SVR4 +  17)
-#define __NR_SVR4_stat			(__NR_SVR4 +  18)
-#define __NR_SVR4_lseek			(__NR_SVR4 +  19)
-#define __NR_SVR4_getpid		(__NR_SVR4 +  20)
-#define __NR_SVR4_mount			(__NR_SVR4 +  21)
-#define __NR_SVR4_umount		(__NR_SVR4 +  22)
-#define __NR_SVR4_setuid		(__NR_SVR4 +  23)
-#define __NR_SVR4_getuid		(__NR_SVR4 +  24)
-#define __NR_SVR4_stime			(__NR_SVR4 +  25)
-#define __NR_SVR4_ptrace		(__NR_SVR4 +  26)
-#define __NR_SVR4_alarm			(__NR_SVR4 +  27)
-#define __NR_SVR4_fstat			(__NR_SVR4 +  28)
-#define __NR_SVR4_pause			(__NR_SVR4 +  29)
-#define __NR_SVR4_utime			(__NR_SVR4 +  30)
-#define __NR_SVR4_stty			(__NR_SVR4 +  31)
-#define __NR_SVR4_gtty			(__NR_SVR4 +  32)
-#define __NR_SVR4_access		(__NR_SVR4 +  33)
-#define __NR_SVR4_nice			(__NR_SVR4 +  34)
-#define __NR_SVR4_statfs		(__NR_SVR4 +  35)
-#define __NR_SVR4_sync			(__NR_SVR4 +  36)
-#define __NR_SVR4_kill			(__NR_SVR4 +  37)
-#define __NR_SVR4_fstatfs		(__NR_SVR4 +  38)
-#define __NR_SVR4_setpgrp		(__NR_SVR4 +  39)
-#define __NR_SVR4_cxenix		(__NR_SVR4 +  40)
-#define __NR_SVR4_dup			(__NR_SVR4 +  41)
-#define __NR_SVR4_pipe			(__NR_SVR4 +  42)
-#define __NR_SVR4_times			(__NR_SVR4 +  43)
-#define __NR_SVR4_profil		(__NR_SVR4 +  44)
-#define __NR_SVR4_plock			(__NR_SVR4 +  45)
-#define __NR_SVR4_setgid		(__NR_SVR4 +  46)
-#define __NR_SVR4_getgid		(__NR_SVR4 +  47)
-#define __NR_SVR4_sig			(__NR_SVR4 +  48)
-#define __NR_SVR4_msgsys		(__NR_SVR4 +  49)
-#define __NR_SVR4_sysmips		(__NR_SVR4 +  50)
-#define __NR_SVR4_sysacct		(__NR_SVR4 +  51)
-#define __NR_SVR4_shmsys		(__NR_SVR4 +  52)
-#define __NR_SVR4_semsys		(__NR_SVR4 +  53)
-#define __NR_SVR4_ioctl			(__NR_SVR4 +  54)
-#define __NR_SVR4_uadmin		(__NR_SVR4 +  55)
-#define __NR_SVR4_exch 			(__NR_SVR4 +  56)
-#define __NR_SVR4_utssys		(__NR_SVR4 +  57)
-#define __NR_SVR4_fsync			(__NR_SVR4 +  58)
-#define __NR_SVR4_exece			(__NR_SVR4 +  59)
-#define __NR_SVR4_umask			(__NR_SVR4 +  60)
-#define __NR_SVR4_chroot		(__NR_SVR4 +  61)
-#define __NR_SVR4_fcntl			(__NR_SVR4 +  62)
-#define __NR_SVR4_ulimit		(__NR_SVR4 +  63)
-#define __NR_SVR4_reserved1		(__NR_SVR4 +  64)
-#define __NR_SVR4_reserved2		(__NR_SVR4 +  65)
-#define __NR_SVR4_reserved3		(__NR_SVR4 +  66)
-#define __NR_SVR4_reserved4		(__NR_SVR4 +  67)
-#define __NR_SVR4_reserved5		(__NR_SVR4 +  68)
-#define __NR_SVR4_reserved6		(__NR_SVR4 +  69)
-#define __NR_SVR4_advfs			(__NR_SVR4 +  70)
-#define __NR_SVR4_unadvfs		(__NR_SVR4 +  71)
-#define __NR_SVR4_unused1		(__NR_SVR4 +  72)
-#define __NR_SVR4_unused2		(__NR_SVR4 +  73)
-#define __NR_SVR4_rfstart		(__NR_SVR4 +  74)
-#define __NR_SVR4_unused3		(__NR_SVR4 +  75)
-#define __NR_SVR4_rdebug		(__NR_SVR4 +  76)
-#define __NR_SVR4_rfstop		(__NR_SVR4 +  77)
-#define __NR_SVR4_rfsys			(__NR_SVR4 +  78)
-#define __NR_SVR4_rmdir			(__NR_SVR4 +  79)
-#define __NR_SVR4_mkdir			(__NR_SVR4 +  80)
-#define __NR_SVR4_getdents		(__NR_SVR4 +  81)
-#define __NR_SVR4_libattach		(__NR_SVR4 +  82)
-#define __NR_SVR4_libdetach		(__NR_SVR4 +  83)
-#define __NR_SVR4_sysfs			(__NR_SVR4 +  84)
-#define __NR_SVR4_getmsg		(__NR_SVR4 +  85)
-#define __NR_SVR4_putmsg		(__NR_SVR4 +  86)
-#define __NR_SVR4_poll			(__NR_SVR4 +  87)
-#define __NR_SVR4_lstat			(__NR_SVR4 +  88)
-#define __NR_SVR4_symlink		(__NR_SVR4 +  89)
-#define __NR_SVR4_readlink		(__NR_SVR4 +  90)
-#define __NR_SVR4_setgroups		(__NR_SVR4 +  91)
-#define __NR_SVR4_getgroups		(__NR_SVR4 +  92)
-#define __NR_SVR4_fchmod		(__NR_SVR4 +  93)
-#define __NR_SVR4_fchown		(__NR_SVR4 +  94)
-#define __NR_SVR4_sigprocmask		(__NR_SVR4 +  95)
-#define __NR_SVR4_sigsuspend		(__NR_SVR4 +  96)
-#define __NR_SVR4_sigaltstack		(__NR_SVR4 +  97)
-#define __NR_SVR4_sigaction		(__NR_SVR4 +  98)
-#define __NR_SVR4_sigpending		(__NR_SVR4 +  99)
-#define __NR_SVR4_setcontext		(__NR_SVR4 + 100)
-#define __NR_SVR4_evsys			(__NR_SVR4 + 101)
-#define __NR_SVR4_evtrapret		(__NR_SVR4 + 102)
-#define __NR_SVR4_statvfs		(__NR_SVR4 + 103)
-#define __NR_SVR4_fstatvfs		(__NR_SVR4 + 104)
-#define __NR_SVR4_reserved7		(__NR_SVR4 + 105)
-#define __NR_SVR4_nfssys		(__NR_SVR4 + 106)
-#define __NR_SVR4_waitid		(__NR_SVR4 + 107)
-#define __NR_SVR4_sigsendset		(__NR_SVR4 + 108)
-#define __NR_SVR4_hrtsys		(__NR_SVR4 + 109)
-#define __NR_SVR4_acancel		(__NR_SVR4 + 110)
-#define __NR_SVR4_async			(__NR_SVR4 + 111)
-#define __NR_SVR4_priocntlset		(__NR_SVR4 + 112)
-#define __NR_SVR4_pathconf		(__NR_SVR4 + 113)
-#define __NR_SVR4_mincore		(__NR_SVR4 + 114)
-#define __NR_SVR4_mmap			(__NR_SVR4 + 115)
-#define __NR_SVR4_mprotect		(__NR_SVR4 + 116)
-#define __NR_SVR4_munmap		(__NR_SVR4 + 117)
-#define __NR_SVR4_fpathconf		(__NR_SVR4 + 118)
-#define __NR_SVR4_vfork			(__NR_SVR4 + 119)
-#define __NR_SVR4_fchdir		(__NR_SVR4 + 120)
-#define __NR_SVR4_readv			(__NR_SVR4 + 121)
-#define __NR_SVR4_writev		(__NR_SVR4 + 122)
-#define __NR_SVR4_xstat			(__NR_SVR4 + 123)
-#define __NR_SVR4_lxstat		(__NR_SVR4 + 124)
-#define __NR_SVR4_fxstat		(__NR_SVR4 + 125)
-#define __NR_SVR4_xmknod		(__NR_SVR4 + 126)
-#define __NR_SVR4_clocal		(__NR_SVR4 + 127)
-#define __NR_SVR4_setrlimit		(__NR_SVR4 + 128)
-#define __NR_SVR4_getrlimit		(__NR_SVR4 + 129)
-#define __NR_SVR4_lchown		(__NR_SVR4 + 130)
-#define __NR_SVR4_memcntl		(__NR_SVR4 + 131)
-#define __NR_SVR4_getpmsg		(__NR_SVR4 + 132)
-#define __NR_SVR4_putpmsg		(__NR_SVR4 + 133)
-#define __NR_SVR4_rename		(__NR_SVR4 + 134)
-#define __NR_SVR4_nuname		(__NR_SVR4 + 135)
-#define __NR_SVR4_setegid		(__NR_SVR4 + 136)
-#define __NR_SVR4_sysconf		(__NR_SVR4 + 137)
-#define __NR_SVR4_adjtime		(__NR_SVR4 + 138)
-#define __NR_SVR4_sysinfo		(__NR_SVR4 + 139)
-#define __NR_SVR4_reserved8		(__NR_SVR4 + 140)
-#define __NR_SVR4_seteuid		(__NR_SVR4 + 141)
-#define __NR_SVR4_PYRAMID_statis	(__NR_SVR4 + 142)
-#define __NR_SVR4_PYRAMID_tuning	(__NR_SVR4 + 143)
-#define __NR_SVR4_PYRAMID_forcerr	(__NR_SVR4 + 144)
-#define __NR_SVR4_PYRAMID_mpcntl	(__NR_SVR4 + 145)
-#define __NR_SVR4_reserved9		(__NR_SVR4 + 146)
-#define __NR_SVR4_reserved10		(__NR_SVR4 + 147)
-#define __NR_SVR4_reserved11		(__NR_SVR4 + 148)
-#define __NR_SVR4_reserved12		(__NR_SVR4 + 149)
-#define __NR_SVR4_reserved13		(__NR_SVR4 + 150)
-#define __NR_SVR4_reserved14		(__NR_SVR4 + 151)
-#define __NR_SVR4_reserved15		(__NR_SVR4 + 152)
-#define __NR_SVR4_reserved16		(__NR_SVR4 + 153)
-#define __NR_SVR4_reserved17		(__NR_SVR4 + 154)
-#define __NR_SVR4_reserved18		(__NR_SVR4 + 155)
-#define __NR_SVR4_reserved19		(__NR_SVR4 + 156)
-#define __NR_SVR4_reserved20		(__NR_SVR4 + 157)
-#define __NR_SVR4_reserved21		(__NR_SVR4 + 158)
-#define __NR_SVR4_reserved22		(__NR_SVR4 + 159)
-#define __NR_SVR4_reserved23		(__NR_SVR4 + 160)
-#define __NR_SVR4_reserved24		(__NR_SVR4 + 161)
-#define __NR_SVR4_reserved25		(__NR_SVR4 + 162)
-#define __NR_SVR4_reserved26		(__NR_SVR4 + 163)
-#define __NR_SVR4_reserved27		(__NR_SVR4 + 164)
-#define __NR_SVR4_reserved28		(__NR_SVR4 + 165)
-#define __NR_SVR4_reserved29		(__NR_SVR4 + 166)
-#define __NR_SVR4_reserved30		(__NR_SVR4 + 167)
-#define __NR_SVR4_reserved31		(__NR_SVR4 + 168)
-#define __NR_SVR4_reserved32		(__NR_SVR4 + 169)
-#define __NR_SVR4_reserved33		(__NR_SVR4 + 170)
-#define __NR_SVR4_reserved34		(__NR_SVR4 + 171)
-#define __NR_SVR4_reserved35		(__NR_SVR4 + 172)
-#define __NR_SVR4_reserved36		(__NR_SVR4 + 173)
-#define __NR_SVR4_reserved37		(__NR_SVR4 + 174)
-#define __NR_SVR4_reserved38		(__NR_SVR4 + 175)
-#define __NR_SVR4_reserved39		(__NR_SVR4 + 176)
-#define __NR_SVR4_reserved40		(__NR_SVR4 + 177)
-#define __NR_SVR4_reserved41		(__NR_SVR4 + 178)
-#define __NR_SVR4_reserved42		(__NR_SVR4 + 179)
-#define __NR_SVR4_reserved43		(__NR_SVR4 + 180)
-#define __NR_SVR4_reserved44		(__NR_SVR4 + 181)
-#define __NR_SVR4_reserved45		(__NR_SVR4 + 182)
-#define __NR_SVR4_reserved46		(__NR_SVR4 + 183)
-#define __NR_SVR4_reserved47		(__NR_SVR4 + 184)
-#define __NR_SVR4_reserved48		(__NR_SVR4 + 185)
-#define __NR_SVR4_reserved49		(__NR_SVR4 + 186)
-#define __NR_SVR4_reserved50		(__NR_SVR4 + 187)
-#define __NR_SVR4_reserved51		(__NR_SVR4 + 188)
-#define __NR_SVR4_reserved52		(__NR_SVR4 + 189)
-#define __NR_SVR4_reserved53		(__NR_SVR4 + 190)
-#define __NR_SVR4_reserved54		(__NR_SVR4 + 191)
-#define __NR_SVR4_reserved55		(__NR_SVR4 + 192)
-#define __NR_SVR4_reserved56		(__NR_SVR4 + 193)
-#define __NR_SVR4_reserved57		(__NR_SVR4 + 194)
-#define __NR_SVR4_reserved58		(__NR_SVR4 + 195)
-#define __NR_SVR4_reserved59		(__NR_SVR4 + 196)
-#define __NR_SVR4_reserved60		(__NR_SVR4 + 197)
-#define __NR_SVR4_reserved61		(__NR_SVR4 + 198)
-#define __NR_SVR4_reserved62		(__NR_SVR4 + 199)
-#define __NR_SVR4_reserved63		(__NR_SVR4 + 200)
-#define __NR_SVR4_aread			(__NR_SVR4 + 201)
-#define __NR_SVR4_awrite		(__NR_SVR4 + 202)	
-#define __NR_SVR4_listio		(__NR_SVR4 + 203)
-#define __NR_SVR4_mips_acancel		(__NR_SVR4 + 204)
-#define __NR_SVR4_astatus		(__NR_SVR4 + 205)
-#define __NR_SVR4_await			(__NR_SVR4 + 206)
-#define __NR_SVR4_areadv		(__NR_SVR4 + 207)
-#define __NR_SVR4_awritev		(__NR_SVR4 + 208)
-#define __NR_SVR4_MIPS_reserved1	(__NR_SVR4 + 209)
-#define __NR_SVR4_MIPS_reserved2	(__NR_SVR4 + 210)
-#define __NR_SVR4_MIPS_reserved3	(__NR_SVR4 + 211)
-#define __NR_SVR4_MIPS_reserved4	(__NR_SVR4 + 212)
-#define __NR_SVR4_MIPS_reserved5	(__NR_SVR4 + 213)
-#define __NR_SVR4_MIPS_reserved6	(__NR_SVR4 + 214)
-#define __NR_SVR4_MIPS_reserved7	(__NR_SVR4 + 215)
-#define __NR_SVR4_MIPS_reserved8	(__NR_SVR4 + 216)
-#define __NR_SVR4_MIPS_reserved9	(__NR_SVR4 + 217)
-#define __NR_SVR4_MIPS_reserved10	(__NR_SVR4 + 218)
-#define __NR_SVR4_MIPS_reserved11	(__NR_SVR4 + 219)
-#define __NR_SVR4_MIPS_reserved12	(__NR_SVR4 + 220)
-#define __NR_SVR4_CDC_reserved1		(__NR_SVR4 + 221)
-#define __NR_SVR4_CDC_reserved2		(__NR_SVR4 + 222)
-#define __NR_SVR4_CDC_reserved3		(__NR_SVR4 + 223)
-#define __NR_SVR4_CDC_reserved4		(__NR_SVR4 + 224)
-#define __NR_SVR4_CDC_reserved5		(__NR_SVR4 + 225)
-#define __NR_SVR4_CDC_reserved6		(__NR_SVR4 + 226)
-#define __NR_SVR4_CDC_reserved7		(__NR_SVR4 + 227)
-#define __NR_SVR4_CDC_reserved8		(__NR_SVR4 + 228)
-#define __NR_SVR4_CDC_reserved9		(__NR_SVR4 + 229)
-#define __NR_SVR4_CDC_reserved10	(__NR_SVR4 + 230)
-#define __NR_SVR4_CDC_reserved11	(__NR_SVR4 + 231)
-#define __NR_SVR4_CDC_reserved12	(__NR_SVR4 + 232)
-#define __NR_SVR4_CDC_reserved13	(__NR_SVR4 + 233)
-#define __NR_SVR4_CDC_reserved14	(__NR_SVR4 + 234)
-#define __NR_SVR4_CDC_reserved15	(__NR_SVR4 + 235)
-#define __NR_SVR4_CDC_reserved16	(__NR_SVR4 + 236)
-#define __NR_SVR4_CDC_reserved17	(__NR_SVR4 + 237)
-#define __NR_SVR4_CDC_reserved18	(__NR_SVR4 + 238)
-#define __NR_SVR4_CDC_reserved19	(__NR_SVR4 + 239)
-#define __NR_SVR4_CDC_reserved20	(__NR_SVR4 + 240)
-
-/*
- * SYS V syscalls are in the range from 1000 to 1999
- */
-#define __NR_SYSV			1000
-#define __NR_SYSV_syscall		(__NR_SYSV +   0)
-#define __NR_SYSV_exit			(__NR_SYSV +   1)
-#define __NR_SYSV_fork			(__NR_SYSV +   2)
-#define __NR_SYSV_read			(__NR_SYSV +   3)
-#define __NR_SYSV_write			(__NR_SYSV +   4)
-#define __NR_SYSV_open			(__NR_SYSV +   5)
-#define __NR_SYSV_close			(__NR_SYSV +   6)
-#define __NR_SYSV_wait			(__NR_SYSV +   7)
-#define __NR_SYSV_creat			(__NR_SYSV +   8)
-#define __NR_SYSV_link			(__NR_SYSV +   9)
-#define __NR_SYSV_unlink		(__NR_SYSV +  10)
-#define __NR_SYSV_execv			(__NR_SYSV +  11)
-#define __NR_SYSV_chdir			(__NR_SYSV +  12)
-#define __NR_SYSV_time			(__NR_SYSV +  13)
-#define __NR_SYSV_mknod			(__NR_SYSV +  14)
-#define __NR_SYSV_chmod			(__NR_SYSV +  15)
-#define __NR_SYSV_chown			(__NR_SYSV +  16)
-#define __NR_SYSV_brk			(__NR_SYSV +  17)
-#define __NR_SYSV_stat			(__NR_SYSV +  18)
-#define __NR_SYSV_lseek			(__NR_SYSV +  19)
-#define __NR_SYSV_getpid		(__NR_SYSV +  20)
-#define __NR_SYSV_mount			(__NR_SYSV +  21)
-#define __NR_SYSV_umount		(__NR_SYSV +  22)
-#define __NR_SYSV_setuid		(__NR_SYSV +  23)
-#define __NR_SYSV_getuid		(__NR_SYSV +  24)
-#define __NR_SYSV_stime			(__NR_SYSV +  25)
-#define __NR_SYSV_ptrace		(__NR_SYSV +  26)
-#define __NR_SYSV_alarm			(__NR_SYSV +  27)
-#define __NR_SYSV_fstat			(__NR_SYSV +  28)
-#define __NR_SYSV_pause			(__NR_SYSV +  29)
-#define __NR_SYSV_utime			(__NR_SYSV +  30)
-#define __NR_SYSV_stty			(__NR_SYSV +  31)
-#define __NR_SYSV_gtty			(__NR_SYSV +  32)
-#define __NR_SYSV_access		(__NR_SYSV +  33)
-#define __NR_SYSV_nice			(__NR_SYSV +  34)
-#define __NR_SYSV_statfs		(__NR_SYSV +  35)
-#define __NR_SYSV_sync			(__NR_SYSV +  36)
-#define __NR_SYSV_kill			(__NR_SYSV +  37)
-#define __NR_SYSV_fstatfs		(__NR_SYSV +  38)
-#define __NR_SYSV_setpgrp		(__NR_SYSV +  39)
-#define __NR_SYSV_syssgi		(__NR_SYSV +  40)
-#define __NR_SYSV_dup			(__NR_SYSV +  41)
-#define __NR_SYSV_pipe			(__NR_SYSV +  42)
-#define __NR_SYSV_times			(__NR_SYSV +  43)
-#define __NR_SYSV_profil		(__NR_SYSV +  44)
-#define __NR_SYSV_plock			(__NR_SYSV +  45)
-#define __NR_SYSV_setgid		(__NR_SYSV +  46)
-#define __NR_SYSV_getgid		(__NR_SYSV +  47)
-#define __NR_SYSV_sig			(__NR_SYSV +  48)
-#define __NR_SYSV_msgsys		(__NR_SYSV +  49)
-#define __NR_SYSV_sysmips		(__NR_SYSV +  50)
-#define __NR_SYSV_acct			(__NR_SYSV +  51)
-#define __NR_SYSV_shmsys		(__NR_SYSV +  52)
-#define __NR_SYSV_semsys		(__NR_SYSV +  53)
-#define __NR_SYSV_ioctl			(__NR_SYSV +  54)
-#define __NR_SYSV_uadmin		(__NR_SYSV +  55)
-#define __NR_SYSV_sysmp			(__NR_SYSV +  56)
-#define __NR_SYSV_utssys		(__NR_SYSV +  57)
-#define __NR_SYSV_USG_reserved1		(__NR_SYSV +  58)
-#define __NR_SYSV_execve		(__NR_SYSV +  59)
-#define __NR_SYSV_umask			(__NR_SYSV +  60)
-#define __NR_SYSV_chroot		(__NR_SYSV +  61)
-#define __NR_SYSV_fcntl			(__NR_SYSV +  62)
-#define __NR_SYSV_ulimit		(__NR_SYSV +  63)
-#define __NR_SYSV_SAFARI4_reserved1	(__NR_SYSV +  64)
-#define __NR_SYSV_SAFARI4_reserved2	(__NR_SYSV +  65)
-#define __NR_SYSV_SAFARI4_reserved3	(__NR_SYSV +  66)
-#define __NR_SYSV_SAFARI4_reserved4	(__NR_SYSV +  67)
-#define __NR_SYSV_SAFARI4_reserved5	(__NR_SYSV +  68)
-#define __NR_SYSV_SAFARI4_reserved6	(__NR_SYSV +  69)
-#define __NR_SYSV_advfs			(__NR_SYSV +  70)
-#define __NR_SYSV_unadvfs		(__NR_SYSV +  71)
-#define __NR_SYSV_rmount		(__NR_SYSV +  72)
-#define __NR_SYSV_rumount		(__NR_SYSV +  73)
-#define __NR_SYSV_rfstart		(__NR_SYSV +  74)
-#define __NR_SYSV_getrlimit64		(__NR_SYSV +  75)
-#define __NR_SYSV_setrlimit64		(__NR_SYSV +  76)
-#define __NR_SYSV_nanosleep		(__NR_SYSV +  77)
-#define __NR_SYSV_lseek64		(__NR_SYSV +  78)
-#define __NR_SYSV_rmdir			(__NR_SYSV +  79)
-#define __NR_SYSV_mkdir			(__NR_SYSV +  80)
-#define __NR_SYSV_getdents		(__NR_SYSV +  81)
-#define __NR_SYSV_sginap		(__NR_SYSV +  82)
-#define __NR_SYSV_sgikopt		(__NR_SYSV +  83)
-#define __NR_SYSV_sysfs			(__NR_SYSV +  84)
-#define __NR_SYSV_getmsg		(__NR_SYSV +  85)
-#define __NR_SYSV_putmsg		(__NR_SYSV +  86)
-#define __NR_SYSV_poll			(__NR_SYSV +  87)
-#define __NR_SYSV_sigreturn		(__NR_SYSV +  88)
-#define __NR_SYSV_accept		(__NR_SYSV +  89)
-#define __NR_SYSV_bind			(__NR_SYSV +  90)
-#define __NR_SYSV_connect		(__NR_SYSV +  91)
-#define __NR_SYSV_gethostid		(__NR_SYSV +  92)
-#define __NR_SYSV_getpeername		(__NR_SYSV +  93)
-#define __NR_SYSV_getsockname		(__NR_SYSV +  94)
-#define __NR_SYSV_getsockopt		(__NR_SYSV +  95)
-#define __NR_SYSV_listen		(__NR_SYSV +  96)
-#define __NR_SYSV_recv			(__NR_SYSV +  97)
-#define __NR_SYSV_recvfrom		(__NR_SYSV +  98)
-#define __NR_SYSV_recvmsg		(__NR_SYSV +  99)
-#define __NR_SYSV_select		(__NR_SYSV + 100)
-#define __NR_SYSV_send			(__NR_SYSV + 101)
-#define __NR_SYSV_sendmsg		(__NR_SYSV + 102)
-#define __NR_SYSV_sendto		(__NR_SYSV + 103)
-#define __NR_SYSV_sethostid		(__NR_SYSV + 104)
-#define __NR_SYSV_setsockopt		(__NR_SYSV + 105)
-#define __NR_SYSV_shutdown		(__NR_SYSV + 106)
-#define __NR_SYSV_socket		(__NR_SYSV + 107)
-#define __NR_SYSV_gethostname		(__NR_SYSV + 108)
-#define __NR_SYSV_sethostname		(__NR_SYSV + 109)
-#define __NR_SYSV_getdomainname		(__NR_SYSV + 110)
-#define __NR_SYSV_setdomainname		(__NR_SYSV + 111)
-#define __NR_SYSV_truncate		(__NR_SYSV + 112)
-#define __NR_SYSV_ftruncate		(__NR_SYSV + 113)
-#define __NR_SYSV_rename		(__NR_SYSV + 114)
-#define __NR_SYSV_symlink		(__NR_SYSV + 115)
-#define __NR_SYSV_readlink		(__NR_SYSV + 116)
-#define __NR_SYSV_lstat			(__NR_SYSV + 117)
-#define __NR_SYSV_nfsmount		(__NR_SYSV + 118)
-#define __NR_SYSV_nfssvc		(__NR_SYSV + 119)
-#define __NR_SYSV_getfh			(__NR_SYSV + 120)
-#define __NR_SYSV_async_daemon		(__NR_SYSV + 121)
-#define __NR_SYSV_exportfs		(__NR_SYSV + 122)
-#define __NR_SYSV_setregid		(__NR_SYSV + 123)
-#define __NR_SYSV_setreuid		(__NR_SYSV + 124)
-#define __NR_SYSV_getitimer		(__NR_SYSV + 125)
-#define __NR_SYSV_setitimer		(__NR_SYSV + 126)
-#define __NR_SYSV_adjtime		(__NR_SYSV + 127)
-#define __NR_SYSV_BSD_getime		(__NR_SYSV + 128)
-#define __NR_SYSV_sproc			(__NR_SYSV + 129)
-#define __NR_SYSV_prctl			(__NR_SYSV + 130)
-#define __NR_SYSV_procblk		(__NR_SYSV + 131)
-#define __NR_SYSV_sprocsp		(__NR_SYSV + 132)
-#define __NR_SYSV_sgigsc		(__NR_SYSV + 133)
-#define __NR_SYSV_mmap			(__NR_SYSV + 134)
-#define __NR_SYSV_munmap		(__NR_SYSV + 135)
-#define __NR_SYSV_mprotect		(__NR_SYSV + 136)
-#define __NR_SYSV_msync			(__NR_SYSV + 137)
-#define __NR_SYSV_madvise		(__NR_SYSV + 138)
-#define __NR_SYSV_pagelock		(__NR_SYSV + 139)
-#define __NR_SYSV_getpagesize		(__NR_SYSV + 140)
-#define __NR_SYSV_quotactl		(__NR_SYSV + 141)
-#define __NR_SYSV_libdetach		(__NR_SYSV + 142)
-#define __NR_SYSV_BSDgetpgrp		(__NR_SYSV + 143)
-#define __NR_SYSV_BSDsetpgrp		(__NR_SYSV + 144)
-#define __NR_SYSV_vhangup		(__NR_SYSV + 145)
-#define __NR_SYSV_fsync			(__NR_SYSV + 146)
-#define __NR_SYSV_fchdir		(__NR_SYSV + 147)
-#define __NR_SYSV_getrlimit		(__NR_SYSV + 148)
-#define __NR_SYSV_setrlimit		(__NR_SYSV + 149)
-#define __NR_SYSV_cacheflush		(__NR_SYSV + 150)
-#define __NR_SYSV_cachectl		(__NR_SYSV + 151)
-#define __NR_SYSV_fchown		(__NR_SYSV + 152)
-#define __NR_SYSV_fchmod		(__NR_SYSV + 153)
-#define __NR_SYSV_wait3			(__NR_SYSV + 154)
-#define __NR_SYSV_socketpair		(__NR_SYSV + 155)
-#define __NR_SYSV_sysinfo		(__NR_SYSV + 156)
-#define __NR_SYSV_nuname		(__NR_SYSV + 157)
-#define __NR_SYSV_xstat			(__NR_SYSV + 158)
-#define __NR_SYSV_lxstat		(__NR_SYSV + 159)
-#define __NR_SYSV_fxstat		(__NR_SYSV + 160)
-#define __NR_SYSV_xmknod		(__NR_SYSV + 161)
-#define __NR_SYSV_ksigaction		(__NR_SYSV + 162)
-#define __NR_SYSV_sigpending		(__NR_SYSV + 163)
-#define __NR_SYSV_sigprocmask		(__NR_SYSV + 164)
-#define __NR_SYSV_sigsuspend		(__NR_SYSV + 165)
-#define __NR_SYSV_sigpoll		(__NR_SYSV + 166)
-#define __NR_SYSV_swapctl		(__NR_SYSV + 167)
-#define __NR_SYSV_getcontext		(__NR_SYSV + 168)
-#define __NR_SYSV_setcontext		(__NR_SYSV + 169)
-#define __NR_SYSV_waitsys		(__NR_SYSV + 170)
-#define __NR_SYSV_sigstack		(__NR_SYSV + 171)
-#define __NR_SYSV_sigaltstack		(__NR_SYSV + 172)
-#define __NR_SYSV_sigsendset		(__NR_SYSV + 173)
-#define __NR_SYSV_statvfs		(__NR_SYSV + 174)
-#define __NR_SYSV_fstatvfs		(__NR_SYSV + 175)
-#define __NR_SYSV_getpmsg		(__NR_SYSV + 176)
-#define __NR_SYSV_putpmsg		(__NR_SYSV + 177)
-#define __NR_SYSV_lchown		(__NR_SYSV + 178)
-#define __NR_SYSV_priocntl		(__NR_SYSV + 179)
-#define __NR_SYSV_ksigqueue		(__NR_SYSV + 180)
-#define __NR_SYSV_readv			(__NR_SYSV + 181)
-#define __NR_SYSV_writev		(__NR_SYSV + 182)
-#define __NR_SYSV_truncate64		(__NR_SYSV + 183)
-#define __NR_SYSV_ftruncate64		(__NR_SYSV + 184)
-#define __NR_SYSV_mmap64		(__NR_SYSV + 185)
-#define __NR_SYSV_dmi			(__NR_SYSV + 186)
-#define __NR_SYSV_pread			(__NR_SYSV + 187)
-#define __NR_SYSV_pwrite		(__NR_SYSV + 188)
+#ifndef _ASM_UNISTD_H
+#define _ASM_UNISTD_H
 
-/*
- * BSD 4.3 syscalls are in the range from 2000 to 2999
- */
-#define __NR_BSD43			2000
-#define __NR_BSD43_syscall		(__NR_BSD43 +   0)
-#define __NR_BSD43_exit			(__NR_BSD43 +   1)
-#define __NR_BSD43_fork			(__NR_BSD43 +   2)
-#define __NR_BSD43_read			(__NR_BSD43 +   3)
-#define __NR_BSD43_write		(__NR_BSD43 +   4)
-#define __NR_BSD43_open			(__NR_BSD43 +   5)
-#define __NR_BSD43_close		(__NR_BSD43 +   6)
-#define __NR_BSD43_wait			(__NR_BSD43 +   7)
-#define __NR_BSD43_creat		(__NR_BSD43 +   8)
-#define __NR_BSD43_link			(__NR_BSD43 +   9)
-#define __NR_BSD43_unlink		(__NR_BSD43 +  10)
-#define __NR_BSD43_exec			(__NR_BSD43 +  11)
-#define __NR_BSD43_chdir		(__NR_BSD43 +  12)
-#define __NR_BSD43_time			(__NR_BSD43 +  13)
-#define __NR_BSD43_mknod		(__NR_BSD43 +  14)
-#define __NR_BSD43_chmod		(__NR_BSD43 +  15)
-#define __NR_BSD43_chown		(__NR_BSD43 +  16)
-#define __NR_BSD43_sbreak		(__NR_BSD43 +  17)
-#define __NR_BSD43_oldstat		(__NR_BSD43 +  18)
-#define __NR_BSD43_lseek		(__NR_BSD43 +  19)
-#define __NR_BSD43_getpid		(__NR_BSD43 +  20)
-#define __NR_BSD43_oldmount		(__NR_BSD43 +  21)
-#define __NR_BSD43_umount		(__NR_BSD43 +  22)
-#define __NR_BSD43_setuid		(__NR_BSD43 +  23)
-#define __NR_BSD43_getuid		(__NR_BSD43 +  24)
-#define __NR_BSD43_stime		(__NR_BSD43 +  25)
-#define __NR_BSD43_ptrace		(__NR_BSD43 +  26)
-#define __NR_BSD43_alarm		(__NR_BSD43 +  27)
-#define __NR_BSD43_oldfstat		(__NR_BSD43 +  28)
-#define __NR_BSD43_pause		(__NR_BSD43 +  29)
-#define __NR_BSD43_utime		(__NR_BSD43 +  30)
-#define __NR_BSD43_stty			(__NR_BSD43 +  31)
-#define __NR_BSD43_gtty			(__NR_BSD43 +  32)
-#define __NR_BSD43_access		(__NR_BSD43 +  33)
-#define __NR_BSD43_nice			(__NR_BSD43 +  34)
-#define __NR_BSD43_ftime		(__NR_BSD43 +  35)
-#define __NR_BSD43_sync			(__NR_BSD43 +  36)
-#define __NR_BSD43_kill			(__NR_BSD43 +  37)
-#define __NR_BSD43_stat			(__NR_BSD43 +  38)
-#define __NR_BSD43_oldsetpgrp		(__NR_BSD43 +  39)
-#define __NR_BSD43_lstat		(__NR_BSD43 +  40)
-#define __NR_BSD43_dup			(__NR_BSD43 +  41)
-#define __NR_BSD43_pipe			(__NR_BSD43 +  42)
-#define __NR_BSD43_times		(__NR_BSD43 +  43)
-#define __NR_BSD43_profil		(__NR_BSD43 +  44)
-#define __NR_BSD43_msgsys		(__NR_BSD43 +  45)
-#define __NR_BSD43_setgid		(__NR_BSD43 +  46)
-#define __NR_BSD43_getgid		(__NR_BSD43 +  47)
-#define __NR_BSD43_ssig			(__NR_BSD43 +  48)
-#define __NR_BSD43_reserved1		(__NR_BSD43 +  49)
-#define __NR_BSD43_reserved2		(__NR_BSD43 +  50)
-#define __NR_BSD43_sysacct		(__NR_BSD43 +  51)
-#define __NR_BSD43_phys			(__NR_BSD43 +  52)
-#define __NR_BSD43_lock			(__NR_BSD43 +  53)
-#define __NR_BSD43_ioctl		(__NR_BSD43 +  54)
-#define __NR_BSD43_reboot		(__NR_BSD43 +  55)
-#define __NR_BSD43_mpxchan		(__NR_BSD43 +  56)
-#define __NR_BSD43_symlink		(__NR_BSD43 +  57)
-#define __NR_BSD43_readlink		(__NR_BSD43 +  58)
-#define __NR_BSD43_execve		(__NR_BSD43 +  59)
-#define __NR_BSD43_umask		(__NR_BSD43 +  60)
-#define __NR_BSD43_chroot		(__NR_BSD43 +  61)
-#define __NR_BSD43_fstat		(__NR_BSD43 +  62)
-#define __NR_BSD43_reserved3		(__NR_BSD43 +  63)
-#define __NR_BSD43_getpagesize		(__NR_BSD43 +  64)
-#define __NR_BSD43_mremap		(__NR_BSD43 +  65)
-#define __NR_BSD43_vfork		(__NR_BSD43 +  66)
-#define __NR_BSD43_vread		(__NR_BSD43 +  67)
-#define __NR_BSD43_vwrite		(__NR_BSD43 +  68)
-#define __NR_BSD43_sbrk			(__NR_BSD43 +  69)
-#define __NR_BSD43_sstk			(__NR_BSD43 +  70)
-#define __NR_BSD43_mmap			(__NR_BSD43 +  71)
-#define __NR_BSD43_vadvise		(__NR_BSD43 +  72)
-#define __NR_BSD43_munmap		(__NR_BSD43 +  73)
-#define __NR_BSD43_mprotect		(__NR_BSD43 +  74)
-#define __NR_BSD43_madvise		(__NR_BSD43 +  75)
-#define __NR_BSD43_vhangup		(__NR_BSD43 +  76)
-#define __NR_BSD43_vlimit		(__NR_BSD43 +  77)
-#define __NR_BSD43_mincore		(__NR_BSD43 +  78)
-#define __NR_BSD43_getgroups		(__NR_BSD43 +  79)
-#define __NR_BSD43_setgroups		(__NR_BSD43 +  80)
-#define __NR_BSD43_getpgrp		(__NR_BSD43 +  81)
-#define __NR_BSD43_setpgrp		(__NR_BSD43 +  82)
-#define __NR_BSD43_setitimer		(__NR_BSD43 +  83)
-#define __NR_BSD43_wait3		(__NR_BSD43 +  84)
-#define __NR_BSD43_swapon		(__NR_BSD43 +  85)
-#define __NR_BSD43_getitimer		(__NR_BSD43 +  86)
-#define __NR_BSD43_gethostname		(__NR_BSD43 +  87)
-#define __NR_BSD43_sethostname		(__NR_BSD43 +  88)
-#define __NR_BSD43_getdtablesize	(__NR_BSD43 +  89)
-#define __NR_BSD43_dup2			(__NR_BSD43 +  90)
-#define __NR_BSD43_getdopt		(__NR_BSD43 +  91)
-#define __NR_BSD43_fcntl		(__NR_BSD43 +  92)
-#define __NR_BSD43_select		(__NR_BSD43 +  93)
-#define __NR_BSD43_setdopt		(__NR_BSD43 +  94)
-#define __NR_BSD43_fsync		(__NR_BSD43 +  95)
-#define __NR_BSD43_setpriority		(__NR_BSD43 +  96)
-#define __NR_BSD43_socket		(__NR_BSD43 +  97)
-#define __NR_BSD43_connect		(__NR_BSD43 +  98)
-#define __NR_BSD43_oldaccept		(__NR_BSD43 +  99)
-#define __NR_BSD43_getpriority		(__NR_BSD43 + 100)
-#define __NR_BSD43_send			(__NR_BSD43 + 101)
-#define __NR_BSD43_recv			(__NR_BSD43 + 102)
-#define __NR_BSD43_sigreturn		(__NR_BSD43 + 103)
-#define __NR_BSD43_bind			(__NR_BSD43 + 104)
-#define __NR_BSD43_setsockopt		(__NR_BSD43 + 105)
-#define __NR_BSD43_listen		(__NR_BSD43 + 106)
-#define __NR_BSD43_vtimes		(__NR_BSD43 + 107)
-#define __NR_BSD43_sigvec		(__NR_BSD43 + 108)
-#define __NR_BSD43_sigblock		(__NR_BSD43 + 109)
-#define __NR_BSD43_sigsetmask		(__NR_BSD43 + 110)
-#define __NR_BSD43_sigpause		(__NR_BSD43 + 111)
-#define __NR_BSD43_sigstack		(__NR_BSD43 + 112)
-#define __NR_BSD43_oldrecvmsg		(__NR_BSD43 + 113)
-#define __NR_BSD43_oldsendmsg		(__NR_BSD43 + 114)
-#define __NR_BSD43_vtrace		(__NR_BSD43 + 115)
-#define __NR_BSD43_gettimeofday		(__NR_BSD43 + 116)
-#define __NR_BSD43_getrusage		(__NR_BSD43 + 117)
-#define __NR_BSD43_getsockopt		(__NR_BSD43 + 118)
-#define __NR_BSD43_reserved4		(__NR_BSD43 + 119)
-#define __NR_BSD43_readv		(__NR_BSD43 + 120)
-#define __NR_BSD43_writev		(__NR_BSD43 + 121)
-#define __NR_BSD43_settimeofday		(__NR_BSD43 + 122)
-#define __NR_BSD43_fchown		(__NR_BSD43 + 123)
-#define __NR_BSD43_fchmod		(__NR_BSD43 + 124)
-#define __NR_BSD43_oldrecvfrom		(__NR_BSD43 + 125)
-#define __NR_BSD43_setreuid		(__NR_BSD43 + 126)
-#define __NR_BSD43_setregid		(__NR_BSD43 + 127)
-#define __NR_BSD43_rename		(__NR_BSD43 + 128)
-#define __NR_BSD43_truncate		(__NR_BSD43 + 129)
-#define __NR_BSD43_ftruncate		(__NR_BSD43 + 130)
-#define __NR_BSD43_flock		(__NR_BSD43 + 131)
-#define __NR_BSD43_semsys		(__NR_BSD43 + 132)
-#define __NR_BSD43_sendto		(__NR_BSD43 + 133)
-#define __NR_BSD43_shutdown		(__NR_BSD43 + 134)
-#define __NR_BSD43_socketpair		(__NR_BSD43 + 135)
-#define __NR_BSD43_mkdir		(__NR_BSD43 + 136)
-#define __NR_BSD43_rmdir		(__NR_BSD43 + 137)
-#define __NR_BSD43_utimes		(__NR_BSD43 + 138)
-#define __NR_BSD43_sigcleanup		(__NR_BSD43 + 139)
-#define __NR_BSD43_adjtime		(__NR_BSD43 + 140)
-#define __NR_BSD43_oldgetpeername	(__NR_BSD43 + 141)
-#define __NR_BSD43_gethostid		(__NR_BSD43 + 142)
-#define __NR_BSD43_sethostid		(__NR_BSD43 + 143)
-#define __NR_BSD43_getrlimit		(__NR_BSD43 + 144)
-#define __NR_BSD43_setrlimit		(__NR_BSD43 + 145)
-#define __NR_BSD43_killpg		(__NR_BSD43 + 146)
-#define __NR_BSD43_shmsys		(__NR_BSD43 + 147)
-#define __NR_BSD43_quota		(__NR_BSD43 + 148)
-#define __NR_BSD43_qquota		(__NR_BSD43 + 149)
-#define __NR_BSD43_oldgetsockname	(__NR_BSD43 + 150)
-#define __NR_BSD43_sysmips		(__NR_BSD43 + 151)
-#define __NR_BSD43_cacheflush		(__NR_BSD43 + 152)
-#define __NR_BSD43_cachectl		(__NR_BSD43 + 153)
-#define __NR_BSD43_debug		(__NR_BSD43 + 154)
-#define __NR_BSD43_reserved5		(__NR_BSD43 + 155)
-#define __NR_BSD43_reserved6		(__NR_BSD43 + 156)
-#define __NR_BSD43_nfs_mount		(__NR_BSD43 + 157)
-#define __NR_BSD43_nfs_svc		(__NR_BSD43 + 158)
-#define __NR_BSD43_getdirentries	(__NR_BSD43 + 159)
-#define __NR_BSD43_statfs		(__NR_BSD43 + 160)
-#define __NR_BSD43_fstatfs		(__NR_BSD43 + 161)
-#define __NR_BSD43_unmount		(__NR_BSD43 + 162)
-#define __NR_BSD43_async_daemon		(__NR_BSD43 + 163)
-#define __NR_BSD43_nfs_getfh		(__NR_BSD43 + 164)
-#define __NR_BSD43_getdomainname	(__NR_BSD43 + 165)
-#define __NR_BSD43_setdomainname	(__NR_BSD43 + 166)
-#define __NR_BSD43_pcfs_mount		(__NR_BSD43 + 167)
-#define __NR_BSD43_quotactl		(__NR_BSD43 + 168)
-#define __NR_BSD43_oldexportfs		(__NR_BSD43 + 169)
-#define __NR_BSD43_smount		(__NR_BSD43 + 170)
-#define __NR_BSD43_mipshwconf		(__NR_BSD43 + 171)
-#define __NR_BSD43_exportfs		(__NR_BSD43 + 172)
-#define __NR_BSD43_nfsfh_open		(__NR_BSD43 + 173)
-#define __NR_BSD43_libattach		(__NR_BSD43 + 174)
-#define __NR_BSD43_libdetach		(__NR_BSD43 + 175)
-#define __NR_BSD43_accept		(__NR_BSD43 + 176)
-#define __NR_BSD43_reserved7		(__NR_BSD43 + 177)
-#define __NR_BSD43_reserved8		(__NR_BSD43 + 178)
-#define __NR_BSD43_recvmsg		(__NR_BSD43 + 179)
-#define __NR_BSD43_recvfrom		(__NR_BSD43 + 180)
-#define __NR_BSD43_sendmsg		(__NR_BSD43 + 181)
-#define __NR_BSD43_getpeername		(__NR_BSD43 + 182)
-#define __NR_BSD43_getsockname		(__NR_BSD43 + 183)
-#define __NR_BSD43_aread		(__NR_BSD43 + 184)
-#define __NR_BSD43_awrite		(__NR_BSD43 + 185)
-#define __NR_BSD43_listio		(__NR_BSD43 + 186)
-#define __NR_BSD43_acancel		(__NR_BSD43 + 187)
-#define __NR_BSD43_astatus		(__NR_BSD43 + 188)
-#define __NR_BSD43_await		(__NR_BSD43 + 189)
-#define __NR_BSD43_areadv		(__NR_BSD43 + 190)
-#define __NR_BSD43_awritev		(__NR_BSD43 + 191)
-
-/*
- * POSIX syscalls are in the range from 3000 to 3999
- */
-#define __NR_POSIX			3000
-#define __NR_POSIX_syscall		(__NR_POSIX +   0)
-#define __NR_POSIX_exit			(__NR_POSIX +   1)
-#define __NR_POSIX_fork			(__NR_POSIX +   2)
-#define __NR_POSIX_read			(__NR_POSIX +   3)
-#define __NR_POSIX_write		(__NR_POSIX +   4)
-#define __NR_POSIX_open			(__NR_POSIX +   5)
-#define __NR_POSIX_close		(__NR_POSIX +   6)
-#define __NR_POSIX_wait			(__NR_POSIX +   7)
-#define __NR_POSIX_creat		(__NR_POSIX +   8)
-#define __NR_POSIX_link			(__NR_POSIX +   9)
-#define __NR_POSIX_unlink		(__NR_POSIX +  10)
-#define __NR_POSIX_exec			(__NR_POSIX +  11)
-#define __NR_POSIX_chdir		(__NR_POSIX +  12)
-#define __NR_POSIX_gtime		(__NR_POSIX +  13)
-#define __NR_POSIX_mknod		(__NR_POSIX +  14)
-#define __NR_POSIX_chmod		(__NR_POSIX +  15)
-#define __NR_POSIX_chown		(__NR_POSIX +  16)
-#define __NR_POSIX_sbreak		(__NR_POSIX +  17)
-#define __NR_POSIX_stat			(__NR_POSIX +  18)
-#define __NR_POSIX_lseek		(__NR_POSIX +  19)
-#define __NR_POSIX_getpid		(__NR_POSIX +  20)
-#define __NR_POSIX_mount		(__NR_POSIX +  21)
-#define __NR_POSIX_umount		(__NR_POSIX +  22)
-#define __NR_POSIX_setuid		(__NR_POSIX +  23)
-#define __NR_POSIX_getuid		(__NR_POSIX +  24)
-#define __NR_POSIX_stime		(__NR_POSIX +  25)
-#define __NR_POSIX_ptrace		(__NR_POSIX +  26)
-#define __NR_POSIX_alarm		(__NR_POSIX +  27)
-#define __NR_POSIX_fstat		(__NR_POSIX +  28)
-#define __NR_POSIX_pause		(__NR_POSIX +  29)
-#define __NR_POSIX_utime		(__NR_POSIX +  30)
-#define __NR_POSIX_stty			(__NR_POSIX +  31)
-#define __NR_POSIX_gtty			(__NR_POSIX +  32)
-#define __NR_POSIX_access		(__NR_POSIX +  33)
-#define __NR_POSIX_nice			(__NR_POSIX +  34)
-#define __NR_POSIX_statfs		(__NR_POSIX +  35)
-#define __NR_POSIX_sync			(__NR_POSIX +  36)
-#define __NR_POSIX_kill			(__NR_POSIX +  37)
-#define __NR_POSIX_fstatfs		(__NR_POSIX +  38)
-#define __NR_POSIX_getpgrp		(__NR_POSIX +  39)
-#define __NR_POSIX_syssgi		(__NR_POSIX +  40)
-#define __NR_POSIX_dup			(__NR_POSIX +  41)
-#define __NR_POSIX_pipe			(__NR_POSIX +  42)
-#define __NR_POSIX_times		(__NR_POSIX +  43)
-#define __NR_POSIX_profil		(__NR_POSIX +  44)
-#define __NR_POSIX_lock			(__NR_POSIX +  45)
-#define __NR_POSIX_setgid		(__NR_POSIX +  46)
-#define __NR_POSIX_getgid		(__NR_POSIX +  47)
-#define __NR_POSIX_sig			(__NR_POSIX +  48)
-#define __NR_POSIX_msgsys		(__NR_POSIX +  49)
-#define __NR_POSIX_sysmips		(__NR_POSIX +  50)
-#define __NR_POSIX_sysacct		(__NR_POSIX +  51)
-#define __NR_POSIX_shmsys		(__NR_POSIX +  52)
-#define __NR_POSIX_semsys		(__NR_POSIX +  53)
-#define __NR_POSIX_ioctl		(__NR_POSIX +  54)
-#define __NR_POSIX_uadmin		(__NR_POSIX +  55)
-#define __NR_POSIX_exch			(__NR_POSIX +  56)
-#define __NR_POSIX_utssys		(__NR_POSIX +  57)
-#define __NR_POSIX_USG_reserved1	(__NR_POSIX +  58)
-#define __NR_POSIX_exece		(__NR_POSIX +  59)
-#define __NR_POSIX_umask		(__NR_POSIX +  60)
-#define __NR_POSIX_chroot		(__NR_POSIX +  61)
-#define __NR_POSIX_fcntl		(__NR_POSIX +  62)
-#define __NR_POSIX_ulimit		(__NR_POSIX +  63)
-#define __NR_POSIX_SAFARI4_reserved1	(__NR_POSIX +  64)
-#define __NR_POSIX_SAFARI4_reserved2	(__NR_POSIX +  65)
-#define __NR_POSIX_SAFARI4_reserved3	(__NR_POSIX +  66)
-#define __NR_POSIX_SAFARI4_reserved4	(__NR_POSIX +  67)
-#define __NR_POSIX_SAFARI4_reserved5	(__NR_POSIX +  68)
-#define __NR_POSIX_SAFARI4_reserved6	(__NR_POSIX +  69)
-#define __NR_POSIX_advfs		(__NR_POSIX +  70)
-#define __NR_POSIX_unadvfs		(__NR_POSIX +  71)
-#define __NR_POSIX_rmount		(__NR_POSIX +  72)
-#define __NR_POSIX_rumount		(__NR_POSIX +  73)
-#define __NR_POSIX_rfstart		(__NR_POSIX +  74)
-#define __NR_POSIX_reserved1		(__NR_POSIX +  75)
-#define __NR_POSIX_rdebug		(__NR_POSIX +  76)
-#define __NR_POSIX_rfstop		(__NR_POSIX +  77)
-#define __NR_POSIX_rfsys		(__NR_POSIX +  78)
-#define __NR_POSIX_rmdir		(__NR_POSIX +  79)
-#define __NR_POSIX_mkdir		(__NR_POSIX +  80)
-#define __NR_POSIX_getdents		(__NR_POSIX +  81)
-#define __NR_POSIX_sginap		(__NR_POSIX +  82)
-#define __NR_POSIX_sgikopt		(__NR_POSIX +  83)
-#define __NR_POSIX_sysfs		(__NR_POSIX +  84)
-#define __NR_POSIX_getmsg		(__NR_POSIX +  85)
-#define __NR_POSIX_putmsg		(__NR_POSIX +  86)
-#define __NR_POSIX_poll			(__NR_POSIX +  87)
-#define __NR_POSIX_sigreturn		(__NR_POSIX +  88)
-#define __NR_POSIX_accept		(__NR_POSIX +  89)
-#define __NR_POSIX_bind			(__NR_POSIX +  90)
-#define __NR_POSIX_connect		(__NR_POSIX +  91)
-#define __NR_POSIX_gethostid		(__NR_POSIX +  92)
-#define __NR_POSIX_getpeername		(__NR_POSIX +  93)
-#define __NR_POSIX_getsockname		(__NR_POSIX +  94)
-#define __NR_POSIX_getsockopt		(__NR_POSIX +  95)
-#define __NR_POSIX_listen		(__NR_POSIX +  96)
-#define __NR_POSIX_recv			(__NR_POSIX +  97)
-#define __NR_POSIX_recvfrom		(__NR_POSIX +  98)
-#define __NR_POSIX_recvmsg		(__NR_POSIX +  99)
-#define __NR_POSIX_select		(__NR_POSIX + 100)
-#define __NR_POSIX_send			(__NR_POSIX + 101)
-#define __NR_POSIX_sendmsg		(__NR_POSIX + 102)
-#define __NR_POSIX_sendto		(__NR_POSIX + 103)
-#define __NR_POSIX_sethostid		(__NR_POSIX + 104)
-#define __NR_POSIX_setsockopt		(__NR_POSIX + 105)
-#define __NR_POSIX_shutdown		(__NR_POSIX + 106)
-#define __NR_POSIX_socket		(__NR_POSIX + 107)
-#define __NR_POSIX_gethostname		(__NR_POSIX + 108)
-#define __NR_POSIX_sethostname		(__NR_POSIX + 109)
-#define __NR_POSIX_getdomainname	(__NR_POSIX + 110)
-#define __NR_POSIX_setdomainname	(__NR_POSIX + 111)
-#define __NR_POSIX_truncate		(__NR_POSIX + 112)
-#define __NR_POSIX_ftruncate		(__NR_POSIX + 113)
-#define __NR_POSIX_rename		(__NR_POSIX + 114)
-#define __NR_POSIX_symlink		(__NR_POSIX + 115)
-#define __NR_POSIX_readlink		(__NR_POSIX + 116)
-#define __NR_POSIX_lstat		(__NR_POSIX + 117)
-#define __NR_POSIX_nfs_mount		(__NR_POSIX + 118)
-#define __NR_POSIX_nfs_svc		(__NR_POSIX + 119)
-#define __NR_POSIX_nfs_getfh		(__NR_POSIX + 120)
-#define __NR_POSIX_async_daemon		(__NR_POSIX + 121)
-#define __NR_POSIX_exportfs		(__NR_POSIX + 122)
-#define __NR_POSIX_SGI_setregid		(__NR_POSIX + 123)
-#define __NR_POSIX_SGI_setreuid		(__NR_POSIX + 124)
-#define __NR_POSIX_getitimer		(__NR_POSIX + 125)
-#define __NR_POSIX_setitimer		(__NR_POSIX + 126)
-#define __NR_POSIX_adjtime		(__NR_POSIX + 127)
-#define __NR_POSIX_SGI_bsdgettime	(__NR_POSIX + 128)
-#define __NR_POSIX_SGI_sproc		(__NR_POSIX + 129)
-#define __NR_POSIX_SGI_prctl		(__NR_POSIX + 130)
-#define __NR_POSIX_SGI_blkproc		(__NR_POSIX + 131)
-#define __NR_POSIX_SGI_reserved1	(__NR_POSIX + 132)
-#define __NR_POSIX_SGI_sgigsc		(__NR_POSIX + 133)
-#define __NR_POSIX_SGI_mmap		(__NR_POSIX + 134)
-#define __NR_POSIX_SGI_munmap		(__NR_POSIX + 135)
-#define __NR_POSIX_SGI_mprotect		(__NR_POSIX + 136)
-#define __NR_POSIX_SGI_msync		(__NR_POSIX + 137)
-#define __NR_POSIX_SGI_madvise		(__NR_POSIX + 138)
-#define __NR_POSIX_SGI_mpin		(__NR_POSIX + 139)
-#define __NR_POSIX_SGI_getpagesize	(__NR_POSIX + 140)
-#define __NR_POSIX_SGI_libattach	(__NR_POSIX + 141)
-#define __NR_POSIX_SGI_libdetach	(__NR_POSIX + 142)
-#define __NR_POSIX_SGI_getpgrp		(__NR_POSIX + 143)
-#define __NR_POSIX_SGI_setpgrp		(__NR_POSIX + 144)
-#define __NR_POSIX_SGI_reserved2	(__NR_POSIX + 145)
-#define __NR_POSIX_SGI_reserved3	(__NR_POSIX + 146)
-#define __NR_POSIX_SGI_reserved4	(__NR_POSIX + 147)
-#define __NR_POSIX_SGI_reserved5	(__NR_POSIX + 148)
-#define __NR_POSIX_SGI_reserved6	(__NR_POSIX + 149)
-#define __NR_POSIX_cacheflush		(__NR_POSIX + 150)
-#define __NR_POSIX_cachectl		(__NR_POSIX + 151)
-#define __NR_POSIX_fchown		(__NR_POSIX + 152)
-#define __NR_POSIX_fchmod		(__NR_POSIX + 153)
-#define __NR_POSIX_wait3		(__NR_POSIX + 154)
-#define __NR_POSIX_mmap			(__NR_POSIX + 155)
-#define __NR_POSIX_munmap		(__NR_POSIX + 156)
-#define __NR_POSIX_madvise		(__NR_POSIX + 157)
-#define __NR_POSIX_BSD_getpagesize	(__NR_POSIX + 158)
-#define __NR_POSIX_setreuid		(__NR_POSIX + 159)
-#define __NR_POSIX_setregid		(__NR_POSIX + 160)
-#define __NR_POSIX_setpgid		(__NR_POSIX + 161)
-#define __NR_POSIX_getgroups		(__NR_POSIX + 162)
-#define __NR_POSIX_setgroups		(__NR_POSIX + 163)
-#define __NR_POSIX_gettimeofday		(__NR_POSIX + 164)
-#define __NR_POSIX_getrusage		(__NR_POSIX + 165)
-#define __NR_POSIX_getrlimit		(__NR_POSIX + 166)
-#define __NR_POSIX_setrlimit		(__NR_POSIX + 167)
-#define __NR_POSIX_waitpid		(__NR_POSIX + 168)
-#define __NR_POSIX_dup2			(__NR_POSIX + 169)
-#define __NR_POSIX_reserved2		(__NR_POSIX + 170)
-#define __NR_POSIX_reserved3		(__NR_POSIX + 171)
-#define __NR_POSIX_reserved4		(__NR_POSIX + 172)
-#define __NR_POSIX_reserved5		(__NR_POSIX + 173)
-#define __NR_POSIX_reserved6		(__NR_POSIX + 174)
-#define __NR_POSIX_reserved7		(__NR_POSIX + 175)
-#define __NR_POSIX_reserved8		(__NR_POSIX + 176)
-#define __NR_POSIX_reserved9		(__NR_POSIX + 177)
-#define __NR_POSIX_reserved10		(__NR_POSIX + 178)
-#define __NR_POSIX_reserved11		(__NR_POSIX + 179)
-#define __NR_POSIX_reserved12		(__NR_POSIX + 180)
-#define __NR_POSIX_reserved13		(__NR_POSIX + 181)
-#define __NR_POSIX_reserved14		(__NR_POSIX + 182)
-#define __NR_POSIX_reserved15		(__NR_POSIX + 183)
-#define __NR_POSIX_reserved16		(__NR_POSIX + 184)
-#define __NR_POSIX_reserved17		(__NR_POSIX + 185)
-#define __NR_POSIX_reserved18		(__NR_POSIX + 186)
-#define __NR_POSIX_reserved19		(__NR_POSIX + 187)
-#define __NR_POSIX_reserved20		(__NR_POSIX + 188)
-#define __NR_POSIX_reserved21		(__NR_POSIX + 189)
-#define __NR_POSIX_reserved22		(__NR_POSIX + 190)
-#define __NR_POSIX_reserved23		(__NR_POSIX + 191)
-#define __NR_POSIX_reserved24		(__NR_POSIX + 192)
-#define __NR_POSIX_reserved25		(__NR_POSIX + 193)
-#define __NR_POSIX_reserved26		(__NR_POSIX + 194)
-#define __NR_POSIX_reserved27		(__NR_POSIX + 195)
-#define __NR_POSIX_reserved28		(__NR_POSIX + 196)
-#define __NR_POSIX_reserved29		(__NR_POSIX + 197)
-#define __NR_POSIX_reserved30		(__NR_POSIX + 198)
-#define __NR_POSIX_reserved31		(__NR_POSIX + 199)
-#define __NR_POSIX_reserved32		(__NR_POSIX + 200)
-#define __NR_POSIX_reserved33		(__NR_POSIX + 201)
-#define __NR_POSIX_reserved34		(__NR_POSIX + 202)
-#define __NR_POSIX_reserved35		(__NR_POSIX + 203)
-#define __NR_POSIX_reserved36		(__NR_POSIX + 204)
-#define __NR_POSIX_reserved37		(__NR_POSIX + 205)
-#define __NR_POSIX_reserved38		(__NR_POSIX + 206)
-#define __NR_POSIX_reserved39		(__NR_POSIX + 207)
-#define __NR_POSIX_reserved40		(__NR_POSIX + 208)
-#define __NR_POSIX_reserved41		(__NR_POSIX + 209)
-#define __NR_POSIX_reserved42		(__NR_POSIX + 210)
-#define __NR_POSIX_reserved43		(__NR_POSIX + 211)
-#define __NR_POSIX_reserved44		(__NR_POSIX + 212)
-#define __NR_POSIX_reserved45		(__NR_POSIX + 213)
-#define __NR_POSIX_reserved46		(__NR_POSIX + 214)
-#define __NR_POSIX_reserved47		(__NR_POSIX + 215)
-#define __NR_POSIX_reserved48		(__NR_POSIX + 216)
-#define __NR_POSIX_reserved49		(__NR_POSIX + 217)
-#define __NR_POSIX_reserved50		(__NR_POSIX + 218)
-#define __NR_POSIX_reserved51		(__NR_POSIX + 219)
-#define __NR_POSIX_reserved52		(__NR_POSIX + 220)
-#define __NR_POSIX_reserved53		(__NR_POSIX + 221)
-#define __NR_POSIX_reserved54		(__NR_POSIX + 222)
-#define __NR_POSIX_reserved55		(__NR_POSIX + 223)
-#define __NR_POSIX_reserved56		(__NR_POSIX + 224)
-#define __NR_POSIX_reserved57		(__NR_POSIX + 225)
-#define __NR_POSIX_reserved58		(__NR_POSIX + 226)
-#define __NR_POSIX_reserved59		(__NR_POSIX + 227)
-#define __NR_POSIX_reserved60		(__NR_POSIX + 228)
-#define __NR_POSIX_reserved61		(__NR_POSIX + 229)
-#define __NR_POSIX_reserved62		(__NR_POSIX + 230)
-#define __NR_POSIX_reserved63		(__NR_POSIX + 231)
-#define __NR_POSIX_reserved64		(__NR_POSIX + 232)
-#define __NR_POSIX_reserved65		(__NR_POSIX + 233)
-#define __NR_POSIX_reserved66		(__NR_POSIX + 234)
-#define __NR_POSIX_reserved67		(__NR_POSIX + 235)
-#define __NR_POSIX_reserved68		(__NR_POSIX + 236)
-#define __NR_POSIX_reserved69		(__NR_POSIX + 237)
-#define __NR_POSIX_reserved70		(__NR_POSIX + 238)
-#define __NR_POSIX_reserved71		(__NR_POSIX + 239)
-#define __NR_POSIX_reserved72		(__NR_POSIX + 240)
-#define __NR_POSIX_reserved73		(__NR_POSIX + 241)
-#define __NR_POSIX_reserved74		(__NR_POSIX + 242)
-#define __NR_POSIX_reserved75		(__NR_POSIX + 243)
-#define __NR_POSIX_reserved76		(__NR_POSIX + 244)
-#define __NR_POSIX_reserved77		(__NR_POSIX + 245)
-#define __NR_POSIX_reserved78		(__NR_POSIX + 246)
-#define __NR_POSIX_reserved79		(__NR_POSIX + 247)
-#define __NR_POSIX_reserved80		(__NR_POSIX + 248)
-#define __NR_POSIX_reserved81		(__NR_POSIX + 249)
-#define __NR_POSIX_reserved82		(__NR_POSIX + 250)
-#define __NR_POSIX_reserved83		(__NR_POSIX + 251)
-#define __NR_POSIX_reserved84		(__NR_POSIX + 252)
-#define __NR_POSIX_reserved85		(__NR_POSIX + 253)
-#define __NR_POSIX_reserved86		(__NR_POSIX + 254)
-#define __NR_POSIX_reserved87		(__NR_POSIX + 255)
-#define __NR_POSIX_reserved88		(__NR_POSIX + 256)
-#define __NR_POSIX_reserved89		(__NR_POSIX + 257)
-#define __NR_POSIX_reserved90		(__NR_POSIX + 258)
-#define __NR_POSIX_reserved91		(__NR_POSIX + 259)
-#define __NR_POSIX_netboot		(__NR_POSIX + 260)
-#define __NR_POSIX_netunboot		(__NR_POSIX + 261)
-#define __NR_POSIX_rdump		(__NR_POSIX + 262)
-#define __NR_POSIX_setsid		(__NR_POSIX + 263)
-#define __NR_POSIX_getmaxsig		(__NR_POSIX + 264)
-#define __NR_POSIX_sigpending		(__NR_POSIX + 265)
-#define __NR_POSIX_sigprocmask		(__NR_POSIX + 266)
-#define __NR_POSIX_sigsuspend		(__NR_POSIX + 267)
-#define __NR_POSIX_sigaction		(__NR_POSIX + 268)
-#define __NR_POSIX_MIPS_reserved1	(__NR_POSIX + 269)
-#define __NR_POSIX_MIPS_reserved2	(__NR_POSIX + 270)
-#define __NR_POSIX_MIPS_reserved3	(__NR_POSIX + 271)
-#define __NR_POSIX_MIPS_reserved4	(__NR_POSIX + 272)
-#define __NR_POSIX_MIPS_reserved5	(__NR_POSIX + 273)
-#define __NR_POSIX_MIPS_reserved6	(__NR_POSIX + 274)
-#define __NR_POSIX_MIPS_reserved7	(__NR_POSIX + 275)
-#define __NR_POSIX_MIPS_reserved8	(__NR_POSIX + 276)
-#define __NR_POSIX_MIPS_reserved9	(__NR_POSIX + 277)
-#define __NR_POSIX_MIPS_reserved10	(__NR_POSIX + 278)
-#define __NR_POSIX_MIPS_reserved11	(__NR_POSIX + 279)
-#define __NR_POSIX_TANDEM_reserved1	(__NR_POSIX + 280)
-#define __NR_POSIX_TANDEM_reserved2	(__NR_POSIX + 281)
-#define __NR_POSIX_TANDEM_reserved3	(__NR_POSIX + 282)
-#define __NR_POSIX_TANDEM_reserved4	(__NR_POSIX + 283)
-#define __NR_POSIX_TANDEM_reserved5	(__NR_POSIX + 284)
-#define __NR_POSIX_TANDEM_reserved6	(__NR_POSIX + 285)
-#define __NR_POSIX_TANDEM_reserved7	(__NR_POSIX + 286)
-#define __NR_POSIX_TANDEM_reserved8	(__NR_POSIX + 287)
-#define __NR_POSIX_TANDEM_reserved9	(__NR_POSIX + 288)
-#define __NR_POSIX_TANDEM_reserved10	(__NR_POSIX + 289)
-#define __NR_POSIX_TANDEM_reserved11	(__NR_POSIX + 290)
-#define __NR_POSIX_TANDEM_reserved12	(__NR_POSIX + 291)
-#define __NR_POSIX_TANDEM_reserved13	(__NR_POSIX + 292)
-#define __NR_POSIX_TANDEM_reserved14	(__NR_POSIX + 293)
-#define __NR_POSIX_TANDEM_reserved15	(__NR_POSIX + 294)
-#define __NR_POSIX_TANDEM_reserved16	(__NR_POSIX + 295)
-#define __NR_POSIX_TANDEM_reserved17	(__NR_POSIX + 296)
-#define __NR_POSIX_TANDEM_reserved18	(__NR_POSIX + 297)
-#define __NR_POSIX_TANDEM_reserved19	(__NR_POSIX + 298)
-#define __NR_POSIX_TANDEM_reserved20	(__NR_POSIX + 299)
-#define __NR_POSIX_SGI_reserved7	(__NR_POSIX + 300)
-#define __NR_POSIX_SGI_reserved8	(__NR_POSIX + 301)
-#define __NR_POSIX_SGI_reserved9	(__NR_POSIX + 302)
-#define __NR_POSIX_SGI_reserved10	(__NR_POSIX + 303)
-#define __NR_POSIX_SGI_reserved11	(__NR_POSIX + 304)
-#define __NR_POSIX_SGI_reserved12	(__NR_POSIX + 305)
-#define __NR_POSIX_SGI_reserved13	(__NR_POSIX + 306)
-#define __NR_POSIX_SGI_reserved14	(__NR_POSIX + 307)
-#define __NR_POSIX_SGI_reserved15	(__NR_POSIX + 308)
-#define __NR_POSIX_SGI_reserved16	(__NR_POSIX + 309)
-#define __NR_POSIX_SGI_reserved17	(__NR_POSIX + 310)
-#define __NR_POSIX_SGI_reserved18	(__NR_POSIX + 311)
-#define __NR_POSIX_SGI_reserved19	(__NR_POSIX + 312)
-#define __NR_POSIX_SGI_reserved20	(__NR_POSIX + 313)
-#define __NR_POSIX_SGI_reserved21	(__NR_POSIX + 314)
-#define __NR_POSIX_SGI_reserved22	(__NR_POSIX + 315)
-#define __NR_POSIX_SGI_reserved23	(__NR_POSIX + 316)
-#define __NR_POSIX_SGI_reserved24	(__NR_POSIX + 317)
-#define __NR_POSIX_SGI_reserved25	(__NR_POSIX + 318)
-#define __NR_POSIX_SGI_reserved26	(__NR_POSIX + 319)
-
-/*
- * Linux syscalls are in the range from 4000 to 4999
- * Hopefully these syscall numbers are unused ...  If not everyone using
- * statically linked binaries is pretty upsh*t.  You've been warned.
- */
 #define __NR_Linux			4000
 #define __NR_syscall			(__NR_Linux +   0)
 #define __NR_exit			(__NR_Linux +   1)
@@ -1045,7 +71,7 @@
 #define __NR_mpx			(__NR_Linux +  56)
 #define __NR_setpgid			(__NR_Linux +  57)
 #define __NR_ulimit			(__NR_Linux +  58)
-#define __NR_oldolduname		(__NR_Linux +  59)
+#define __NR_unused59			(__NR_Linux +  59)
 #define __NR_umask			(__NR_Linux +  60)
 #define __NR_chroot			(__NR_Linux +  61)
 #define __NR_ustat			(__NR_Linux +  62)
@@ -1095,7 +121,7 @@
 #define __NR_stat			(__NR_Linux + 106)
 #define __NR_lstat			(__NR_Linux + 107)
 #define __NR_fstat			(__NR_Linux + 108)
-#define __NR_olduname			(__NR_Linux + 109)
+#define __NR_unused109			(__NR_Linux + 109)
 #define __NR_iopl			(__NR_Linux + 110)
 #define __NR_vhangup			(__NR_Linux + 111)
 #define __NR_idle			(__NR_Linux + 112)
@@ -1206,11 +232,12 @@
 #define __NR_mincore			(__NR_Linux + 217)
 #define __NR_madvise			(__NR_Linux + 218)
 #define __NR_getdents64			(__NR_Linux + 219)
+#define __NR_fcntl64			(__NR_Linux + 220)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		219
+#define __NR_Linux_syscalls		220
 
 #ifndef _LANGUAGE_ASSEMBLY
 
@@ -1218,13 +245,15 @@
 #define _syscall0(type,name) \
 type name(void) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("li\t$2,%2\n\t" \
-		  "syscall" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name) \
-                  : "$8","$9","$10","$11","$12","$13","$14","$15","$24"); \
+                  : "$2","$7","$8","$9","$10","$11","$12","$13","$14","$15", \
+		    "$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1238,14 +267,15 @@
 #define _syscall1(type,name,atype,a) \
 type name(atype a) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall" \
-                  : "=r" (__res), "=r" (__err) \
-                  : "i" (__NR_##name),"r" ((long)(a)) \
-                  : "$4","$8","$9","$10","$11","$12","$13","$14","$15","$24"); \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7" \
+		  : "=r" (__res), "=r" (__err) \
+		  : "i" (__NR_##name),"r" ((long)(a)) \
+		  : "$2","$4","$7","$8","$9","$10","$11","$12","$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1255,17 +285,18 @@
 #define _syscall2(type,name,atype,a,btype,b) \
 type name(atype a,btype b) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)) \
-                  : "$4","$5","$8","$9","$10","$11","$12","$13","$14","$15", \
-                    "$24"); \
+                  : "$2","$4","$5","$7","$8","$9","$10","$11","$12","$13", \
+		    "$14","$15", "$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1275,19 +306,20 @@
 #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
 type name (atype a, btype b, ctype c) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
                   "move\t$6,%5\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)) \
-                  : "$4","$5","$6","$8","$9","$10","$11","$12","$13","$14", \
-                    "$15","$24"); \
+                  : "$2","$4","$5","$6","$7","$8","$9","$10","$11","$12", \
+		    "$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1297,21 +329,22 @@
 #define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \
 type name (atype a, btype b, ctype c, dtype d) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
                   "move\t$6,%5\n\t" \
                   "move\t$7,%6\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)) \
-                  : "$4","$5","$6","$8","$9","$10","$11","$12","$13","$14", \
-                    "$15","$24"); \
+                  : "$2","$4","$5","$6","$7","$8","$9","$10","$11","$12", \
+		    "$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1321,8 +354,7 @@
 #define _syscall5(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e) \
 type name (atype a,btype b,ctype c,dtype d,etype e) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
                   "move\t$6,%5\n\t" \
@@ -1331,7 +363,9 @@
 		  "subu\t$29,24\n\t" \
 		  "sw\t$2,16($29)\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall\n\t" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7\n\t" \
 		  "addiu\t$29,24" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
@@ -1350,8 +384,7 @@
 #define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
 type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
                   "move\t$6,%5\n\t" \
@@ -1362,7 +395,9 @@
 		  "sw\t$2,16($29)\n\t" \
 		  "sw\t$3,20($29)\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall\n\t" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7\n\t" \
 		  "addiu\t$29,24" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
@@ -1382,8 +417,7 @@
 #define _syscall7(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f,gtype,g) \
 type name (atype a,btype b,ctype c,dtype d,etype e,ftype f,gtype g) \
 { \
-register long __res __asm__ ("$2"); \
-register long __err __asm__ ("$7"); \
+long __res, __err; \
 __asm__ volatile ("move\t$4,%3\n\t" \
                   "move\t$5,%4\n\t" \
                   "move\t$6,%5\n\t" \
@@ -1396,7 +430,9 @@
 		  "sw\t$3,20($29)\n\t" \
 		  "sw\t$2,24($29)\n\t" \
 		  "li\t$2,%2\n\t" \
-                  "syscall\n\t" \
+		  "syscall\n\t" \
+		  "move\t%0, $2\n\t" \
+		  "move\t%1, $7\n\t" \
 		  "addiu\t$29,32" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
@@ -1450,4 +486,4 @@
 #endif /* !defined (__KERNEL_SYSCALLS__) */
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
-#endif /* __ASM_MIPS_UNISTD_H */
+#endif /* _ASM_UNISTD_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/watch.h linux/include/asm-mips/watch.h
--- linux-2.4.6-pre8/include/asm-mips/watch.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/watch.h	Mon Dec  3 22:50:39 2001
@@ -1,10 +1,9 @@
-/* $Id: watch.h,v 1.3 1998/08/19 21:58:15 ralf Exp $
- *
+/*
  * 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) 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
  */
 #ifndef __ASM_WATCH_H
 #define __ASM_WATCH_H
@@ -35,4 +34,4 @@
 	if (watch_available)					\
 		__watch_reenable()
 
-#endif __ASM_WATCH_H
+#endif /* __ASM_WATCH_H */
diff -urN linux-2.4.6-pre8/include/asm-mips/wbflush.h linux/include/asm-mips/wbflush.h
--- linux-2.4.6-pre8/include/asm-mips/wbflush.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/wbflush.h	Mon Dec  3 22:50:39 2001
@@ -27,7 +27,7 @@
  * we don't need no stinkin' wbflush
  */
 
-#define wbflush()
+#define wbflush()  do { } while(0)
 
 #endif
 
diff -urN linux-2.4.6-pre8/include/asm-ppc/bootinfo.h linux/include/asm-ppc/bootinfo.h
--- linux-2.4.6-pre8/include/asm-ppc/bootinfo.h	Thu May 24 15:03:05 2001
+++ linux/include/asm-ppc/bootinfo.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.bootinfo.h 1.7 05/23/01 00:38:42 cort
+ * BK Id: SCCS/s.bootinfo.h 1.9 06/13/01 15:28:43 paulus
  */
 /*
  * Non-machine dependent bootinfo structure.  Basic idea
@@ -34,27 +34,6 @@
 
 #endif /* CONFIG_APUS */
 
-/*
- * 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 -urN linux-2.4.6-pre8/include/asm-ppc/highmem.h linux/include/asm-ppc/highmem.h
--- linux-2.4.6-pre8/include/asm-ppc/highmem.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/highmem.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.highmem.h 1.7 05/17/01 18:14:24 cort
+ * BK Id: SCCS/s.highmem.h 1.10 06/28/01 15:50:17 paulus
  */
 /*
  * highmem.h: virtual kernel memory mappings for high memory
@@ -94,7 +94,7 @@
 		BUG();
 #endif
 	set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
-	flush_hash_page(0, vaddr);
+	flush_tlb_page(0, vaddr);
 
 	return (void*) vaddr;
 }
@@ -116,7 +116,7 @@
 	 * this pte without first remap it
 	 */
 	pte_clear(kmap_pte+idx);
-	flush_hash_page(0, vaddr);
+	flush_tlb_page(0, vaddr);
 #endif
 }
 
diff -urN linux-2.4.6-pre8/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- linux-2.4.6-pre8/include/asm-ppc/machdep.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/machdep.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.machdep.h 1.11 05/17/01 18:14:25 cort
+ * BK Id: SCCS/s.machdep.h 1.14 06/28/01 16:13:50 paulus
  */
 #ifdef __KERNEL__
 #ifndef _PPC_MACHDEP_H
@@ -67,26 +67,19 @@
 	 * optional PCI "hooks"
 	 */
 
-	 	/* Called after scanning the bus, before allocating
-	 	 * resources
-	 	 */
+	/* Called after scanning the bus, before allocating resources */
 	void (*pcibios_fixup)(void);
 
-		/* Called for each PCI bus in the system
-		 * when it's probed
-		 */
+	/* Called for each PCI bus in the system when it's probed */
 	void (*pcibios_fixup_bus)(struct pci_bus *);
-	
-		/* Called when pci_enable_device() is called (initial=0) or
-		 * when a device with no assigned resource is found (initial=1).
-		 * Returns 0 to allow assignement/enabling of the device
-		 */
+
+	/* Called when pci_enable_device() is called (initial=0) or
+	 * when a device with no assigned resource is found (initial=1).
+	 * Returns 0 to allow assignment/enabling of the device. */
 	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
 
-		/* Called at then very end of pcibios_init()
-		 */
+	/* 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 -urN linux-2.4.6-pre8/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h
--- linux-2.4.6-pre8/include/asm-ppc/mmu.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/mmu.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.mmu.h 1.7 05/17/01 18:14:25 cort
+ * BK Id: SCCS/s.mmu.h 1.10 06/28/01 15:50:17 paulus
  */
 /*
  * PowerPC memory management structures
@@ -115,34 +115,6 @@
 	P601_BATL batl;		/* Lower register */
 } P601_BAT;
 
-/*
- * Simulated two-level MMU.  This structure is used by the kernel
- * to keep track of MMU mappings and is used to update/maintain
- * the hardware HASH table which is really a cache of mappings.
- *
- * The simulated structures mimic the hardware available on other
- * platforms, notably the 80x86 and 680x0.
- */
-
-typedef struct _pte {
-   	unsigned long page_num:20;
-   	unsigned long flags:12;		/* Page flags (some unused bits) */
-} pte;
-
-#define PD_SHIFT (10+12)		/* Page directory */
-#define PD_MASK  0x02FF
-#define PT_SHIFT (12)			/* Page Table */
-#define PT_MASK  0x02FF
-#define PG_SHIFT (12)			/* Page Entry */
- 
-
-/* MMU context */
-
-typedef struct _MMU_context {
-	SEGREG	segs[16];	/* Segment registers */
-	pte	**pmap;		/* Two-level page-map structure */
-} MMU_context;
-
 extern void _tlbie(unsigned long va);	/* invalidate a TLB entry */
 extern void _tlbia(void);		/* invalidate all TLB entries */
 
@@ -166,22 +138,6 @@
 #define BPP_XX	0x00		/* No access */
 #define BPP_RX	0x01		/* Read only */
 #define BPP_RW	0x02		/* Read/write */
-
-/* Used to set up SDR1 register */
-#define HASH_TABLE_SIZE_64K	0x00010000
-#define HASH_TABLE_SIZE_128K	0x00020000
-#define HASH_TABLE_SIZE_256K	0x00040000
-#define HASH_TABLE_SIZE_512K	0x00080000
-#define HASH_TABLE_SIZE_1M	0x00100000
-#define HASH_TABLE_SIZE_2M	0x00200000
-#define HASH_TABLE_SIZE_4M	0x00400000
-#define HASH_TABLE_MASK_64K	0x000   
-#define HASH_TABLE_MASK_128K	0x001   
-#define HASH_TABLE_MASK_256K	0x003   
-#define HASH_TABLE_MASK_512K	0x007
-#define HASH_TABLE_MASK_1M	0x00F   
-#define HASH_TABLE_MASK_2M	0x01F   
-#define HASH_TABLE_MASK_4M	0x03F   
 
 /* Control/status registers for the MPC8xx.
  * A write operation to these registers causes serialized access.
diff -urN linux-2.4.6-pre8/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- linux-2.4.6-pre8/include/asm-ppc/mmu_context.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/mmu_context.h	Mon Dec  3 22:50:39 2001
@@ -1,18 +1,40 @@
 /*
- * BK Id: SCCS/s.mmu_context.h 1.9 05/17/01 18:14:25 cort
+ * BK Id: SCCS/s.mmu_context.h 1.12 06/28/01 15:50:17 paulus
  */
-#include <linux/config.h>
-
 #ifdef __KERNEL__
 #ifndef __PPC_MMU_CONTEXT_H
 #define __PPC_MMU_CONTEXT_H
 
-/* the way contexts are handled on the ppc they are vsid's and
-   don't need any special treatment right now.
-   perhaps I can defer flushing the tlb by keeping a list of
-   zombie vsid/context's and handling that through destroy_context
-   later -- Cort
+#include <linux/config.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/mmu.h>
+
+/*
+ * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
+ * (virtual segment identifiers) for each context.  Although the
+ * hardware supports 24-bit VSIDs, and thus >1 million contexts,
+ * we only use 32,768 of them.  That is ample, since there can be
+ * at most around 30,000 tasks in the system anyway, and it means
+ * that we can use a bitmap to indicate which contexts are in use.
+ * Using a bitmap means that we entirely avoid all of the problems
+ * that we used to have when the context number overflowed,
+ * particularly on SMP systems.
+ *  -- paulus.
+ */
 
+/*
+ * This function defines the mapping from contexts to VSIDs (virtual
+ * segment IDs).  We use a skew on both the context and the high 4 bits
+ * of the 32-bit virtual address (the "effective segment ID") in order
+ * to spread out the entries in the MMU hash table.  Note, if this
+ * function is changed then arch/ppc/mm/hashtable.S will have to be
+ * changed correspondly.
+ */
+#define CTX_TO_VSID(ctx, va)	(((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
+				 & 0xffffff)
+
+/*
    The MPC8xx has only 16 contexts.  We rotate through them on each
    task switch.  A better way would be to keep track of tasks that
    own contexts, and implement an LRU usage.  That way very active
@@ -32,38 +54,22 @@
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
 {
 }
+
 #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
-
-/*
- * Allocating context numbers this way tends to spread out
- * the entries in the hash table better than a simple linear
- * allocation.
- */
-#define MUNGE_CONTEXT(n)        (((n) * 897) & LAST_CONTEXT)
+#define NO_CONTEXT      	((mm_context_t) -1)
+#define LAST_CONTEXT    	32767
 #endif
 
-extern atomic_t next_mmu_context;
-extern void mmu_context_overflow(void);
-
 /*
  * Set the current MMU context.
  * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by
@@ -73,19 +79,58 @@
  * and once I implement a real TLB context manager this will disappear.
  * The PGD is ignored on other processors. - Dan
  */
-extern void set_context(int context, void *pgd);
+extern void set_context(mm_context_t context);
 
 /*
- * Get a new mmu context for task tsk if necessary.
+ * Bitmap of contexts in use.
+ * The size of this bitmap is LAST_CONTEXT + 1 bits.
  */
-#define get_mmu_context(mm)					\
-do { 								\
-	if (mm->context == NO_CONTEXT) {			\
-		if (atomic_read(&next_mmu_context) == LAST_CONTEXT)		\
-			mmu_context_overflow();			\
-		mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));\
-	}							\
-} while (0)
+extern unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+
+/*
+ * This caches the next context number that we expect to be free.
+ * Its use is an optimization only, we can't rely on this context
+ * number to be free, but it usually will be.
+ */
+extern mm_context_t next_mmu_context;
+
+/*
+ * If we don't have sufficient contexts to give one to every task
+ * that could be in the system, we need to be able to steal contexts.
+ * These variables support that.
+ */
+#if LAST_CONTEXT < 30000
+#define FEW_CONTEXTS	1
+extern atomic_t nr_free_contexts;
+extern struct mm_struct *context_mm[LAST_CONTEXT+1];
+extern void steal_context(void);
+#endif
+
+/*
+ * Get a new mmu context for the address space described by `mm'.
+ */
+static inline void get_mmu_context(struct mm_struct *mm)
+{
+	mm_context_t ctx;
+
+	if (mm->context != NO_CONTEXT)
+		return;
+#ifdef FEW_CONTEXTS
+	while (atomic_dec_if_positive(&nr_free_contexts) < 0)
+		steal_context();
+#endif
+	ctx = next_mmu_context;
+	while (test_and_set_bit(ctx, context_map)) {
+		ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
+		if (ctx > LAST_CONTEXT)
+			ctx = 0;
+	}
+	next_mmu_context = (ctx + 1) & LAST_CONTEXT;
+	mm->context = ctx;
+#ifdef FEW_CONTEXTS
+	context_mm[ctx] = mm;
+#endif
+}
 
 /*
  * Set up the context for a new address space.
@@ -95,14 +140,23 @@
 /*
  * We're finished using the context for an address space.
  */
-#define destroy_context(mm)     do { } while (0)
+static inline void destroy_context(struct mm_struct *mm)
+{
+	if (mm->context != NO_CONTEXT) {
+		clear_bit(mm->context, context_map);
+		mm->context = NO_CONTEXT;
+#ifdef FEW_CONTEXTS
+		atomic_inc(&nr_free_contexts);
+#endif
+	}
+}
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk, int cpu)
 {
 	tsk->thread.pgdir = next->pgd;
 	get_mmu_context(next);
-	set_context(next->context, next->pgd);
+	set_context(next->context);
 }
 
 /*
@@ -113,16 +167,8 @@
 {
 	current->thread.pgdir = mm->pgd;
 	get_mmu_context(mm);
-	set_context(mm->context, mm->pgd);
+	set_context(mm->context);
 }
 
-/*
- * compute the vsid from the context and segment
- * segments > 7 are kernel segments and their
- * vsid is the segment -- Cort
- */
-#define	VSID_FROM_CONTEXT(segment,context) \
-   ((segment < 8) ? ((segment) | (context)<<4) : (segment))
-
-#endif
+#endif /* __PPC_MMU_CONTEXT_H */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.6-pre8/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- linux-2.4.6-pre8/include/asm-ppc/pgtable.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/pgtable.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pgtable.h 1.9 05/17/01 18:14:25 cort
+ * BK Id: SCCS/s.pgtable.h 1.12 06/28/01 15:50:17 paulus
  */
 #ifdef __KERNEL__
 #ifndef _PPC_PGTABLE_H
@@ -20,8 +20,8 @@
 extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
 				  unsigned long end);
-static inline void flush_hash_page(unsigned context, unsigned long va)
-	{ }
+#define update_mmu_cache(vma, addr, pte)	do { } while (0)
+
 #elif defined(CONFIG_8xx)
 #define __tlbia()	asm volatile ("tlbia" : : )
 
@@ -35,9 +35,9 @@
 static inline void local_flush_tlb_range(struct mm_struct *mm,
 				unsigned long start, unsigned long end)
 	{ __tlbia(); }
-static inline void flush_hash_page(unsigned context, unsigned long va)
-	{ }
-#else
+#define update_mmu_cache(vma, addr, pte)	do { } while (0)
+
+#else	/* 6xx, 7xx, 7xxx cpus */
 struct mm_struct;
 struct vm_area_struct;
 extern void local_flush_tlb_all(void);
@@ -45,6 +45,15 @@
 extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
 			    unsigned long end);
+
+/*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to put a corresponding HPTE into the hash table
+ * ahead of time, instead of waiting for the inevitable extra
+ * hash-table miss exception.
+ */
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
 #endif
 
 #define flush_tlb_all local_flush_tlb_all
@@ -52,16 +61,20 @@
 #define flush_tlb_page local_flush_tlb_page
 #define flush_tlb_range local_flush_tlb_range
 
+/*
+ * This is called in munmap when we have freed up some page-table
+ * pages.  We don't need to do anything here, there's nothing special
+ * about our page-table pages.  -- paulus
+ */
 static inline void flush_tlb_pgtables(struct mm_struct *mm,
-				unsigned long start, unsigned long end)
+				      unsigned long start, unsigned long end)
 {
-	/* PPC has hw page tables. */
 }
 
 /*
  * No cache flushing is required when address mappings are
  * changed, because the caches on PowerPCs are physically
- * addressed.
+ * addressed.  -- paulus
  * Also, when SMP we use the coherency (M) bit of the
  * BATs and PTEs.  -- Cort
  */
@@ -88,12 +101,12 @@
  * the virtual to physical address mapping.
  *
  * We use the hash table as an extended TLB, i.e. a cache of currently
- * active mappings.  We maintain a two-level page table tree, much like
- * that used by the i386, for the sake of the Linux memory management code.
- * Low-level assembler code in head.S (procedure hash_page) is responsible
- * for extracting ptes from the tree and putting them into the hash table
- * when necessary, and updating the accessed and modified bits in the
- * page table tree.
+ * active mappings.  We maintain a two-level page table tree, much
+ * like that used by the i386, for the sake of the Linux memory
+ * management code.  Low-level assembler code in hashtable.S
+ * (procedure hash_page) is responsible for extracting ptes from the
+ * tree and putting them into the hash table when necessary, and
+ * updating the accessed and modified bits in the page table tree.
  */
 
 /*
@@ -189,12 +202,11 @@
 #define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
 #define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
 #define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
+#define _PAGE_EXEC	0x020	/* software: i-cache coherency required */
 #define	_PAGE_PRESENT	0x040	/* software: PTE contains a translation */
 #define _PAGE_DIRTY	0x100	/* C: page changed */
 #define	_PAGE_RW	0x200	/* Writes permitted */
 #define _PAGE_ACCESSED	0x400	/* R: page referenced */
-#define _PAGE_HWWRITE	0x800	/* software: _PAGE_RW & _PAGE_DIRTY */
-#define	_PAGE_SHARED	0
 
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
@@ -205,48 +217,62 @@
 /* These five software bits must be masked out when the entry is loaded
  * into the TLB.
  */
-#define _PAGE_DIRTY	0x0008	/* software: page changed */
+#define _PAGE_EXEC	0x0008	/* software: i-cache coherency required */
 #define _PAGE_GUARDED	0x0010	/* software: guarded access */
 #define _PAGE_WRITETHRU 0x0020	/* software: use writethrough cache */
 #define _PAGE_RW	0x0040	/* software: user write access allowed */
 #define _PAGE_ACCESSED	0x0080	/* software: page referenced */
 
-#define _PAGE_HWWRITE	0x0100	/* C: page changed (write protect) */
-#define _PAGE_USER	0x0800	/* One of the PP bits, the other must be 0 */
+#define _PAGE_DIRTY	0x0100	/* C: page changed (write protect) */
+#define _PAGE_USER	0x0800	/* One of the PP bits, the other is USER&~RW */
 
 #else /* CONFIG_6xx */
 /* Definitions for 60x, 740/750, etc. */
 #define _PAGE_PRESENT	0x001	/* software: pte contains a translation */
-#define _PAGE_USER	0x002	/* matches one of the PP bits */
-#define _PAGE_RW	0x004	/* software: user write access allowed */
-#define _PAGE_GUARDED	0x008
+#define _PAGE_HASHPTE	0x002	/* hash_page has made an HPTE for this pte */
+#define _PAGE_USER	0x004	/* usermode access allowed */
+#define _PAGE_GUARDED	0x008	/* G: prohibit speculative access */
 #define _PAGE_COHERENT	0x010	/* M: enforce memory coherence (SMP systems) */
 #define _PAGE_NO_CACHE	0x020	/* I: cache inhibit */
 #define _PAGE_WRITETHRU	0x040	/* W: cache write-through */
 #define _PAGE_DIRTY	0x080	/* C: page changed */
 #define _PAGE_ACCESSED	0x100	/* R: page referenced */
-#define _PAGE_HWWRITE	0x200	/* software: _PAGE_RW & _PAGE_DIRTY */
+#define _PAGE_EXEC	0x200	/* software: i-cache coherency required */
+#define _PAGE_RW	0x400	/* software: user write access allowed */
+#endif
+
+#ifndef _PAGE_HASHPTE
+#define _PAGE_HASHPTE	0
+#endif
+#ifndef _PAGE_SHARED
 #define _PAGE_SHARED	0
 #endif
 
 #define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
-#ifdef CONFIG_SMP
-#define _PAGE_BASE	_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT
-#else
+/*
+ * Note: the _PAGE_COHERENT bit automatically gets set in the hardware
+ * PTE if CONFIG_SMP is defined (hash_page does this); there is no need
+ * to have it in the Linux PTE, and in fact the bit could be reused for
+ * another purpose.  -- paulus.
+ */
 #define _PAGE_BASE	_PAGE_PRESENT | _PAGE_ACCESSED
-#endif
-#define _PAGE_WRENABLE	_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE
+#define _PAGE_WRENABLE	_PAGE_RW | _PAGE_DIRTY
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define _PAGE_KERNEL	_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED
+#define _PAGE_IO	_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED
 
-#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | \
-				 _PAGE_SHARED)
-#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_NONE	__pgprot(_PAGE_BASE)
 #define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED)
-#define PAGE_KERNEL_CI	__pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | \
-				 _PAGE_NO_CACHE )
+#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
+#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+
+#define PAGE_KERNEL	__pgprot(_PAGE_KERNEL)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_SHARED)
+#define PAGE_KERNEL_CI	__pgprot(_PAGE_IO)
 
 /*
  * The PowerPC can only do execute protection on a segment (256MB) basis,
@@ -255,22 +281,22 @@
  * This is the closest we can get..
  */
 #define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
+#define __P001	PAGE_READONLY_X
 #define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
+#define __P011	PAGE_COPY_X
 #define __P100	PAGE_READONLY
-#define __P101	PAGE_READONLY
+#define __P101	PAGE_READONLY_X
 #define __P110	PAGE_COPY
-#define __P111	PAGE_COPY
+#define __P111	PAGE_COPY_X
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
+#define __S001	PAGE_READONLY_X
 #define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
+#define __S011	PAGE_SHARED_X
 #define __S100	PAGE_READONLY
-#define __S101	PAGE_READONLY
+#define __S101	PAGE_READONLY_X
 #define __S110	PAGE_SHARED
-#define __S111	PAGE_SHARED
+#define __S111	PAGE_SHARED_X
 
 #ifndef __ASSEMBLY__
 /*
@@ -280,33 +306,11 @@
 extern unsigned long empty_zero_page[1024];
 #define ZERO_PAGE(vaddr) (virt_to_page(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()
 #endif /* __ASSEMBLY__ */
 
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR	(8*sizeof(unsigned long))
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK	(~(sizeof(void*)-1))
-
-/* sizeof(void*) == 1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware!  SRB. */
-#define SIZEOF_PTR_LOG2	2
-
-#define pte_none(pte)		(!pte_val(pte))
+#define pte_none(pte)		((pte_val(pte) & ~_PAGE_HASHPTE) == 0)
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
-#define pte_clear(ptep)		do { pte_val(*(ptep)) = 0; } while (0)
+#define pte_clear(ptep)		do { set_pte((ptep), __pte(0)); } while (0)
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define	pmd_bad(pmd)		((pmd_val(pmd) & ~PAGE_MASK) != 0)
@@ -316,8 +320,7 @@
 /*
  * Permanent address of a page.
  */
-#define page_address(page)  ((page)->virtual)
-#define pages_to_mb(x)		((x) >> (20-PAGE_SHIFT))
+#define page_address(page)	((page)->virtual)
 #define pte_page(x)		(mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
 
 #ifndef __ASSEMBLY__
@@ -340,7 +343,7 @@
  */
 static inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
 static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
+static inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_EXEC; }
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
 
@@ -349,42 +352,26 @@
 
 static inline pte_t pte_rdprotect(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_USER; return pte; }
-static inline pte_t pte_exprotect(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_USER; return pte; }
 static inline pte_t pte_wrprotect(pte_t pte) {
-	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
+	pte_val(pte) &= ~_PAGE_RW; return pte; }
+static inline pte_t pte_exprotect(pte_t pte) {
+	pte_val(pte) &= ~_PAGE_EXEC; return pte; }
 static inline pte_t pte_mkclean(pte_t pte) {
-	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
+	pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkold(pte_t pte) {
 	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
 
 static inline pte_t pte_mkread(pte_t pte) {
 	pte_val(pte) |= _PAGE_USER; return pte; }
 static inline pte_t pte_mkexec(pte_t pte) {
-	pte_val(pte) |= _PAGE_USER; return pte; }
-static inline pte_t pte_mkwrite(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_RW;
-	if (pte_val(pte) & _PAGE_DIRTY)
-		pte_val(pte) |= _PAGE_HWWRITE;
-	return pte;
-}
-static inline pte_t pte_mkdirty(pte_t pte)
-{
-	pte_val(pte) |= _PAGE_DIRTY;
-	if (pte_val(pte) & _PAGE_RW)
-		pte_val(pte) |= _PAGE_HWWRITE;
-	return pte;
-}
+	pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) {
+	pte_val(pte) |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) {
+	pte_val(pte) |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte) {
 	pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval)	((*(pteptr)) = (pteval))
-
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
@@ -421,11 +408,11 @@
 {
 	unsigned long old, tmp;
 	
-	__asm__ __volatile__("\n\
-1:	lwarx	%0,0,%3 \n\
-	andc	%1,%0,%4 \n\
-	or	%1,%1,%5 \n\
-	stwcx.	%1,0,%3 \n\
+	__asm__ __volatile__("\
+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)
@@ -433,6 +420,12 @@
 	return old;
 }
 
+/*
+ * Writing a new value into the PTE doesn't disturb the state of the
+ * _PAGE_HASHPTE bit, on those machines which use an MMU hash table.
+ */
+extern void set_pte(pte_t *ptep, pte_t pte);
+
 static inline int ptep_test_and_clear_young(pte_t *ptep)
 {
 	return (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED) != 0;
@@ -440,36 +433,25 @@
 
 static inline int ptep_test_and_clear_dirty(pte_t *ptep)
 {
-	return (pte_update(ptep, _PAGE_DIRTY | _PAGE_HWWRITE, 0)
-		& _PAGE_DIRTY) != 0;
+	return (pte_update(ptep, _PAGE_DIRTY, 0) & _PAGE_DIRTY) != 0;
 }
 
 static inline pte_t ptep_get_and_clear(pte_t *ptep)
 {
-	return __pte(pte_update(ptep, ~0UL, 0));
+	return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0));
 }
 
 static inline void ptep_set_wrprotect(pte_t *ptep)
 {
-	pte_update(ptep, _PAGE_RW | _PAGE_HWWRITE, 0);
+	pte_update(ptep, _PAGE_RW, 0);
 }
 
 static inline void ptep_mkdirty(pte_t *ptep)
 {
-	/*
-	 * N.B. this doesn't set the _PAGE_HWWRITE bit in the case
-	 * where _PAGE_RW is set and _PAGE_DIRTY was clear.  This
-	 * doesn't matter; all it will mean is that if the next call
-	 * to hash_page for this page is for a read, it will put a
-	 * readonly HPTE into the hash table rather than a R/W HPTE.
-	 * A call to hash_page for a write to this page will set
-	 * _PAGE_HWWRITE and put a R/W HPTE into the hash table.
-	 *  -- paulus.
-	 */
 	pte_update(ptep, 0, _PAGE_DIRTY);
 }
 
-#define pte_same(A,B)	(pte_val(A) == pte_val(B))
+#define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
 
 #define pmd_page(pmd)	(pmd_val(pmd))
 
@@ -496,25 +478,25 @@
 extern void paging_init(void);
 
 /*
- * Page tables may have changed.  We don't need to do anything here
- * as entries are faulted into the hash table by the low-level
- * data/instruction access exception handlers.
+ * When flushing the tlb entry for a page, we also need to flush the hash
+ * table entry.  flush_hash_page is assembler (for speed) in hashtable.S.
  */
-#define update_mmu_cache(vma, addr, pte)	do { } while (0)
+extern int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep);
+
+/* Add an HPTE to the hash table */
+extern void add_hash_page(unsigned context, unsigned long va, pte_t *ptep);
 
 /*
- * When flushing the tlb entry for a page, we also need to flush the
- * hash table entry.  flush_hash_page is assembler (for speed) in head.S.
+ * Encode and decode a swap entry.
+ * Note that the bits we use in a PTE for representing a swap entry
+ * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit
+ * (if used).  -- paulus
  */
-extern void flush_hash_segments(unsigned low_vsid, unsigned high_vsid);
-extern void flush_hash_page(unsigned context, unsigned long va);
-
-/* Encode and de-code a swap entry */
-#define SWP_TYPE(entry)			(((entry).val >> 1) & 0x3f)
-#define SWP_OFFSET(entry)		((entry).val >> 8)
-#define SWP_ENTRY(type, offset)		((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
-#define pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
-#define swp_entry_to_pte(x)		((pte_t) { (x).val })
+#define SWP_TYPE(entry)			((entry).val & 0x3f)
+#define SWP_OFFSET(entry)		((entry).val >> 6)
+#define SWP_ENTRY(type, offset)		((swp_entry_t) { (type) | ((offset) << 6) })
+#define pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 2 })
+#define swp_entry_to_pte(x)		((pte_t) { (x).val << 2 })
 
 /* CONFIG_APUS */
 /* For virtual address to physical address conversion */
@@ -545,7 +527,6 @@
                                  unsigned int cmode);
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define PageSkip(page)		(0)
 #define kern_addr_valid(addr)	(1)
 
 #define io_remap_page_range remap_page_range 
diff -urN linux-2.4.6-pre8/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- linux-2.4.6-pre8/include/asm-ppc/processor.h	Thu May 24 15:03:05 2001
+++ linux/include/asm-ppc/processor.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.processor.h 1.19 05/18/01 08:18:10 patch
+ * BK Id: SCCS/s.processor.h 1.24 06/15/01 13:56:56 paulus
  */
 #ifdef __KERNEL__
 #ifndef __ASM_PPC_PROCESSOR_H
@@ -445,6 +445,7 @@
 #define	PVR_403GC	0x00200200
 #define	PVR_403GCX	0x00201400
 #define	PVR_405GP	0x40110000
+#define	PVR_STB03XXX	0x40310000 
 #define	PVR_601		0x00010000
 #define	PVR_602		0x00050000
 #define	PVR_603		0x00030000
@@ -459,6 +460,8 @@
 #define	PVR_750		PVR_740
 #define	PVR_740P	0x10080000
 #define	PVR_750P	PVR_740P
+#define	PVR_7400	0x000C0000
+#define	PVR_7410	0x800C0000
 /*
  * For the 8xx processors, all of them report the same PVR family for
  * the PowerPC core. The various versions of these processors must be
@@ -469,7 +472,6 @@
 #define	PVR_823		PVR_821
 #define	PVR_850		PVR_821
 #define	PVR_860		PVR_821
-#define	PVR_7400       	0x000C0000
 #define	PVR_8240	0x00810100
 #define	PVR_8260	PVR_8240
 
diff -urN linux-2.4.6-pre8/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h
--- linux-2.4.6-pre8/include/asm-ppc/prom.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/prom.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.prom.h 1.11 05/18/01 08:18:10 patch
+ * BK Id: SCCS/s.prom.h 1.14 06/13/01 15:28:43 paulus
  */
 /*
  * Definitions for talking to the Open Firmware PROM on
@@ -45,6 +45,9 @@
 	struct property *next;
 };
 
+/*
+ * Note: don't change this structure for now or you'll break BootX !
+ */
 struct device_node {
 	char	*name;
 	char	*type;
@@ -60,10 +63,6 @@
 	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;
@@ -101,6 +100,24 @@
 extern void map_bootx_text(void);
 extern void bootx_update_display(unsigned long phys, int width, int height,
 				 int depth, int pitch);
+
+/*
+ * When we call back to the Open Firmware client interface, we usually
+ * have to do that before the kernel is relocated to its final location
+ * (this is because we can't use OF after we have overwritten the
+ * exception vectors with our exception handlers).  These macros assist
+ * in performing the address calculations that we need to do to access
+ * data when the kernel is running at an address that is different from
+ * the address that the kernel is linked at.  The reloc_offset() function
+ * returns the difference between these two addresses and the macros
+ * simplify the process of adding or subtracting this offset to/from
+ * pointer values.  See arch/ppc/kernel/prom.c for how these are used.
+ */
+extern unsigned long reloc_offset(void);
+
+#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_PROM_H */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.6-pre8/include/asm-ppc/time.h linux/include/asm-ppc/time.h
--- linux-2.4.6-pre8/include/asm-ppc/time.h	Mon May 21 15:02:06 2001
+++ linux/include/asm-ppc/time.h	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.time.h 1.10 05/17/01 18:14:26 cort
+ * BK Id: SCCS/s.time.h 1.13 06/27/01 14:49:58 trini
  */
 /*
  * Common time prototypes and such for all ppc machines.
@@ -23,6 +23,8 @@
 
 extern void to_tm(int tim, struct rtc_time * tm);
 extern time_t last_rtc_update;
+
+extern void set_dec_cpu6(unsigned int val);
 
 int via_calibrate_decr(void);
 
diff -urN linux-2.4.6-pre8/include/asm-sh/hitachi_se.h linux/include/asm-sh/hitachi_se.h
--- linux-2.4.6-pre8/include/asm-sh/hitachi_se.h	Mon Jun 19 17:59:38 2000
+++ linux/include/asm-sh/hitachi_se.h	Mon Dec  3 22:50:39 2001
@@ -38,7 +38,7 @@
 #define PA_LED		0xb0c00000	/* LED */
 #define PA_BCR		0xb1400000	/* FPGA */
 
-#define PA_MRSHPC	0xb83fffe0	/* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC	0xb83fffe0	/* MR-SHPC-01 PCMCIA controller */
 #define PA_MRSHPC_MW1	0xb8400000	/* MR-SHPC-01 memory window base */
 #define PA_MRSHPC_MW2	0xb8500000	/* MR-SHPC-01 attribute window base */
 #define PA_MRSHPC_IO	0xb8600000	/* MR-SHPC-01 I/O window base */
diff -urN linux-2.4.6-pre8/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h
--- linux-2.4.6-pre8/include/asm-sparc/hardirq.h	Mon Dec  3 22:50:28 2001
+++ linux/include/asm-sparc/hardirq.h	Mon Dec  3 22:50:39 2001
@@ -1,7 +1,7 @@
 /* hardirq.h: 32-bit Sparc hard IRQ support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
  */
 
 #ifndef __SPARC_HARDIRQ_H
diff -urN linux-2.4.6-pre8/include/asm-sparc/vaddrs.h linux/include/asm-sparc/vaddrs.h
--- linux-2.4.6-pre8/include/asm-sparc/vaddrs.h	Fri Aug  4 18:16:11 2000
+++ linux/include/asm-sparc/vaddrs.h	Mon Dec  3 22:50:39 2001
@@ -9,7 +9,7 @@
  *                      which important things will be mapped.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
  */
 
 #define SRMMU_MAXMEM		0x0c000000
diff -urN linux-2.4.6-pre8/include/asm-sparc64/starfire.h linux/include/asm-sparc64/starfire.h
--- linux-2.4.6-pre8/include/asm-sparc64/starfire.h	Tue Oct  3 09:24:41 2000
+++ linux/include/asm-sparc64/starfire.h	Mon Dec  3 22:50:39 2001
@@ -1,7 +1,7 @@
 /* $Id: starfire.h,v 1.1 2000/09/21 06:18:53 anton Exp $
  * starfire.h: Group all starfire specific code together.
  *
- * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
  */
 
 #ifndef _SPARC64_STARFIRE_H
diff -urN linux-2.4.6-pre8/include/linux/agp_backend.h linux/include/linux/agp_backend.h
--- linux-2.4.6-pre8/include/linux/agp_backend.h	Tue Feb 13 14:13:43 2001
+++ linux/include/linux/agp_backend.h	Mon Dec  3 22:50:39 2001
@@ -45,7 +45,7 @@
 	INTEL_BX,
 	INTEL_GX,
 	INTEL_I810,
-       INTEL_I815,
+	INTEL_I815,
 	INTEL_I840,
 	INTEL_I850,
 	VIA_GENERIC,
@@ -65,7 +65,10 @@
 	ALI_M1641,
 	ALI_M1647,
 	ALI_M1651,
-	ALI_GENERIC
+	ALI_GENERIC,
+	SVWRKS_HE,
+	SVWRKS_LE,
+	SVWRKS_GENERIC
 };
 
 typedef struct _agp_version {
diff -urN linux-2.4.6-pre8/include/linux/atmdev.h linux/include/linux/atmdev.h
--- linux-2.4.6-pre8/include/linux/atmdev.h	Fri May 25 18:03:14 2001
+++ linux/include/linux/atmdev.h	Mon Dec  3 22:50:39 2001
@@ -22,6 +22,13 @@
 			   max cell rate:  353207.547 cells/sec */
 #define ATM_25_PCR	((25600000/8-8000)/54)
 			/* 25 Mbps ATM cell rate (59111) */
+#define ATM_OC12_PCR	(622080000/1080*1040/8/53)
+			/* OC12 link rate: 622080000 bps
+			   SONET overhead: /1080*1040
+			   bits per cell:  /8/53
+			   max cell rate:  1412830.188 cells/sec */
+#define ATM_DS3_PCR	(8000*12)
+			/* DS3: 12 cells in a 125 usec time slot */
 
 #define ATM_PDU_OVHD	0	/* number of bytes to charge against buffer
 				   quota per PDU */
diff -urN linux-2.4.6-pre8/include/linux/isdn/tpam.h linux/include/linux/isdn/tpam.h
--- linux-2.4.6-pre8/include/linux/isdn/tpam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isdn/tpam.h	Mon Dec  3 22:50:39 2001
@@ -0,0 +1,56 @@
+/* $Id: tpam.h,v 1.1.2.1 2001/06/08 08:23:46 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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.
+ *
+ */
+
+#ifndef _TPAM_H_
+#define _TPAM_H_
+
+#include <linux/types.h>
+#include <linux/pci.h>
+
+/* IOCTL commands */
+#define TPAM_CMD_DSPLOAD	0x0001
+#define TPAM_CMD_DSPSAVE	0x0002
+#define TPAM_CMD_DSPRUN		0x0003
+#define TPAM_CMD_LOOPMODEON	0x0004
+#define TPAM_CMD_LOOPMODEOFF	0x0005
+
+/* addresses of debug information zones on board */
+#define TPAM_TRAPAUDIT_REGISTER		0x005493e4
+#define TPAM_NCOAUDIT_REGISTER		0x00500000
+#define TPAM_MSGAUDIT_REGISTER		0x008E30F0
+
+/* length of debug information zones on board */
+#define TPAM_TRAPAUDIT_LENGTH		10000
+#define TPAM_NCOAUDIT_LENGTH		300000
+#define TPAM_NCOAUDIT_COUNT		30
+#define TPAM_MSGAUDIT_LENGTH		60000
+
+/* IOCTL load/save parameter */
+typedef struct tpam_dsp_ioctl {
+	__u32 address;	/* address to load/save data */
+	__u32 data_len;	/* size of data to be loaded/saved */
+	__u8 data[0];	/* data */
+} tpam_dsp_ioctl;
+
+#endif /* _TPAM_H_ */
diff -urN linux-2.4.6-pre8/include/linux/isdn.h linux/include/linux/isdn.h
--- linux-2.4.6-pre8/include/linux/isdn.h	Sat May 19 17:54:14 2001
+++ linux/include/linux/isdn.h	Mon Dec  3 22:50:39 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.111.6.6 2001/05/17 21:15:34 kai Exp $
+/* $Id: isdn.h,v 1.111.6.7 2001/06/30 19:47:51 kai Exp $
 
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -27,6 +27,15 @@
 
 #include <linux/ioctl.h>
 
+#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
+
 /* New ioctl-codes */
 #define IIOCNETAIF  _IO('I',1)
 #define IIOCNETDIF  _IO('I',2)
@@ -181,14 +190,6 @@
  * 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
diff -urN linux-2.4.6-pre8/include/linux/isdnif.h linux/include/linux/isdnif.h
--- linux-2.4.6-pre8/include/linux/isdnif.h	Sat May 19 17:54:14 2001
+++ linux/include/linux/isdnif.h	Mon Dec  3 22:50:39 2001
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.37.6.2 2001/05/17 21:15:34 kai Exp $
+/* $Id: isdnif.h,v 1.37.6.4 2001/06/09 15:14:19 kai Exp $
 
  * Linux ISDN subsystem
  *
@@ -433,6 +433,7 @@
 #ifdef CONFIG_ISDN_TTY_FAX
 		T30_s	*fax;	/* Pointer to ttys fax struct		*/
 #endif
+		ulong userdata;	/* User Data */
 	} parm;
 } isdn_ctrl;
 
diff -urN linux-2.4.6-pre8/include/linux/nfsd/nfsd.h linux/include/linux/nfsd/nfsd.h
--- linux-2.4.6-pre8/include/linux/nfsd/nfsd.h	Fri May 25 18:02:17 2001
+++ linux/include/linux/nfsd/nfsd.h	Mon Dec  3 22:50:39 2001
@@ -81,7 +81,7 @@
 int		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
 				const char *, int, struct svc_fh *);
 int		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
-				struct iattr *);
+				struct iattr *, int, time_t);
 int		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
 				int type, dev_t rdev, struct svc_fh *res);
@@ -143,6 +143,7 @@
 #define	nfserr_noent		__constant_htonl(NFSERR_NOENT)
 #define	nfserr_io		__constant_htonl(NFSERR_IO)
 #define	nfserr_nxio		__constant_htonl(NFSERR_NXIO)
+#define	nfserr_eagain		__constant_htonl(NFSERR_EAGAIN)
 #define	nfserr_acces		__constant_htonl(NFSERR_ACCES)
 #define	nfserr_exist		__constant_htonl(NFSERR_EXIST)
 #define	nfserr_xdev		__constant_htonl(NFSERR_XDEV)
@@ -160,9 +161,10 @@
 #define	nfserr_dquot		__constant_htonl(NFSERR_DQUOT)
 #define	nfserr_stale		__constant_htonl(NFSERR_STALE)
 #define	nfserr_remote		__constant_htonl(NFSERR_REMOTE)
+#define	nfserr_wflush		__constant_htonl(NFSERR_WFLUSH)
 #define	nfserr_badhandle	__constant_htonl(NFSERR_BADHANDLE)
-#define	nfserr_notsync		__constant_htonl(NFSERR_NOTSYNC)
-#define	nfserr_badcookie	__constant_htonl(NFSERR_BADCOOKIE)
+#define	nfserr_notsync		__constant_htonl(NFSERR_NOT_SYNC)
+#define	nfserr_badcookie	__constant_htonl(NFSERR_BAD_COOKIE)
 #define	nfserr_notsupp		__constant_htonl(NFSERR_NOTSUPP)
 #define	nfserr_toosmall		__constant_htonl(NFSERR_TOOSMALL)
 #define	nfserr_serverfault	__constant_htonl(NFSERR_SERVERFAULT)
diff -urN linux-2.4.6-pre8/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h
--- linux-2.4.6-pre8/include/linux/nfsd/nfsfh.h	Fri May 25 18:02:17 2001
+++ linux/include/linux/nfsd/nfsfh.h	Mon Dec  3 22:50:39 2001
@@ -199,7 +199,7 @@
  * Function prototypes
  */
 u32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
-int	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *);
+int	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
 int	fh_update(struct svc_fh *);
 void	fh_put(struct svc_fh *);
 
diff -urN linux-2.4.6-pre8/include/linux/pci.h linux/include/linux/pci.h
--- linux-2.4.6-pre8/include/linux/pci.h	Mon Dec  3 22:50:28 2001
+++ linux/include/linux/pci.h	Mon Dec  3 22:50:39 2001
@@ -641,6 +641,8 @@
 static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
 static inline void pci_disable_device(struct pci_dev *dev) { }
 static inline int pci_module_init(struct pci_driver *drv) { return -ENODEV; }
+static inline int pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) { return -EIO; }
+static inline int pci_set_power_state(struct pci_dev *dev, int state) { return 0; }
 static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
 static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
diff -urN linux-2.4.6-pre8/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- linux-2.4.6-pre8/include/linux/pci_ids.h	Mon Dec  3 22:50:28 2001
+++ linux/include/linux/pci_ids.h	Mon Dec  3 22:50:39 2001
@@ -211,6 +211,7 @@
 #define PCI_DEVICE_ID_ATI_RAGE128_PP	0x5050
 #define PCI_DEVICE_ID_ATI_RAGE128_PQ	0x5051
 #define PCI_DEVICE_ID_ATI_RAGE128_PR	0x5052
+#define PCI_DEVICE_ID_ATI_RAGE128_TR	0x5452
 #define PCI_DEVICE_ID_ATI_RAGE128_PS	0x5053
 #define PCI_DEVICE_ID_ATI_RAGE128_PT	0x5054
 #define PCI_DEVICE_ID_ATI_RAGE128_PU	0x5055
@@ -326,6 +327,7 @@
 #define PCI_DEVICE_ID_IBM_TR_WAKE	0x003e
 #define PCI_DEVICE_ID_IBM_MPIC		0x0046
 #define PCI_DEVICE_ID_IBM_3780IDSP	0x007d
+#define PCI_DEVICE_ID_IBM_CHUKAR	0x0096
 #define	PCI_DEVICE_ID_IBM_405GP		0x0156
 #define PCI_DEVICE_ID_IBM_MPIC_2	0xffff
 
@@ -345,6 +347,9 @@
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
 #define PCI_DEVICE_ID_AMD_FE_GATE_7006	0x7006
+#define PCI_DEVICE_ID_AMD_FE_GATE_7007	0x7007
+#define PCI_DEVICE_ID_AMD_FE_GATE_700E	0x700E
+#define PCI_DEVICE_ID_AMD_FE_GATE_700F	0x700F
 #define PCI_DEVICE_ID_AMD_COBRA_7400	0x7400
 #define PCI_DEVICE_ID_AMD_COBRA_7401	0x7401
 #define PCI_DEVICE_ID_AMD_COBRA_7403	0x7403
@@ -353,6 +358,10 @@
 #define PCI_DEVICE_ID_AMD_VIPER_7409	0x7409
 #define PCI_DEVICE_ID_AMD_VIPER_740B	0x740B
 #define PCI_DEVICE_ID_AMD_VIPER_740C	0x740C
+#define PCI_DEVICE_ID_AMD_VIPER_7410	0x7410
+#define PCI_DEVICE_ID_AMD_VIPER_7411	0x7411
+#define PCI_DEVICE_ID_AMD_VIPER_7413	0x7413
+#define PCI_DEVICE_ID_AMD_VIPER_7414	0x7414
 
 #define PCI_VENDOR_ID_TRIDENT		0x1023
 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX	0x2000
@@ -403,6 +412,7 @@
 #define PCI_VENDOR_ID_NEC		0x1033
 #define PCI_DEVICE_ID_NEC_PCX2		0x0046
 #define PCI_DEVICE_ID_NEC_NILE4		0x005a
+#define PCI_DEVICE_ID_NEC_VRC5476       0x009b
 
 #define PCI_VENDOR_ID_FD		0x1036
 #define PCI_DEVICE_ID_FD_36C70		0x0000
@@ -417,15 +427,20 @@
 #define PCI_DEVICE_ID_SI_501		0x0406
 #define PCI_DEVICE_ID_SI_496		0x0496
 #define PCI_DEVICE_ID_SI_300		0x0300
+#define PCI_DEVICE_ID_SI_315H		0x0310
+#define PCI_DEVICE_ID_SI_315		0x0315
 #define PCI_DEVICE_ID_SI_530		0x0530
 #define PCI_DEVICE_ID_SI_540		0x0540
+#define PCI_DEVICE_ID_SI_550		0x0550
 #define PCI_DEVICE_ID_SI_540_VGA	0x5300
+#define PCI_DEVICE_ID_SI_550_VGA	0x5315
 #define PCI_DEVICE_ID_SI_601		0x0601
 #define PCI_DEVICE_ID_SI_620		0x0620
 #define PCI_DEVICE_ID_SI_630		0x0630
-#define PCI_DEVICE_ID_SI_730		0x0730         
+#define PCI_DEVICE_ID_SI_730		0x0730
 #define PCI_DEVICE_ID_SI_630_VGA	0x6300
 #define PCI_DEVICE_ID_SI_730_VGA	0x7300
+#define PCI_DEVICE_ID_SI_900		0x0900
 #define PCI_DEVICE_ID_SI_5107		0x5107
 #define PCI_DEVICE_ID_SI_5300		0x5300
 #define PCI_DEVICE_ID_SI_5511		0x5511
@@ -439,6 +454,7 @@
 #define PCI_DEVICE_ID_SI_6306		0x6306
 #define PCI_DEVICE_ID_SI_6326		0x6326
 #define PCI_DEVICE_ID_SI_7001		0x7001
+#define PCI_DEVICE_ID_SI_7016		0x7016
 
 #define PCI_VENDOR_ID_HP		0x103c
 #define PCI_DEVICE_ID_HP_DONNER_GFX	0x1008
@@ -508,6 +524,8 @@
 #define PCI_DEVICE_ID_TI_1251A		0xac1d
 #define PCI_DEVICE_ID_TI_1211		0xac1e
 #define PCI_DEVICE_ID_TI_1251B		0xac1f
+#define PCI_DEVICE_ID_TI_4410		0xac41
+#define PCI_DEVICE_ID_TI_4451		0xac42
 #define PCI_DEVICE_ID_TI_1420		0xac51
 
 #define PCI_VENDOR_ID_SONY		0x104d
@@ -544,6 +562,7 @@
 #define PCI_DEVICE_ID_PROMISE_20267	0x4d30
 #define PCI_DEVICE_ID_PROMISE_20246	0x4d33
 #define PCI_DEVICE_ID_PROMISE_20262	0x4d38
+#define PCI_DEVICE_ID_PROMISE_20268	0x4d68
 #define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
 #define PCI_VENDOR_ID_N9		0x105d
@@ -800,6 +819,8 @@
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
+#define PCI_DEVICE_ID_IMS_TT128		0x9128
+#define PCI_DEVICE_ID_IMS_TT3D		0x9135
 
 #define PCI_VENDOR_ID_TEKRAM2		0x10e1
 #define PCI_DEVICE_ID_TEKRAM2_690c	0x690c
@@ -825,6 +846,9 @@
 #define PCI_DEVICE_ID_REALTEK_8129	0x8129
 #define PCI_DEVICE_ID_REALTEK_8139	0x8139
 
+#define PCI_VENDOR_ID_XILINX		0x10ee
+#define PCI_DEVICE_ID_TURBOPAM		0x4020
+
 #define PCI_VENDOR_ID_TRUEVISION	0x10fa
 #define PCI_DEVICE_ID_TRUEVISION_T1000	0x000c
 
@@ -1003,15 +1027,18 @@
 #define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
 
-#define PCI_VENDOR_ID_SERVERWORKS	0x1166
-#define PCI_DEVICE_ID_SERVERWORKS_HE	0x0008
-#define PCI_DEVICE_ID_SERVERWORKS_LE	0x0009
-#define PCI_DEVICE_ID_SERVERWORKS_CIOB30   0x0010
-#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE  0x0011
-#define PCI_DEVICE_ID_SERVERWORKS_CSB5	   0x0201
-#define PCI_DEVICE_ID_SERVERWORKS_OSB4	0x0200
+#define PCI_VENDOR_ID_SERVERWORKS	  0x1166
+#define PCI_DEVICE_ID_SERVERWORKS_HE	  0x0008
+#define PCI_DEVICE_ID_SERVERWORKS_LE	  0x0009
+#define PCI_DEVICE_ID_SERVERWORKS_CIOB30  0x0010
+#define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5	  0x0201
+#define PCI_DEVICE_ID_SERVERWORKS_OSB4	  0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
+#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
 
 #define PCI_VENDOR_ID_SBE		0x1176
 #define PCI_DEVICE_ID_SBE_WANXL100	0x0301
@@ -1189,6 +1216,9 @@
 
 #define PCI_VENDOR_ID_ROCKWELL		0x127A
 
+#define PCI_VENDOR_ID_ITE		0x1283
+#define PCI_DEVICE_ID_ITE_IT8172G	0x8172
+
 /* formerly Platform Tech */
 #define PCI_VENDOR_ID_ESS_OLD		0x1285
 #define PCI_DEVICE_ID_ESS_ESS0100	0x0100
@@ -1299,6 +1329,9 @@
 #define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2	0x0108
 #define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS	0x0109
 
+#define PCI_VENDOR_ID_KAWASAKI		0x136b
+#define PCI_DEVICE_ID_MCHIP_KL5A72002	0xff01
+
 #define PCI_VENDOR_ID_LMC		0x1376
 #define PCI_DEVICE_ID_LMC_HSSI		0x0003
 #define PCI_DEVICE_ID_LMC_DS3		0x0004
@@ -1372,6 +1405,8 @@
 #define PCI_DEVICE_ID_AIRONET_4500	0x4800 // drivers/net/aironet4500_card.c
 
 #define PCI_VENDOR_ID_TITAN		0x14D2
+#define PCI_DEVICE_ID_TITAN_110L	0x8011
+#define PCI_DEVICE_ID_TITAN_210L	0x8021
 #define PCI_DEVICE_ID_TITAN_100		0xA001
 #define PCI_DEVICE_ID_TITAN_200		0xA005
 #define PCI_DEVICE_ID_TITAN_400		0xA003
@@ -1591,6 +1626,10 @@
 
 #define PCI_VENDOR_ID_HOLTEK		0x9412
 #define PCI_DEVICE_ID_HOLTEK_6565	0x6565
+
+#define PCI_VENDOR_ID_NETMOS		0x9710
+#define PCI_DEVICE_ID_NETMOS_9735	0x9735
+#define PCI_DEVICE_ID_NETMOS_9835	0x9835
 
 #define PCI_SUBVENDOR_ID_EXSYS		0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
diff -urN linux-2.4.6-pre8/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h
--- linux-2.4.6-pre8/include/linux/sysv_fs.h	Mon Dec 11 13:26:16 2000
+++ linux/include/linux/sysv_fs.h	Mon Dec  3 22:50:39 2001
@@ -7,7 +7,6 @@
 
 
 /* This code assumes
-   - a little endian processor like 386,
    - sizeof(short) = 2, sizeof(int) = 4, sizeof(long) = 4,
    - alignof(short) = 2, alignof(long) = 4.
 */
@@ -26,27 +25,17 @@
 /* Layout on disk */
 /* ============== */
 
-
-/* The block size is sb->sv_block_size which may be smaller than BLOCK_SIZE. */
-
-/* zones (= data allocation units) are blocks */
-
-/* On Coherent FS, 32 bit quantities are stored using (I quote the Coherent
-   manual) a "canonical byte ordering". This is the PDP-11 byte ordering:
-   x = 2^24 * byte3 + 2^16 * byte2 + 2^8 * byte1 + byte0 is stored
-   as { byte2, byte3, byte0, byte1 }. We need conversions.
-*/
-
-typedef u32 coh_ulong;
-
-static inline coh_ulong to_coh_ulong (u32 x)
-{
-	return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
-}
-
-static inline u32 from_coh_ulong (coh_ulong x)
+static inline u32 PDP_swab(u32 x)
 {
+#ifdef __LITTLE_ENDIAN
 	return ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16);
+#else
+#ifdef __BIG_ENDIAN
+	return ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8);
+#else
+#error BYTESEX
+#endif
+#endif
 }
 
 /* inode numbers are 16 bit */
@@ -103,12 +92,6 @@
 								
 };
 
-/* Xenix free list block on disk */
-struct xenix_freelist_chunk {
-	u16	fl_nfree;	/* number of free blocks in fl_free, <= XENIX_NICFREE] */
-	u32	fl_free[XENIX_NICFREE] __packed2__;
-};
-
 /* SystemV FS comes in two variants:
  * sysv2: System V Release 2 (e.g. Microport), structure elements aligned(2).
  * sysv4: System V Release 4 (e.g. Consensys), structure elements aligned(4).
@@ -148,12 +131,6 @@
 								2 for 1024 byte blocks */
 };
 
-/* SystemV4 free list block on disk */
-struct sysv4_freelist_chunk {
-	u16 fl_nfree;	/* number of free blocks in fl_free, <= SYSV_NICFREE] */
-	u32  fl_free[SYSV_NICFREE];
-};
-
 /* SystemV2 super-block data on disk */
 struct sysv2_super_block {
 	u16	s_isize; 		/* index of first data zone */
@@ -182,10 +159,31 @@
 								2 for 1024 byte blocks */
 };
 
-/* SystemV2 free list block on disk */
-struct sysv2_freelist_chunk {
-	u16	fl_nfree;	/* number of free blocks in fl_free, <= SYSV_NICFREE] */
-	u32	fl_free[SYSV_NICFREE] __packed2__;
+/* V7 super-block data on disk */
+#define V7_NICINOD     100     /* number of inode cache entries */
+#define V7_NICFREE     50      /* number of free block list chunk entries */
+struct v7_super_block {
+	u16    s_isize;        /* index of first data zone */
+	u32    s_fsize __packed2__; /* total number of zones of this fs */
+	/* the start of the free block list: */
+	u16    s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
+	u32    s_free[V7_NICFREE]; /* first free block list chunk */
+	/* the cache of free inodes: */
+	u16    s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
+	sysv_ino_t      s_inode[V7_NICINOD]; /* some free inodes */
+	/* locks, not used by Linux or V7: */
+	char    s_flock;        /* lock during free block list manipulation */
+	char    s_ilock;        /* lock during inode cache manipulation */
+	char    s_fmod;         /* super-block modified flag */
+	char    s_ronly;        /* flag whether fs is mounted read-only */
+	u32     s_time __packed2__; /* time of last super block update */
+	/* the following fields are not maintained by V7: */
+	u32     s_tfree __packed2__; /* total number of free zones */
+	u16     s_tinode;       /* total number of free inodes */
+	u16     s_m;            /* interleave factor */
+	u16     s_n;            /* interleave factor */
+	char    s_fname[6];     /* file system name */
+	char    s_fpack[6];     /* file system pack name */
 };
 
 /* Coherent super-block data on disk */
@@ -193,10 +191,10 @@
 #define COH_NICFREE	64	/* number of free block list chunk entries */
 struct coh_super_block {
 	u16		s_isize;	/* index of first data zone */
-	coh_ulong	s_fsize __packed2__; /* total number of zones of this fs */
+	u32		s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
 	u16 s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
-	coh_ulong	s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+	u32		s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
 	/* the cache of free inodes: */
 	u16		s_ninode;	/* number of free inodes in s_inode, <= COH_NICINOD */
 	sysv_ino_t	s_inode[COH_NICINOD]; /* some free inodes */
@@ -205,8 +203,8 @@
 	char		s_ilock;	/* lock during inode cache manipulation */
 	char		s_fmod;		/* super-block modified flag */
 	char		s_ronly;	/* flag whether fs is mounted read-only */
-	coh_ulong	s_time __packed2__; /* time of last super block update */
-	coh_ulong	s_tfree __packed2__; /* total number of free zones */
+	u32		s_time __packed2__; /* time of last super block update */
+	u32		s_tfree __packed2__; /* total number of free zones */
 	u16		s_tinode;	/* total number of free inodes */
 	u16		s_interleave_m;	/* interleave factor */
 	u16		s_interleave_n;
@@ -215,13 +213,6 @@
 	u32		s_unique;	/* zero, not used */
 };
 
-/* Coherent free list block on disk */
-struct coh_freelist_chunk {
-	u16 fl_nfree;	/* number of free blocks in fl_free, <= COH_NICFREE] */
-	u32  fl_free[COH_NICFREE] __packed2__;
-};
-
-
 /* SystemV/Coherent inode data on disk */
 
 struct sysv_inode {
@@ -237,8 +228,6 @@
 					      * then 1 triple indirection block.
 					      * Then maybe a "file generation number" ??
 					      */
-		/* devices */
-		dev_t i_rdev;
 		/* named pipes on Coherent */
 		struct {
 			char p_addp[30];
@@ -300,9 +289,12 @@
 }
 
 /* Admissible values for i_nlink: 0.._LINK_MAX */
-#define XENIX_LINK_MAX	126	/* ?? */
-#define SYSV_LINK_MAX	126	/* 127? 251? */
-#define COH_LINK_MAX	10000	/* max number of hard links to an inode */
+enum {
+	XENIX_LINK_MAX	=	126,	/* ?? */
+	SYSV_LINK_MAX	=	126,	/* 127? 251? */
+	V7_LINK_MAX     =	126,	/* ?? */
+	COH_LINK_MAX	=	10000,
+};
 
 /* The number of inodes per block is
    sb->sv_inodes_per_block = block_size / sizeof(struct sysv_inode) */
@@ -325,12 +317,16 @@
 /* Operations */
 /* ========== */
 
-
 /* identify the FS in memory */
-#define FSTYPE_XENIX	1
-#define FSTYPE_SYSV4	2
-#define FSTYPE_SYSV2	3
-#define FSTYPE_COH	4
+enum {
+	FSTYPE_NONE = 0,
+	FSTYPE_XENIX,
+	FSTYPE_SYSV4,
+	FSTYPE_SYSV2,
+	FSTYPE_COH,
+	FSTYPE_V7,
+	FSTYPE_END,
+};
 
 #define SYSV_MAGIC_BASE		0x012FF7B3
 
@@ -341,55 +337,112 @@
 
 #ifdef __KERNEL__
 
-/* sv_get_hash_table(sb,dev,block) is equivalent to  get_hash_table(dev,block,block_size)  */
-static inline struct buffer_head *
-sv_get_hash_table (struct super_block *sb, kdev_t dev, unsigned int block)
-{
-	return get_hash_table (dev, block + sb->sv_block_base, sb->sv_block_size);
-}
-
-/* sv_getblk(sb,dev,block) is equivalent to  getblk(dev,block,block_size)  */
-static inline struct buffer_head *
-sv_getblk (struct super_block *sb, kdev_t dev, unsigned int block)
-{
-	return getblk (dev, block + sb->sv_block_base, sb->sv_block_size);
-}
-
-/* sv_bread(sb,dev,block) is equivalent to  bread(dev,block,block_size)  */
-static inline struct buffer_head *
-sv_bread (struct super_block *sb, kdev_t dev, unsigned int block)
-{
-	return bread (dev, block + sb->sv_block_base, sb->sv_block_size);
-}
-
+enum {
+	BYTESEX_LE,
+	BYTESEX_PDP,
+	BYTESEX_BE,
+};
 
 /*
  * Function prototypes
  */
 
-extern struct inode * sysv_new_inode(const struct inode * dir);
-extern void sysv_free_inode(struct inode * inode);
-extern unsigned long sysv_count_free_inodes(struct super_block *sb);
-extern int sysv_new_block(struct super_block * sb);
-extern void sysv_free_block(struct super_block * sb, unsigned int block);
-extern unsigned long sysv_count_free_blocks(struct super_block *sb);
-
-extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
+extern struct inode * sysv_new_inode(const struct inode *, mode_t);
+extern void sysv_free_inode(struct inode *);
+extern unsigned long sysv_count_free_inodes(struct super_block *);
+extern u32 sysv_new_block(struct super_block *);
+extern void sysv_free_block(struct super_block *, u32);
+extern unsigned long sysv_count_free_blocks(struct super_block *);
 
 extern void sysv_truncate(struct inode *);
+
 extern void sysv_write_inode(struct inode *, int);
 extern int sysv_sync_inode(struct inode *);
 extern int sysv_sync_file(struct file *, struct dentry *, int);
 extern int sysv_notify_change(struct dentry *, struct iattr *);
+extern void sysv_set_inode(struct inode *, dev_t);
+
+extern struct sysv_dir_entry *sysv_find_entry(struct dentry*, struct page**);
+extern int sysv_add_link(struct dentry*, struct inode*);
+extern int sysv_delete_entry(struct sysv_dir_entry*, struct page*);
+extern int sysv_make_empty(struct inode*, struct inode*);
+extern int sysv_empty_dir(struct inode*);
+extern void sysv_set_link(struct sysv_dir_entry*, struct page*, struct inode*);
+extern struct sysv_dir_entry *sysv_dotdot(struct inode*, struct page**);
+extern ino_t sysv_inode_by_name(struct dentry*);
 
 extern struct inode_operations sysv_file_inode_operations;
-extern struct inode_operations sysv_symlink_inode_operations;
 extern struct inode_operations sysv_dir_inode_operations;
 extern struct file_operations sysv_file_operations;
 extern struct file_operations sysv_dir_operations;
 extern struct address_space_operations sysv_aops;
+extern struct super_operations sysv_sops;
+extern struct dentry_operations sysv_dentry_operations;
+
+extern struct sysv_inode *sysv_raw_inode(struct super_block *, unsigned, struct buffer_head **);
+
+static inline void dirty_sb(struct super_block *sb)
+{
+	mark_buffer_dirty(sb->sv_bh1);
+	if (sb->sv_bh1 != sb->sv_bh2)
+		mark_buffer_dirty(sb->sv_bh2);
+	sb->s_dirt = 1;
+}
+
+static inline u32 fs32_to_cpu(struct super_block *sb, u32 n)
+{
+	if (sb->sv_bytesex == BYTESEX_PDP)
+		return PDP_swab(n);
+	else if (sb->sv_bytesex == BYTESEX_LE)
+		return le32_to_cpu(n);
+	else
+		return be32_to_cpu(n);
+}
+
+static inline u32 cpu_to_fs32(struct super_block *sb, u32 n)
+{
+	if (sb->sv_bytesex == BYTESEX_PDP)
+		return PDP_swab(n);
+	else if (sb->sv_bytesex == BYTESEX_LE)
+		return cpu_to_le32(n);
+	else
+		return cpu_to_be32(n);
+}
+
+static inline u32 fs32_add(struct super_block *sb, u32 *n, int d)
+{
+	if (sb->sv_bytesex == BYTESEX_PDP)
+		return *n = PDP_swab(PDP_swab(*n)+d);
+	else if (sb->sv_bytesex == BYTESEX_LE)
+		return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+	else
+		return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+}
+
+static inline u16 fs16_to_cpu(struct super_block *sb, u16 n)
+{
+	if (sb->sv_bytesex != BYTESEX_BE)
+		return le16_to_cpu(n);
+	else
+		return be16_to_cpu(n);
+}
+
+static inline u16 cpu_to_fs16(struct super_block *sb, u16 n)
+{
+	if (sb->sv_bytesex != BYTESEX_BE)
+		return cpu_to_le16(n);
+	else
+		return cpu_to_be16(n);
+}
+
+static inline u16 fs16_add(struct super_block *sb, u16 *n, int d)
+{
+	if (sb->sv_bytesex != BYTESEX_BE)
+		return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+	else
+		return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+}
 
 #endif /* __KERNEL__ */
 
 #endif
-
diff -urN linux-2.4.6-pre8/include/linux/sysv_fs_i.h linux/include/linux/sysv_fs_i.h
--- linux-2.4.6-pre8/include/linux/sysv_fs_i.h	Sun Sep 13 10:27:07 1998
+++ linux/include/linux/sysv_fs_i.h	Mon Dec  3 22:50:39 2001
@@ -2,7 +2,7 @@
 #define _SYSV_FS_I
 
 /*
- * SystemV/Coherent FS inode data in memory
+ * SystemV/V7/Coherent FS inode data in memory
  */
 struct sysv_inode_info {
 	u32 i_data[10+1+1+1];	/* zone numbers: max. 10 data blocks,
diff -urN linux-2.4.6-pre8/include/linux/sysv_fs_sb.h linux/include/linux/sysv_fs_sb.h
--- linux-2.4.6-pre8/include/linux/sysv_fs_sb.h	Sun Sep 13 10:27:07 1998
+++ linux/include/linux/sysv_fs_sb.h	Mon Dec  3 22:50:39 2001
@@ -2,8 +2,8 @@
 #define _SYSV_FS_SB
 
 /*
- * SystemV/Coherent super-block data in memory
- * The SystemV/Coherent superblock contains dynamic data (it gets modified
+ * SystemV/V7/Coherent super-block data in memory
+ * The SystemV/V7/Coherent superblock contains dynamic data (it gets modified
  * while the system is running). This is in contrast to the Minix and Berkeley
  * filesystems (where the superblock is never modified). This affects the
  * sync() operation: we must keep the superblock in a disk buffer and use this
@@ -12,12 +12,7 @@
 
 struct sysv_sb_info {
 	int	       s_type;		/* file system type: FSTYPE_{XENIX|SYSV|COH} */
-	unsigned int   s_block_size;	/* zone size, = 512 or = 1024 */
-	unsigned int   s_block_size_1;	/* block_size - 1 */
-	unsigned int   s_block_size_bits;	/* log2(block_size) */
-	unsigned int   s_block_size_inc_bits;	/* log2(block_size/BLOCK_SIZE) if >0 */
-	unsigned int   s_block_size_dec_bits;	/* log2(BLOCK_SIZE/block_size) if >0 */
-	char	       s_convert;	/* flag whether byte ordering requires conversion */
+	char	       s_bytesex;	/* bytesex (le/be/pdp) */
 	char	       s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */
 	char	       s_truncate;	/* if 1: names > SYSV_NAMELEN chars are truncated */
 					/* if 0: they are disallowed (ENAMETOOLONG) */
@@ -26,19 +21,8 @@
 	unsigned int   s_inodes_per_block_1;	/* inodes_per_block - 1 */
 	unsigned int   s_inodes_per_block_bits;	/* log2(inodes_per_block) */
 	unsigned int   s_ind_per_block;		/* number of indirections per block */
-	unsigned int   s_ind_per_block_1;	/* ind_per_block - 1 */
 	unsigned int   s_ind_per_block_bits;	/* log2(ind_per_block) */
 	unsigned int   s_ind_per_block_2;	/* ind_per_block ^ 2 */
-	unsigned int   s_ind_per_block_2_1;	/* ind_per_block ^ 2 - 1 */
-	unsigned int   s_ind_per_block_2_bits;	/* log2(ind_per_block^2) */
-	unsigned int   s_ind_per_block_3;	/* ind_per_block ^ 3 */
-	unsigned int   s_ind_per_block_block_size_1;	/* ind_per_block*block_size - 1 */
-	unsigned int   s_ind_per_block_block_size_bits;	/* log2(ind_per_block*block_size) */
-	unsigned int   s_ind_per_block_2_block_size_1;	/* ind_per_block^2 * block_size - 1 */
-	unsigned int   s_ind_per_block_2_block_size_bits; /* log2(ind_per_block^2 * block_size) */
-	unsigned int   s_ind0_size;		/* 10 * block_size */
-	unsigned int   s_ind1_size;		/* (10 + ipb) * block_size */
-	unsigned int   s_ind2_size;		/* (10 + ipb + ipb^2) * block_size */
 	unsigned int   s_toobig_block;		/* 10 + ipb + ipb^2 + ipb^3 */
 	unsigned int   s_block_base;	/* physical block number of block 0 */
 	unsigned short s_fic_size;	/* free inode cache size, NICINOD */
@@ -53,9 +37,9 @@
 	u16            *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
         u16            *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
 	u16            *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
-	u16            *s_sb_flc_count;	/* pointer to s_sbd->s_nfree */
-	u32	       *s_sb_flc_blocks; /* pointer to s_sbd->s_free */
-	u32            *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */
+	u16            *s_bcache_count;	/* pointer to s_sbd->s_nfree */
+	u32	       *s_bcache;	/* pointer to s_sbd->s_free */
+	u32            *s_free_blocks;	/* pointer to s_sbd->s_tfree */
 	u32            *s_sb_time;	/* pointer to s_sbd->s_time */
 	u32            *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
 	/* We keep those superblock entities that don't change here;
@@ -65,17 +49,13 @@
 	u32            s_ninodes;	/* total number of inodes */
 	u32            s_ndatazones;	/* total number of data zones */
 	u32            s_nzones;	/* same as s_sbd->s_fsize */
+	u16	       s_namelen;       /* max length of dir entry */
 };
-/* The fields s_ind_per_block_2_1, s_toobig_block are currently unused. */
+/* The field s_toobig_block is currently unused. */
 
 /* sv_ == u.sysv_sb.s_ */
 #define sv_type					u.sysv_sb.s_type
-#define sv_block_size				u.sysv_sb.s_block_size
-#define sv_block_size_1				u.sysv_sb.s_block_size_1
-#define sv_block_size_bits			u.sysv_sb.s_block_size_bits
-#define sv_block_size_inc_bits			u.sysv_sb.s_block_size_inc_bits
-#define sv_block_size_dec_bits			u.sysv_sb.s_block_size_dec_bits
-#define sv_convert				u.sysv_sb.s_convert
+#define sv_bytesex				u.sysv_sb.s_bytesex
 #define sv_kludge_symlinks			u.sysv_sb.s_kludge_symlinks
 #define sv_truncate				u.sysv_sb.s_truncate
 #define sv_link_max				u.sysv_sb.s_link_max
@@ -83,19 +63,8 @@
 #define sv_inodes_per_block_1			u.sysv_sb.s_inodes_per_block_1
 #define sv_inodes_per_block_bits		u.sysv_sb.s_inodes_per_block_bits
 #define sv_ind_per_block			u.sysv_sb.s_ind_per_block
-#define sv_ind_per_block_1			u.sysv_sb.s_ind_per_block_1
 #define sv_ind_per_block_bits			u.sysv_sb.s_ind_per_block_bits
 #define sv_ind_per_block_2			u.sysv_sb.s_ind_per_block_2
-#define sv_ind_per_block_2_1			u.sysv_sb.s_ind_per_block_2_1
-#define sv_ind_per_block_2_bits			u.sysv_sb.s_ind_per_block_2_bits
-#define sv_ind_per_block_3			u.sysv_sb.s_ind_per_block_3
-#define sv_ind_per_block_block_size_1		u.sysv_sb.s_ind_per_block_block_size_1
-#define sv_ind_per_block_block_size_bits	u.sysv_sb.s_ind_per_block_block_size_bits
-#define sv_ind_per_block_2_block_size_1		u.sysv_sb.s_ind_per_block_2_block_size_1
-#define sv_ind_per_block_2_block_size_bits	u.sysv_sb.s_ind_per_block_2_block_size_bits
-#define sv_ind0_size				u.sysv_sb.s_ind0_size
-#define sv_ind1_size				u.sysv_sb.s_ind1_size
-#define sv_ind2_size				u.sysv_sb.s_ind2_size
 #define sv_toobig_block				u.sysv_sb.s_toobig_block
 #define sv_block_base				u.sysv_sb.s_block_base
 #define sv_fic_size				u.sysv_sb.s_fic_size
@@ -107,9 +76,9 @@
 #define sv_sb_fic_count				u.sysv_sb.s_sb_fic_count
 #define sv_sb_fic_inodes			u.sysv_sb.s_sb_fic_inodes
 #define sv_sb_total_free_inodes			u.sysv_sb.s_sb_total_free_inodes
-#define sv_sb_flc_count				u.sysv_sb.s_sb_flc_count
-#define sv_sb_flc_blocks			u.sysv_sb.s_sb_flc_blocks
-#define sv_sb_total_free_blocks			u.sysv_sb.s_sb_total_free_blocks
+#define sv_bcache_count				u.sysv_sb.s_bcache_count
+#define sv_bcache				u.sysv_sb.s_bcache
+#define sv_free_blocks				u.sysv_sb.s_free_blocks
 #define sv_sb_time				u.sysv_sb.s_sb_time
 #define sv_sb_state				u.sysv_sb.s_sb_state
 #define sv_firstinodezone			u.sysv_sb.s_firstinodezone
@@ -117,6 +86,6 @@
 #define sv_ninodes				u.sysv_sb.s_ninodes
 #define sv_ndatazones				u.sysv_sb.s_ndatazones
 #define sv_nzones				u.sysv_sb.s_nzones
+#define sv_namelen                              u.sysv_sb.s_namelen
 
 #endif
-
diff -urN linux-2.4.6-pre8/include/linux/udf_fs.h linux/include/linux/udf_fs.h
--- linux-2.4.6-pre8/include/linux/udf_fs.h	Mon Dec  3 22:50:28 2001
+++ linux/include/linux/udf_fs.h	Mon Dec  3 22:50:39 2001
@@ -37,8 +37,8 @@
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS	8
 
-#define UDFFS_DATE			"2001/06/06"
-#define UDFFS_VERSION			"0.9.4"
+#define UDFFS_DATE			"2001/06/13"
+#define UDFFS_VERSION			"0.9.4.1"
 
 #if !defined(UDFFS_RW)
 
diff -urN linux-2.4.6-pre8/include/linux/udf_fs_i.h linux/include/linux/udf_fs_i.h
--- linux-2.4.6-pre8/include/linux/udf_fs_i.h	Mon Dec  3 22:50:28 2001
+++ linux/include/linux/udf_fs_i.h	Mon Dec  3 22:50:39 2001
@@ -30,9 +30,10 @@
 
 struct udf_inode_info
 {
-	long i_uatime;
 	long i_umtime;
 	long i_uctime;
+	long i_crtime;
+	long i_ucrtime;
 	/* Physical address of inode */
 	lb_addr i_location;
 	__u64 i_unique;
diff -urN linux-2.4.6-pre8/include/linux/udf_udf.h linux/include/linux/udf_udf.h
--- linux-2.4.6-pre8/include/linux/udf_udf.h	Mon Dec  3 22:50:28 2001
+++ linux/include/linux/udf_udf.h	Mon Dec  3 22:50:39 2001
@@ -162,6 +162,10 @@
 	Uint32  vatEntry[0];
 };
 
+/* ----------- 2.01 ------------- */
+/* UDF 2.01 6.11 */
+#define FILE_TYPE_REALTIME	0xf9U
+
 /* Sparing maps, see UDF 1.5 2.2.11 */
 typedef struct {
 	Uint32  origLocation;
diff -urN linux-2.4.6-pre8/mm/bootmem.c linux/mm/bootmem.c
--- linux-2.4.6-pre8/mm/bootmem.c	Thu May 24 15:20:18 2001
+++ linux/mm/bootmem.c	Mon Dec  3 22:50:39 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/mm/initmem.c
+ *  linux/mm/bootmem.c
  *
  *  Copyright (C) 1999 Ingo Molnar
  *  Discontiguous memory support, Kanoj Sarcar, SGI, Nov 1999
diff -urN linux-2.4.6-pre8/mm/mmap.c linux/mm/mmap.c
--- linux-2.4.6-pre8/mm/mmap.c	Thu May 24 15:20:18 2001
+++ linux/mm/mmap.c	Mon Dec  3 22:50:39 2001
@@ -66,14 +66,6 @@
 	free += nr_swap_pages;
 
 	/*
-	 * This double-counts: the nrpages are both in the page-cache
-	 * and in the swapper space. At the same time, this compensates
-	 * for the swap-space over-allocation (ie "nr_swap_pages" being
-	 * too small. 
-	 */
-	free += swapper_space.nrpages;
-
-	/*
 	 * The code below doesn't account for free space in the inode
 	 * and dentry slab cache, slab cache fragmentation, inodes and
 	 * dentries which will become freeable under VM load, etc.
diff -urN linux-2.4.6-pre8/mm/numa.c linux/mm/numa.c
--- linux-2.4.6-pre8/mm/numa.c	Mon Dec  3 22:50:28 2001
+++ linux/mm/numa.c	Mon Dec  3 22:50:39 2001
@@ -92,7 +92,7 @@
  * This can be refined. Currently, tries to do round robin, instead
  * should do concentratic circle search, starting from current node.
  */
-struct page * _alloc_pages(int gfp_mask, unsigned long order)
+struct page * _alloc_pages(unsigned int gfp_mask, unsigned long order)
 {
 	struct page *ret = 0;
 	pg_data_t *start, *temp;
diff -urN linux-2.4.6-pre8/net/ax25/ax25_ip.c linux/net/ax25/ax25_ip.c
--- linux-2.4.6-pre8/net/ax25/ax25_ip.c	Fri Dec 29 14:35:47 2000
+++ linux/net/ax25/ax25_ip.c	Mon Dec  3 22:50:39 2001
@@ -160,7 +160,7 @@
 			dst_c = *dst;
 
 			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
-			skb->nh.raw = skb->data;
+			ourskb->nh.raw = ourskb->data;
 
 			ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c, 
 &dst_c, route->digipeat, dev);
diff -urN linux-2.4.6-pre8/net/ipx/af_spx.c linux/net/ipx/af_spx.c
--- linux-2.4.6-pre8/net/ipx/af_spx.c	Mon Dec  3 22:50:29 2001
+++ linux/net/ipx/af_spx.c	Mon Dec  3 22:50:39 2001
@@ -398,7 +398,7 @@
 			pdata->retransmit.expires = jiffies + spx_calc_rtt(0);
 			add_timer(&pdata->retransmit);
 
-			skb2 = skb_clone(skb, GFP_NOFS);	/* Why? Why not GFP_KERNEL? */
+			skb2 = skb_clone(skb, GFP_NOIO);
 	                if(skb2 == NULL)
         	                return -ENOBUFS;
         	        skb_queue_tail(&pdata->retransmit_queue, skb2);
diff -urN linux-2.4.6-pre8/scripts/Configure linux/scripts/Configure
--- linux-2.4.6-pre8/scripts/Configure	Sat Dec 30 18:16:13 2000
+++ linux/scripts/Configure	Mon Dec  3 22:50:39 2001
@@ -92,6 +92,7 @@
 
 			/^#/b
 			/^[^ 	]/q
+			/<file:\\([^>]*\\)>/s//\\1/g
 			p
 		    }" Documentation/Configure.help)
      if [ -z "$text" ]
diff -urN linux-2.4.6-pre8/scripts/Menuconfig linux/scripts/Menuconfig
--- linux-2.4.6-pre8/scripts/Menuconfig	Sat May 19 17:47:55 2001
+++ linux/scripts/Menuconfig	Mon Dec  3 22:50:39 2001
@@ -376,6 +376,7 @@
                         /^#/b
                         /^[^ 	]/q
                         s/^  //
+			/<file:\\([^>]*\\)>/s//\\1/g
                         p
                     }" Documentation/Configure.help)
 
diff -urN linux-2.4.6-pre8/scripts/header.tk linux/scripts/header.tk
--- linux-2.4.6-pre8/scripts/header.tk	Mon Jun 19 13:45:52 2000
+++ linux/scripts/header.tk	Mon Dec  3 22:50:39 2001
@@ -466,6 +466,7 @@
 				/^#/b
 				/^\[^ 	\]/q
 				s/^  //
+				/<file:\\(\[^>\]*\\)>/s//\\1/g
 				p
 			}
 			" Documentation/Configure.help]
diff -urN linux-2.4.6-pre8/scripts/kernel-doc linux/scripts/kernel-doc
--- linux-2.4.6-pre8/scripts/kernel-doc	Mon Dec  3 22:50:29 2001
+++ linux/scripts/kernel-doc	Mon Dec  3 22:50:39 2001
@@ -18,6 +18,11 @@
 # 		Functions prototyped as foo(void) same as foo()
 # 		Stop eval'ing where we don't need to.
 # -- huggie@earth.li
+
+# 27/06/2001 -  Allowed whitespace after initial "/**" and
+#               allowed comments before function declarations.
+# -- Christian Kreibich <ck@whoop.org>
+
 # Still to do:
 # 	- add perldoc documentation
 # 	- Look more closely at some of the scarier bits :)
@@ -825,7 +830,7 @@
 
 $doc_special = "\@\%\$\&";
 
-$doc_start = "^/\\*\\*\$";
+$doc_start = "^/\\*\\*\\s*\$"; # Allow whitespace at end of comment start.
 $doc_end = "\\*/";
 $doc_com = "\\s*\\*\\s*";
 $doc_func = $doc_com."(\\w+):?";
@@ -975,7 +980,7 @@
 	    elsif (/([^\{]*)/) {
 		$prototype .= $1;
 	    }
-	    if (/\{/ || /\#/) { # added for #define AK
+	    if (/\{/ || /\#/ || /;/) { # added for #define AK, ';' added for declarations.
 		$prototype =~ s@/\*.*?\*/@@gos;	# strip comments.
 		$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 		$prototype =~ s@^ +@@gos; # strip leading spaces
